Skip to main content

uuid/
uuid.rs

1mod fmt;
2mod parse;
3mod serde;
4mod v4;
5mod v7;
6mod v8;
7// _mod error;
8
9#[derive(Clone, Copy, Debug, PartialEq, thiserror::Error)]
10pub enum Error {
11    #[error("uuid: Size is not valid")]
12    InvalidSize,
13    #[error("uuid: Invalid uuid")]
14    InvalidUuid,
15}
16
17#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
18pub struct Uuid([u8; 16]);
19
20#[derive(Clone, Copy, Debug, PartialEq)]
21#[non_exhaustive]
22#[repr(u8)]
23pub enum Version {
24    /// The "nil" (all zeros) UUID.
25    Nil = 0u8,
26    /// Version 4: Random.
27    V4 = 4,
28    /// Version 7: Timestamp and random.
29    V7 = 7,
30    /// Version 8: Custom
31    V8 = 8,
32    /// The "max" (all ones) UUID.
33    Max = 0xff,
34}
35
36impl Uuid {
37    /// The 'nil UUID' (all zeros).
38    ///
39    /// The nil UUID is a special form of UUID that is specified to have all
40    /// 128 bits set to zero.
41    ///
42    /// # References
43    ///
44    /// * [Nil UUID in RFC4122](https://tools.ietf.org/html/rfc4122.html#section-4.1.7)
45    ///
46    /// # Examples
47    ///
48    /// Basic usage:
49    ///
50    /// ```
51    /// # use uuid::Uuid;
52    /// let uuid = Uuid::nil();
53    ///
54    /// assert_eq!(
55    ///     "00000000-0000-0000-0000-000000000000",
56    ///     uuid.hyphenated().to_string(),
57    /// );
58    /// ```
59    pub const fn nil() -> Uuid {
60        Uuid([0; 16])
61    }
62
63    pub const fn get_version(&self) -> Option<Version> {
64        match self.0[6] >> 4 {
65            0 if self.is_nil() => Some(Version::Nil),
66            4 => Some(Version::V4),
67            7 => Some(Version::V7),
68            0xf => Some(Version::Max),
69            _ => None,
70        }
71    }
72
73    pub const fn is_nil(&self) -> bool {
74        self.as_u128() == u128::MIN
75    }
76
77    pub const fn as_u128(&self) -> u128 {
78        u128::from_be_bytes(self.0)
79    }
80
81    pub const fn from_u128(v: u128) -> Self {
82        Uuid::from_bytes([
83            (v >> 120) as u8,
84            (v >> 112) as u8,
85            (v >> 104) as u8,
86            (v >> 96) as u8,
87            (v >> 88) as u8,
88            (v >> 80) as u8,
89            (v >> 72) as u8,
90            (v >> 64) as u8,
91            (v >> 56) as u8,
92            (v >> 48) as u8,
93            (v >> 40) as u8,
94            (v >> 32) as u8,
95            (v >> 24) as u8,
96            (v >> 16) as u8,
97            (v >> 8) as u8,
98            v as u8,
99        ])
100    }
101
102    #[inline]
103    pub const fn from_bytes(bytes: [u8; 16]) -> Uuid {
104        Uuid(bytes)
105    }
106
107    pub const fn as_bytes(&self) -> &[u8; 16] {
108        &self.0
109    }
110
111    pub fn from_slice(b: &[u8]) -> Result<Uuid, Error> {
112        if b.len() != 16 {
113            return Err(Error::InvalidSize);
114        }
115
116        let mut bytes = [0; 16];
117        bytes.copy_from_slice(b);
118        return Ok(Uuid(bytes));
119    }
120
121    pub fn parse_str(input: &str) -> Result<Uuid, Error> {
122        Self::try_parse(input.as_bytes())
123            .map(|bytes| Uuid(bytes))
124            .map_err(|_| Error::InvalidUuid)
125    }
126
127    const fn try_parse(input: &[u8]) -> Result<[u8; 16], Error> {
128        match (input.len(), input) {
129            (36, s) => parse::parse_hyphenated(s),
130            // Any other shaped input is immediately invalid
131            _ => Err(Error::InvalidUuid),
132        }
133    }
134}
135
136// The following types and methods are used to mimick the uuid crate so we can override our dependencies
137// with stdx's uuid
138impl Uuid {
139    pub fn hyphenated(&self) -> String {
140        return self.to_string();
141    }
142
143    pub fn as_hyphenated(&self) -> String {
144        return self.to_string();
145    }
146
147    pub fn simple(&self) -> Self {
148        return self.clone();
149    }
150
151    pub fn as_simple(&self) -> Self {
152        return self.clone();
153    }
154}
155
156pub type Bytes = [u8; 16];
157
158#[derive(Clone, Copy, Debug, PartialEq)]
159#[non_exhaustive]
160#[repr(u8)]
161pub enum Variant {
162    /// Reserved by the NCS for backward compatibility.
163    NCS = 0u8,
164    /// As described in the RFC 9562 Specification (default).
165    /// (for backward compatibility it is not yet renamed)
166    RFC4122,
167    /// Reserved by Microsoft for backward compatibility.
168    Microsoft,
169    /// Reserved for future expansion.
170    Future,
171}
172
173// Compatibility layer for the aws-sdk
174pub struct Builder(Uuid);
175
176impl Builder {
177    pub const fn from_random_bytes(random_bytes: Bytes) -> Self {
178        Builder(Uuid::from_bytes(random_bytes))
179            .with_variant(Variant::RFC4122)
180            .with_version(Version::V4)
181    }
182
183    pub const fn into_uuid(self) -> Uuid {
184        self.0
185    }
186
187    pub const fn with_variant(mut self, v: Variant) -> Self {
188        let byte = (self.0).0[8];
189
190        (self.0).0[8] = match v {
191            Variant::NCS => byte & 0x7f,
192            Variant::RFC4122 => (byte & 0x3f) | 0x80,
193            Variant::Microsoft => (byte & 0x1f) | 0xc0,
194            Variant::Future => byte | 0xe0,
195        };
196
197        self
198    }
199
200    pub const fn with_version(mut self, v: Version) -> Self {
201        (self.0).0[6] = ((self.0).0[6] & 0x0f) | ((v as u8) << 4);
202
203        self
204    }
205}