1#![doc(html_root_url = "https://docs.rs/uuid-rs")]
20
21mod name;
22mod rand;
23mod time;
24
25use core::fmt;
26use core::sync::atomic;
27use std::time::SystemTime;
28
29pub const UTC_EPOCH: u64 = 0x1B21_DD21_3814_000;
31
32#[derive(Debug)]
34pub struct Layout {
35    pub field_low: u32,
37    pub field_mid: u16,
39    pub field_high_and_version: u16,
41    pub clock_seq_high_and_reserved: u8,
43    pub clock_seq_low: u8,
45    pub node: [u8; 6],
47}
48
49impl Layout {
50    pub fn as_fields(&self) -> (u32, u16, u16, u16, u64) {
52        (
53            self.field_low,
54            self.field_mid,
55            self.field_high_and_version,
56            ((self.clock_seq_high_and_reserved as u16) << 8) | self.clock_seq_low as u16,
57            (self.node[0] as u64) << 40
58                | (self.node[1] as u64) << 32
59                | (self.node[2] as u64) << 24
60                | (self.node[3] as u64) << 16
61                | (self.node[4] as u64) << 8
62                | (self.node[5] as u64),
63        )
64    }
65
66    pub fn as_bytes(&self) -> UUID {
68        UUID([
69            self.field_low.to_be_bytes()[0],
70            self.field_low.to_be_bytes()[1],
71            self.field_low.to_be_bytes()[2],
72            self.field_low.to_be_bytes()[3],
73            self.field_mid.to_be_bytes()[0],
74            self.field_mid.to_be_bytes()[1],
75            self.field_high_and_version.to_be_bytes()[0],
76            self.field_high_and_version.to_be_bytes()[1],
77            self.clock_seq_high_and_reserved,
78            self.clock_seq_low,
79            self.node[0],
80            self.node[1],
81            self.node[2],
82            self.node[3],
83            self.node[4],
84            self.node[5],
85        ])
86    }
87
88    pub fn get_version(&self) -> Option<Version> {
90        match (self.field_high_and_version >> 12) & 0xf {
91            0x01 => Some(Version::TIME),
92            0x02 => Some(Version::DCE),
93            0x03 => Some(Version::MD5),
94            0x04 => Some(Version::RAND),
95            0x05 => Some(Version::SHA1),
96            _ => None,
97        }
98    }
99
100    pub fn get_variant(&self) -> Option<Variant> {
102        match (self.clock_seq_high_and_reserved >> 4) & 0xf {
103            0x00 => Some(Variant::NCS),
104            0x01 => Some(Variant::RFC),
105            0x02 => Some(Variant::MS),
106            0x03 => Some(Variant::FUT),
107            _ => None,
108        }
109    }
110
111    pub fn get_time(&self) -> u64 {
113        self.field_low as u64
114    }
115
116    pub fn get_mac(&self) -> Node {
118        Node(self.node)
119    }
120}
121
122#[derive(Debug, Copy, Clone)]
124pub enum Domain {
125    PERSON = 0,
126    GROUP,
127    ORG,
128}
129
130#[derive(Debug, Eq, PartialEq)]
132pub enum Variant {
133    NCS = 0,
135    RFC,
137    MS,
139    FUT,
141}
142
143#[derive(Debug, Eq, PartialEq)]
145pub enum Version {
146    TIME = 1,
148    DCE,
150    MD5,
152    RAND,
154    SHA1,
156}
157
158#[derive(Debug, Eq, PartialEq)]
161pub struct Timestamp(u64);
162
163impl Timestamp {
164    pub fn new() -> u64 {
166        let utc = SystemTime::now()
167            .duration_since(SystemTime::UNIX_EPOCH)
168            .unwrap()
169            .checked_add(std::time::Duration::from_nanos(UTC_EPOCH))
170            .unwrap()
171            .as_nanos();
172
173        (utc & 0xffff_ffff_ffff_ffff) as u64
174    }
175}
176
177#[derive(Debug, Eq, PartialEq, Copy, Clone)]
179pub struct UUID([u8; 16]);
180
181impl UUID {
182    pub const NIL: Self = UUID([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
184
185    pub const NAMESPACE_DNS: Self = UUID([
187        0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
188        0xc8,
189    ]);
190
191    pub const NAMESPACE_OID: Self = UUID([
193        0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
194        0xc8,
195    ]);
196
197    pub const NAMESPACE_URL: Self = UUID([
199        0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
200        0xc8,
201    ]);
202
203    pub const NAMESPACE_X500: Self = UUID([
205        0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
206        0xc8,
207    ]);
208}
209
210impl fmt::Display for UUID {
212    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
213        write!(
214            fmt,
215            "{:02x}{:02x}{:02x}{:02x}
216            {:02x}{:02x}
217            {:02x}{:02x}
218            {:02x}{:02x}
219            {:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
220            self.0[0],
221            self.0[1],
222            self.0[2],
223            self.0[3],
224            self.0[4],
225            self.0[5],
226            self.0[6],
227            self.0[7],
228            self.0[8],
229            self.0[9],
230            self.0[10],
231            self.0[11],
232            self.0[12],
233            self.0[13],
234            self.0[14],
235            self.0[15],
236        )
237    }
238}
239
240impl fmt::LowerHex for UUID {
241    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
242        write!(
243            fmt,
244            "{:02x}{:02x}{:02x}{:02x}
245            -{:02x}{:02x}
246            -{:02x}{:02x}
247            -{:02x}{:02x}
248            -{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
249            self.0[0],
250            self.0[1],
251            self.0[2],
252            self.0[3],
253            self.0[4],
254            self.0[5],
255            self.0[6],
256            self.0[7],
257            self.0[8],
258            self.0[9],
259            self.0[10],
260            self.0[11],
261            self.0[12],
262            self.0[13],
263            self.0[14],
264            self.0[15],
265        )
266    }
267}
268
269impl fmt::UpperExp for UUID {
270    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
271        write!(
272            fmt,
273            "{:02X}{:02X}{:02X}{:02X}
274            -{:02X}{:02X}
275            -{:02X}{:02X}
276            -{:02X}{:02X}
277            -{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}",
278            self.0[0],
279            self.0[1],
280            self.0[2],
281            self.0[3],
282            self.0[4],
283            self.0[5],
284            self.0[6],
285            self.0[7],
286            self.0[8],
287            self.0[9],
288            self.0[10],
289            self.0[11],
290            self.0[12],
291            self.0[13],
292            self.0[14],
293            self.0[15],
294        )
295    }
296}
297
298pub struct ClockSeq(u16);
301
302impl ClockSeq {
303    pub fn new(r: u16) -> u16 {
305        atomic::AtomicU16::new(r).fetch_add(1, atomic::Ordering::AcqRel)
306    }
307}
308
309pub struct Node([u8; 6]);
312
313impl fmt::Display for Node {
314    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
315        write!(
316            fmt,
317            "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
318            self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5],
319        )
320    }
321}
322
323impl fmt::LowerHex for Node {
324    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
325        write!(
326            fmt,
327            "{:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}",
328            self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5],
329        )
330    }
331}
332
333impl fmt::UpperHex for Node {
334    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
335        write!(
336            fmt,
337            "{:02X}-{:02X}-{:02X}-{:02X}-{:02X}-{:02X}",
338            self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5],
339        )
340    }
341}