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