• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
6 use crate::{Builder, Uuid};
7 
8 #[deprecated(note = "use types from the crate root instead")]
9 pub use crate::{timestamp::context::Context, Timestamp};
10 
11 impl 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"))]
now_v1(node_id: &[u8; 6]) -> Self22     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`]. RFC4122 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 RFC4122:
70     ///
71     /// ```
72     /// # use uuid::{Uuid, Timestamp, Context, ClockSequence};
73     /// let context = Context::new(42);
74     /// let ts = Timestamp::from_rfc4122(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     /// * [Version 1 UUIDs in RFC4122](https://www.rfc-editor.org/rfc/rfc4122#section-4.2)
87     ///
88     /// [`Timestamp`]: v1/struct.Timestamp.html
89     /// [`ClockSequence`]: v1/trait.ClockSequence.html
90     /// [`Context`]: v1/struct.Context.html
new_v1(ts: Timestamp, node_id: &[u8; 6]) -> Self91     pub fn new_v1(ts: Timestamp, node_id: &[u8; 6]) -> Self {
92         let (ticks, counter) = ts.to_rfc4122();
93 
94         Builder::from_rfc4122_timestamp(ticks, counter, node_id).into_uuid()
95     }
96 }
97 
98 #[cfg(test)]
99 mod tests {
100     use super::*;
101 
102     use crate::{std::string::ToString, Variant, Version};
103     #[cfg(all(
104         target_arch = "wasm32",
105         target_vendor = "unknown",
106         target_os = "unknown"
107     ))]
108     use wasm_bindgen_test::*;
109 
110     #[test]
111     #[cfg_attr(
112         all(
113             target_arch = "wasm32",
114             target_vendor = "unknown",
115             target_os = "unknown"
116         ),
117         wasm_bindgen_test
118     )]
test_new()119     fn test_new() {
120         let time: u64 = 1_496_854_535;
121         let time_fraction: u32 = 812_946_000;
122         let node = [1, 2, 3, 4, 5, 6];
123         let context = Context::new(0);
124 
125         let uuid = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
126 
127         assert_eq!(uuid.get_version(), Some(Version::Mac));
128         assert_eq!(uuid.get_variant(), Variant::RFC4122);
129         assert_eq!(
130             uuid.hyphenated().to_string(),
131             "20616934-4ba2-11e7-8000-010203040506"
132         );
133 
134         let ts = uuid.get_timestamp().unwrap().to_rfc4122();
135 
136         assert_eq!(ts.0 - 0x01B2_1DD2_1381_4000, 14_968_545_358_129_460);
137 
138         // Ensure parsing the same UUID produces the same timestamp
139         let parsed = Uuid::parse_str("20616934-4ba2-11e7-8000-010203040506").unwrap();
140 
141         assert_eq!(
142             uuid.get_timestamp().unwrap(),
143             parsed.get_timestamp().unwrap()
144         );
145     }
146 
147     #[test]
148     #[cfg_attr(
149         all(
150             target_arch = "wasm32",
151             target_vendor = "unknown",
152             target_os = "unknown"
153         ),
154         wasm_bindgen_test
155     )]
156     #[cfg(all(feature = "std", feature = "rng"))]
test_now()157     fn test_now() {
158         let node = [1, 2, 3, 4, 5, 6];
159 
160         let uuid = Uuid::now_v1(&node);
161 
162         assert_eq!(uuid.get_version(), Some(Version::Mac));
163         assert_eq!(uuid.get_variant(), Variant::RFC4122);
164     }
165 
166     #[test]
167     #[cfg_attr(
168         all(
169             target_arch = "wasm32",
170             target_vendor = "unknown",
171             target_os = "unknown"
172         ),
173         wasm_bindgen_test
174     )]
test_new_context()175     fn test_new_context() {
176         let time: u64 = 1_496_854_535;
177         let time_fraction: u32 = 812_946_000;
178         let node = [1, 2, 3, 4, 5, 6];
179 
180         // This context will wrap
181         let context = Context::new(u16::MAX >> 2);
182 
183         let uuid1 = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
184 
185         let time: u64 = 1_496_854_536;
186 
187         let uuid2 = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
188 
189         assert_eq!(uuid1.get_timestamp().unwrap().to_rfc4122().1, 16383);
190         assert_eq!(uuid2.get_timestamp().unwrap().to_rfc4122().1, 0);
191 
192         let time = 1_496_854_535;
193 
194         let uuid3 = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
195         let uuid4 = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
196 
197         assert_eq!(uuid3.get_timestamp().unwrap().to_rfc4122().1, 1);
198         assert_eq!(uuid4.get_timestamp().unwrap().to_rfc4122().1, 2);
199     }
200 }
201