while n > 0 { symbol.push( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" .chars() .nth(((n - 1) % 26) as usize) .unwrap(), ); n = (n - 1) / 26; } for c in symbol.chars().rev() { write!(f, "{c}")?; } Ok(()) } } impl FromStr for Rune { type Err = crate::Error; fn from_str(s: &str) -> crate::Result { let mut x = 0u128; for (i, c) in s.chars().enumerate() { if i > 0 { x += 1; } x *= 26; match c { 'A'..='Z' => { x = x .checked_add(c as u128 - 'A' as u128) .ok_or_else(|| anyhow!("out of range"))?; } _ => bail!("invalid character in rune name: {c}"), } } Ok(Rune(x)) } } #[cfg(test)] mod tests { use super::*; #[test] fn round_trip() { fn case(n: u128, s: &str) { assert_eq!(Rune(n).to_string(), s); assert_eq!(s.parse::().unwrap(), Rune(n)); } case(0, "A"); case(1, "B"); case(2, "C");