use crate::generator;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct BeakId(u64);
impl From<u64> for BeakId {
fn from(v: u64) -> Self {
BeakId(v)
}
}
impl BeakId {
pub fn new(v: u64) -> Self {
BeakId(v)
}
pub fn from_base62(s: &str) -> Result<Self, crate::Error> {
const LEN: usize = 11;
if s.len() != LEN {
return Err(crate::Error::InvalidBase62);
}
let mut n = 0u64;
for &byte in s.as_bytes() {
let digit = match byte {
b'0'..=b'9' => (byte - b'0') as u64,
b'A'..=b'Z' => (byte - b'A' + 10) as u64,
b'a'..=b'z' => (byte - b'a' + 36) as u64,
_ => return Err(crate::Error::InvalidBase62),
};
n = n
.checked_mul(62)
.and_then(|n| n.checked_add(digit))
.ok_or(crate::Error::InvalidBase62)?;
}
Ok(BeakId(n))
}
pub fn base62(&self) -> String {
const ALPHABET: &[u8; 62] =
b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const LEN: usize = 11;
let mut buf = [b'0'; LEN];
let mut n = self.0;
for i in (0..LEN).rev() {
buf[i] = ALPHABET[(n % 62) as usize];
n /= 62;
}
unsafe { String::from_utf8_unchecked(buf.to_vec()) }
}
pub fn timestamp(&self) -> u64 {
(self.0 >> generator::TIMESTAMP_SHIFT) * 100
}
}