1 use rand::Rng; 2 use std::fmt; 3 use std::time::SystemTime; 4 5 #[derive(Debug, Clone, Eq, PartialEq, Hash, Default, Copy)] 6 pub struct Uuid { 7 value: [char; 16], 8 random_count: RandomDigitCount, 9 } 10 11 #[derive(Debug, Clone, Eq, PartialEq, Hash, Default, Copy)] 12 pub enum RandomDigitCount { 13 #[default] 14 Zero = 0, 15 One = 1, 16 Two = 2, 17 Three = 3, 18 Four = 4, 19 Five = 5, 20 Six = 6, 21 } 22 23 fn u8_to_enum(digit: u8) -> RandomDigitCount { 24 match digit { 25 0 => RandomDigitCount::Zero, 26 1 => RandomDigitCount::One, 27 2 => RandomDigitCount::Two, 28 3 => RandomDigitCount::Three, 29 4 => RandomDigitCount::Four, 30 5 => RandomDigitCount::Five, 31 6 => RandomDigitCount::Six, 32 _ => RandomDigitCount::Zero, 33 } 34 } 35 36 impl Uuid { 37 pub fn from_str2(uuid: &String) -> Option<Uuid> { 38 let length = uuid.len(); 39 if !(10..=16).contains(&length) { 40 return None; 41 } 42 43 let random_count = u8_to_enum(length as u8 - 10); 44 let mut value: [char; 16] = ['\0'; 16]; 45 for (i, c) in uuid.chars().enumerate() { 46 value[i] = c; 47 } 48 49 Some(Uuid { 50 value, 51 random_count, 52 }) 53 } 54 pub fn new(random_digit_count: RandomDigitCount) -> Self { 55 let duration = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH); 56 let seconds = match duration { 57 Ok(result) => result.as_secs(), 58 _ => 0, 59 }; 60 61 let seconds_str = seconds.to_string(); 62 let mut value: [char; 16] = ['\0'; 16]; 63 for (i, c) in seconds_str.chars().enumerate() { 64 if i >= 10 { 65 break; 66 } 67 value[i] = c; 68 } 69 70 let mut rng = rand::thread_rng(); 71 let random_size = random_digit_count as usize; 72 for i in 0..random_size { 73 let number = rng.gen_range(0..=9); 74 if let Some(c) = std::char::from_digit(number, 10) { 75 value[10 + i] = c; 76 } 77 } 78 79 // let count = random_digit_count as u8; 80 // let mut rng = rand::thread_rng(); 81 // let random_digit_str: String = (0..count) 82 // .map(|_| rng.gen_range(0..=9).to_string()) 83 // .collect(); 84 85 // let seconds_str = format!("{}", seconds); 86 // let random_num_str = if count > 0 { 87 // format!("-{}", random_digit_str) 88 // } else { 89 // String::from("") 90 // }; 91 92 Self { 93 value, 94 random_count: random_digit_count, 95 } 96 } 97 } 98 99 impl fmt::Display for Uuid { 100 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 101 let val: String = self 102 .value 103 .iter() 104 .take(10 + self.random_count as usize) 105 .collect(); 106 write!(f, "{}", &val) 107 } 108 } 109 110 #[cfg(test)] 111 mod tests { 112 use super::Uuid; 113 114 #[test] 115 fn test_uuid() { 116 let id = Uuid::new(super::RandomDigitCount::Four); 117 118 let s = id.to_string(); 119 120 println!("{s}"); 121 122 if let Some(u) = Uuid::from_str2(&s) { 123 println!("{:?}", u.to_string()); 124 } 125 } 126 } 127