const BASE_58_CHARS: &str = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
const VERSION: &str = "01";
const ENCODED_LENGTH: usize = 22;
fn base58_encode(n: u128) -> String {
let base = BASE_58_CHARS.len() as u128;
let mut result: Vec<char> = vec![BASE_58_CHARS.chars().next().unwrap(); ENCODED_LENGTH];
let mut i = ENCODED_LENGTH as i32 - 1;
let mut value = n;
while value > 0 {
let rem = (value % base) as usize;
result[i as usize] = BASE_58_CHARS.chars().nth(rem).unwrap();
value = value / base;
i -= 1;
}
result.into_iter().collect()
}
fn uuid_to_u128(uuid: &str) -> Result<u128, String> {
let hex = uuid.replace('-', "");
if hex.len() != 32 {
return Err(format!("Invalid UUID hex length: {}", hex.len()));
}
u128::from_str_radix(&hex, 16).map_err(|e| e.to_string())
}
pub fn to_tagged_id(tag: &str, uuid: &str) -> Result<String, String> {
let n = uuid_to_u128(uuid)?;
Ok(format!("{}_{}{}", tag, VERSION, base58_encode(n)))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_base58_encode() {
let encoded = base58_encode(0);
assert_eq!(encoded.len(), ENCODED_LENGTH);
}
#[test]
fn test_tagged_id() {
let result = to_tagged_id("user", "00000000-0000-0000-0000-000000000001");
assert!(result.is_ok());
let id = result.unwrap();
assert!(id.starts_with("user_01"));
}
}