1#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
2pub struct Uuid(String);
3
4impl Uuid {
5 pub fn new_v4() -> Self {
7 let mut bytes = [0u8; 16];
8 crate::rand::fill_bytes(&mut bytes);
9 bytes[6] = (bytes[6] & 0x0f) | 0x40; bytes[8] = (bytes[8] & 0x3f) | 0x80; let s = format!(
13 "{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
14 bytes[0], bytes[1], bytes[2], bytes[3],
15 bytes[4], bytes[5],
16 bytes[6], bytes[7],
17 bytes[8], bytes[9],
18 bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]
19 );
20 Self(s)
21 }
22
23 pub fn parse_str(s: &str) -> Result<Self, &'static str> {
25 if s.len() != 36 {
26 return Err("Invalid length");
27 }
28 let bytes = s.as_bytes();
29 for (i, &b) in bytes.iter().enumerate() {
30 if i == 8 || i == 13 || i == 18 || i == 23 {
31 if b != b'-' {
32 return Err("Invalid separator");
33 }
34 } else {
35 if !b.is_ascii_hexdigit() {
36 return Err("Invalid character");
37 }
38 }
39 }
40 Ok(Self(s.to_string()))
41 }
42}
43
44impl std::fmt::Display for Uuid {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 write!(f, "{}", self.0)
47 }
48}