simid/
lib.rs

1//! This crate defines a uniform resource name namespace for UUIDs
2//! (Universally Unique IDentifier), also known as GUIDs (Globally
3//! Unique Identifier). A UUID is 128 bits long, and can guarantee
4//! uniqueness across space and time.
5//!
6//! ```toml
7//! [dependencies]
8//! uuid = { version = "0.1.0", features = ["random"] }
9//! ```
10//!
11//! ```rust
12//! use simid::v4;
13//!
14//! fn main() {
15//!     println!("{}", v4!());
16//! }
17//! ```
18
19#![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
29/// Is 100-ns ticks between UNIX and UTC epochs.
30pub const UTC_EPOCH: u64 = 0x1B21_DD21_3814_000;
31
32/// The UUID format is 16 octets.
33#[derive(Debug)]
34pub struct Layout {
35    /// The low field of the Timestamp.
36    pub field_low: u32,
37    /// The mid field of the Timestamp.
38    pub field_mid: u16,
39    /// The high field of the Timestamp multiplexed with the version number.
40    pub field_high_and_version: u16,
41    /// The high field of the ClockSeq multiplexed with the variant.
42    pub clock_seq_high_and_reserved: u8,
43    /// The low field of the ClockSeq.
44    pub clock_seq_low: u8,
45    /// IEEE 802 MAC address.
46    pub node: [u8; 6],
47}
48
49impl Layout {
50    /// Returns the five field values of the UUID in big-endian order.
51    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    /// Returns a byte slice of this UUID content.
67    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    /// Get the version of the current generated UUID.
89    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    /// Get the variant field of the current generated UUID.
101    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    /// Get timestamp where the UUID generated in.
112    pub fn get_time(&self) -> u64 {
113        self.field_low as u64
114    }
115
116    /// Get the MAC-address where the UUID generated with.
117    pub fn get_mac(&self) -> Node {
118        Node(self.node)
119    }
120}
121
122/// Domain is security-domain-relative name.
123#[derive(Debug, Copy, Clone)]
124pub enum Domain {
125    PERSON = 0,
126    GROUP,
127    ORG,
128}
129
130/// Variant is a type field determines the layout of the UUID.
131#[derive(Debug, Eq, PartialEq)]
132pub enum Variant {
133    /// Reserved, NCS backward compatibility.
134    NCS = 0,
135    /// The variant specified in `rfc4122` document.
136    RFC,
137    /// Reserved, Microsoft Corporation backward compatibility.
138    MS,
139    /// Reserved for future definition.
140    FUT,
141}
142
143/// Version represents the type of UUID, and is in the most significant 4 bits of the Timestamp.
144#[derive(Debug, Eq, PartialEq)]
145pub enum Version {
146    /// The time-based version specified in `rfc4122` document.
147    TIME = 1,
148    /// DCE Security version, with embedded POSIX UIDs.
149    DCE,
150    /// The name-based version specified in `rfc4122` document that uses MD5 hashing.
151    MD5,
152    /// The randomly or pseudo-randomly generated version specified in `rfc4122` document.
153    RAND,
154    /// The name-based version specified in `rfc4122`document that uses SHA-1 hashing.
155    SHA1,
156}
157
158/// Represented by Coordinated Universal Time (UTC)
159/// as a count of 100-ns intervals from the system-time.
160#[derive(Debug, Eq, PartialEq)]
161pub struct Timestamp(u64);
162
163impl Timestamp {
164    /// Generate UTC timestamp.
165    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/// Is a 128-bit number used to identify information in computer systems.
178#[derive(Debug, Eq, PartialEq, Copy, Clone)]
179pub struct UUID([u8; 16]);
180
181impl UUID {
182    /// A special case for UUID.
183    pub const NIL: Self = UUID([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
184
185    /// UUID namespace for domain name system (DNS).
186    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    /// UUID namespace for ISO object identifiers (OIDs).
192    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    /// UUID namespace for uniform resource locators (URLs).
198    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    /// UUID namespace for X.500 distinguished names (DNs).
204    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
210/// NOTE: This is not a valid UUID format.
211impl 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
298/// Used to avoid duplicates that could arise when the clock is
299/// set backwards in time.
300pub struct ClockSeq(u16);
301
302impl ClockSeq {
303    /// Generate new atomic random value.
304    pub fn new(r: u16) -> u16 {
305        atomic::AtomicU16::new(r).fetch_add(1, atomic::Ordering::AcqRel)
306    }
307}
308
309/// The clock sequence is used to help avoid duplicates that could arise
310/// when the clock is set backwards in time or if the node ID changes.
311pub 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}