const ITO_S: &str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const N: usize = ITO_S.len();
pub fn s_to_int(s: &str) -> usize {
let mut acc = 0;
let mut pow = 1;
for c in s.chars().rev() {
let idx = ITO_S.find(c).expect("invalid character in s_to_int");
acc += idx * pow;
pow *= N;
}
acc
}
#[allow(dead_code)]
pub fn int_to_s(value: usize) -> String {
if value == 0 {
return ITO_S.chars().next().unwrap().to_string();
}
let mut val = value;
let mut acc = Vec::new();
while val != 0 {
let i = val % N;
let c = ITO_S.chars().nth(i).unwrap();
acc.push(c);
val /= N;
}
acc.iter().rev().collect()
}
#[allow(dead_code)]
fn reverse(s: &str) -> String {
s.chars().rev().collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_base62_roundtrip() {
for i in 0..1000 {
let encoded = int_to_s(i);
let decoded = s_to_int(&encoded);
assert_eq!(i, decoded, "Failed for {}", i);
}
}
#[test]
fn test_known_values() {
assert_eq!(int_to_s(0), "0");
assert_eq!(int_to_s(9), "9");
assert_eq!(int_to_s(10), "A");
assert_eq!(int_to_s(35), "Z");
assert_eq!(int_to_s(36), "a");
assert_eq!(int_to_s(61), "z");
assert_eq!(int_to_s(62), "10");
}
}