uuid/v1.rs
1//! The implementation for Version 1 UUIDs.
2//!
3//! This module is soft-deprecated. Instead of using the `Context` type re-exported here,
4//! use the one from the crate root.
5
6use crate::{Builder, Uuid};
7
8#[deprecated(note = "use types from the crate root instead")]
9pub use crate::{timestamp::context::Context, Timestamp};
10
11impl Uuid {
12 /// Create a new version 1 UUID using the current system time and node ID.
13 ///
14 /// This method is only available if both the `std` and `rng` features are enabled.
15 ///
16 /// This method is a convenient alternative to [`Uuid::new_v1`] that uses the current system time
17 /// as the source timestamp.
18 ///
19 /// Note that usage of this method requires the `v1`, `std`, and `rng` features of this crate
20 /// to be enabled.
21 #[cfg(all(feature = "std", feature = "rng"))]
22 pub fn now_v1(node_id: &[u8; 6]) -> Self {
23 let ts = Timestamp::now(crate::timestamp::context::shared_context());
24
25 Self::new_v1(ts, node_id)
26 }
27
28 /// Create a new version 1 UUID using the given timestamp and node ID.
29 ///
30 /// Also see [`Uuid::now_v1`] for a convenient way to generate version 1
31 /// UUIDs using the current system time.
32 ///
33 /// When generating [`Timestamp`]s using a [`ClockSequence`], this function
34 /// is only guaranteed to produce unique values if the following conditions
35 /// hold:
36 ///
37 /// 1. The *node ID* is unique for this process,
38 /// 2. The *context* is shared across all threads which are generating version 1
39 /// UUIDs,
40 /// 3. The [`ClockSequence`] implementation reliably returns unique
41 /// clock sequences (this crate provides [`Context`] for this
42 /// purpose. However you can create your own [`ClockSequence`]
43 /// implementation, if [`Context`] does not meet your needs).
44 ///
45 /// Note that usage of this method requires the `v1` feature of this crate
46 /// to be enabled.
47 ///
48 /// # Examples
49 ///
50 /// A UUID can be created from a unix [`Timestamp`] with a
51 /// [`ClockSequence`]. RFC 9562 requires the clock sequence
52 /// is seeded with a random value:
53 ///
54 /// ```
55 /// # use uuid::{Timestamp, Context};
56 /// # use uuid::Uuid;
57 /// # fn random_seed() -> u16 { 42 }
58 /// let context = Context::new(random_seed());
59 /// let ts = Timestamp::from_unix(&context, 1497624119, 1234);
60 ///
61 /// let uuid = Uuid::new_v1(ts, &[1, 2, 3, 4, 5, 6]);
62 ///
63 /// assert_eq!(
64 /// uuid.hyphenated().to_string(),
65 /// "f3b4958c-52a1-11e7-802a-010203040506"
66 /// );
67 /// ```
68 ///
69 /// The timestamp can also be created manually as per RFC 9562:
70 ///
71 /// ```
72 /// # use uuid::{Uuid, Timestamp, Context, ClockSequence};
73 /// let context = Context::new(42);
74 /// let ts = Timestamp::from_gregorian(14976234442241191232, context.generate_sequence(0, 0));
75 ///
76 /// let uuid = Uuid::new_v1(ts, &[1, 2, 3, 4, 5, 6]);
77 ///
78 /// assert_eq!(
79 /// uuid.hyphenated().to_string(),
80 /// "b2c1ad40-45e0-1fd6-802a-010203040506"
81 /// );
82 /// ```
83 ///
84 /// # References
85 ///
86 /// * [UUID Version 1 in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-5.1)
87 ///
88 /// [`Timestamp`]: v1/struct.Timestamp.html
89 /// [`ClockSequence`]: v1/trait.ClockSequence.html
90 /// [`Context`]: v1/struct.Context.html
91 pub fn new_v1(ts: Timestamp, node_id: &[u8; 6]) -> Self {
92 let (ticks, counter) = ts.to_gregorian();
93
94 Builder::from_gregorian_timestamp(ticks, counter, node_id).into_uuid()
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 use crate::{std::string::ToString, Variant, Version};
103 #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))]
104 use wasm_bindgen_test::*;
105
106 #[test]
107 #[cfg_attr(
108 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
109 wasm_bindgen_test
110 )]
111 fn test_new() {
112 let time: u64 = 1_496_854_535;
113 let time_fraction: u32 = 812_946_000;
114 let node = [1, 2, 3, 4, 5, 6];
115 let context = Context::new(0);
116
117 let uuid = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
118
119 assert_eq!(uuid.get_version(), Some(Version::Mac));
120 assert_eq!(uuid.get_variant(), Variant::RFC4122);
121 assert_eq!(
122 uuid.hyphenated().to_string(),
123 "20616934-4ba2-11e7-8000-010203040506"
124 );
125
126 let ts = uuid.get_timestamp().unwrap().to_gregorian();
127
128 assert_eq!(ts.0 - 0x01B2_1DD2_1381_4000, 14_968_545_358_129_460);
129
130 assert_eq!(Some(node), uuid.get_node_id(),);
131
132 // Ensure parsing the same UUID produces the same timestamp
133 let parsed = Uuid::parse_str("20616934-4ba2-11e7-8000-010203040506").unwrap();
134
135 assert_eq!(
136 uuid.get_timestamp().unwrap(),
137 parsed.get_timestamp().unwrap()
138 );
139
140 assert_eq!(uuid.get_node_id().unwrap(), parsed.get_node_id().unwrap(),);
141 }
142
143 #[test]
144 #[cfg_attr(
145 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
146 wasm_bindgen_test
147 )]
148 #[cfg(all(feature = "std", feature = "rng"))]
149 fn test_now() {
150 let node = [1, 2, 3, 4, 5, 6];
151
152 let uuid = Uuid::now_v1(&node);
153
154 assert_eq!(uuid.get_version(), Some(Version::Mac));
155 assert_eq!(uuid.get_variant(), Variant::RFC4122);
156 }
157}