uuid_str/
lib.rs

1
2use std::str::FromStr;
3
4/// A wrapper around a UUID string.
5/// It uses a static 36 byte array to store the UUID string.
6/// It allows for Copy and Clone.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub struct UuidStr {
9    bytes: [u8; 36],
10}
11
12impl Default for UuidStr {
13    fn default() -> Self {
14        Self {
15            bytes: *b"00000000-0000-0000-0000-000000000000",
16        }
17    }
18}
19
20impl UuidStr {
21    pub fn new() -> Self {
22        Self::default()
23    }
24
25    pub fn new_v4() -> Self {
26        let uuid = uuid::Uuid::new_v4();
27        Self::from(&uuid)
28    }
29
30    pub fn bytes(&self) -> [u8; 36] {
31        self.bytes
32    }
33}
34
35impl AsRef<str> for UuidStr {
36    fn as_ref(&self) -> &str {
37        std::str::from_utf8(&self.bytes).unwrap()
38    }
39}
40
41impl std::fmt::Display for UuidStr {
42    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43        f.write_str(self.as_ref())
44    }
45}
46
47impl FromStr for UuidStr {
48    type Err = uuid::Error;
49
50    fn from_str(s: &str) -> Result<Self, Self::Err> {
51        let uuid = uuid::Uuid::parse_str(s)?;
52        Ok(Self::from(&uuid))
53    }
54}
55
56impl std::ops::Deref for UuidStr {
57    type Target = str;
58
59    fn deref(&self) -> &Self::Target {
60        self.as_ref()
61    }
62}
63
64impl std::convert::TryFrom<&str> for UuidStr {
65    type Error = uuid::Error;
66
67    fn try_from(s: &str) -> Result<Self, Self::Error> {
68        Self::from_str(s)
69    }
70}
71
72impl std::convert::TryFrom<String> for UuidStr {
73    type Error = uuid::Error;
74
75    fn try_from(s: String) -> Result<Self, Self::Error> {
76        Self::from_str(&s)
77    }
78}
79
80impl AsRef<[u8]> for UuidStr {
81    fn as_ref(&self) -> &[u8] {
82        &self.bytes
83    }
84}
85
86impl From<&uuid::Uuid> for UuidStr {
87    fn from(uuid: &uuid::Uuid) -> Self {
88        let str = uuid.as_hyphenated().to_string().to_ascii_lowercase();
89        let bytes = str.as_bytes();
90        assert_eq!(bytes.len(), 36);
91        let mut uuid_str = Self::default();
92        uuid_str.bytes.copy_from_slice(bytes);
93        uuid_str
94    }
95}
96
97impl From<uuid::Uuid> for UuidStr {
98    fn from(uuid: uuid::Uuid) -> Self {
99        Self::from(&uuid)
100    }
101}
102
103
104#[cfg(test)]
105mod tests {
106    use super::*;
107
108    #[test]
109    fn default() {
110        let default_uuid = UuidStr::default();
111        let default_str: &str = default_uuid.as_ref();
112        assert_eq!(default_str, "00000000-0000-0000-0000-000000000000");
113    }
114
115    #[test]
116    fn v4() {
117        let uuid = UuidStr::new_v4();
118        let bytes: &[u8] = uuid.as_ref();
119        assert_eq!(bytes.len(), 36);
120        let maybe_uuid = uuid::Uuid::parse_str(uuid.as_ref());
121        assert!(maybe_uuid.is_ok());
122    }
123}