1use std::{fmt::Display, str::FromStr};
2
3use rand::random;
4use time::OffsetDateTime;
5
6#[cfg(test)]
7mod tests {
8 use crate::UwuId;
9
10 #[test]
11 fn generate_uwuid() {
12 let uwuid = UwuId::new();
13 let uwuid_parsed: UwuId = format!("{}", uwuid).parse().unwrap();
14 assert_eq!(uwuid, uwuid_parsed);
15 }
16}
17
18static UWUID_HEX_DIGITS: [char; 16] = [
19 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '🥰', '😳', '🥺', '🤗', '😍', ',',
20];
21
22#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
23pub struct UwuId(u128);
24
25impl UwuId {
26 pub fn new() -> Self {
27 Self(
28 (((OffsetDateTime::now_utc().unix_timestamp_nanos() as u128) / 1_000_000_u128) << 80)
29 + (random::<u128>() & 0xffffffffffffffffffff),
30 )
31 }
32 pub fn time(&self) -> Result<OffsetDateTime, time::error::ComponentRange> {
33 OffsetDateTime::from_unix_timestamp_nanos((self.0 >> 80) as i128 * 1_000_000)
34 }
35}
36
37impl Display for UwuId {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 for i in 0..32 {
40 let mask = 0xF << (i * 4);
41 let digit = (self.0 & mask) >> (i * 4);
42 write!(f, "{}", UWUID_HEX_DIGITS[digit as usize])?;
43 }
44 Ok(())
45 }
46}
47
48impl FromStr for UwuId {
49 type Err = std::fmt::Error;
50 fn from_str(s: &str) -> Result<Self, Self::Err> {
51 let mut id = 0_u128;
52 for digit in s.chars().rev() {
53 id <<= 4;
54 id += UWUID_HEX_DIGITS
55 .iter()
56 .position(|e| *e == digit)
57 .ok_or(std::fmt::Error)? as u128;
58 }
59 Ok(Self(id))
60 }
61}