uuid/
timestamp.rs

1//! Generating UUIDs from timestamps.
2//!
3//! Timestamps are used in a few UUID versions as a source of decentralized
4//! uniqueness (as in versions 1 and 6), and as a way to enable sorting (as
5//! in versions 6 and 7). Timestamps aren't encoded the same way by all UUID
6//! versions so this module provides a single [`Timestamp`] type that can
7//! convert between them.
8//!
9//! # Timestamp representations in UUIDs
10//!
11//! Versions 1 and 6 UUIDs use a bespoke timestamp that consists of the
12//! number of 100ns ticks since `1582-10-15 00:00:00`, along with
13//! a counter value to avoid duplicates.
14//!
15//! Version 7 UUIDs use a more standard timestamp that consists of the
16//! number of millisecond ticks since the Unix epoch (`1970-01-01 00:00:00`).
17//!
18//! # References
19//!
20//! * [UUID Version 1 in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-5.1)
21//! * [UUID Version 7 in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-5.7)
22//! * [Timestamp Considerations in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-6.1)
23
24use core::cmp;
25
26use crate::Uuid;
27
28/// The number of 100 nanosecond ticks between the RFC 9562 epoch
29/// (`1582-10-15 00:00:00`) and the Unix epoch (`1970-01-01 00:00:00`).
30pub const UUID_TICKS_BETWEEN_EPOCHS: u64 = 0x01B2_1DD2_1381_4000;
31
32/// A timestamp that can be encoded into a UUID.
33///
34/// This type abstracts the specific encoding, so versions 1, 6, and 7
35/// UUIDs can both be supported through the same type, even
36/// though they have a different representation of a timestamp.
37///
38/// # References
39///
40/// * [Timestamp Considerations in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-6.1)
41/// * [UUID Generator States in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-6.3)
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
43pub struct Timestamp {
44    seconds: u64,
45    subsec_nanos: u32,
46    counter: u128,
47    usable_counter_bits: u8,
48}
49
50impl Timestamp {
51    /// Get a timestamp representing the current system time and up to a 128-bit counter.
52    ///
53    /// This method defers to the standard library's `SystemTime` type.
54    #[cfg(feature = "std")]
55    pub fn now(context: impl ClockSequence<Output = impl Into<u128>>) -> Self {
56        let (seconds, subsec_nanos) = now();
57
58        let (counter, seconds, subsec_nanos) =
59            context.generate_timestamp_sequence(seconds, subsec_nanos);
60        let counter = counter.into();
61        let usable_counter_bits = context.usable_bits() as u8;
62
63        Timestamp {
64            seconds,
65            subsec_nanos,
66            counter,
67            usable_counter_bits,
68        }
69    }
70
71    /// Construct a `Timestamp` from the number of 100 nanosecond ticks since 00:00:00.00,
72    /// 15 October 1582 (the date of Gregorian reform to the Christian calendar) and a 14-bit
73    /// counter, as used in versions 1 and 6 UUIDs.
74    ///
75    /// # Overflow
76    ///
77    /// If conversion from RFC 9562 ticks to the internal timestamp format would overflow
78    /// it will wrap.
79    pub const fn from_gregorian(ticks: u64, counter: u16) -> Self {
80        let (seconds, subsec_nanos) = Self::gregorian_to_unix(ticks);
81
82        Timestamp {
83            seconds,
84            subsec_nanos,
85            counter: counter as u128,
86            usable_counter_bits: 14,
87        }
88    }
89
90    /// Construct a `Timestamp` from a Unix timestamp and up to a 128-bit counter, as used in version 7 UUIDs.
91    pub const fn from_unix_time(
92        seconds: u64,
93        subsec_nanos: u32,
94        counter: u128,
95        usable_counter_bits: u8,
96    ) -> Self {
97        Timestamp {
98            seconds,
99            subsec_nanos,
100            counter,
101            usable_counter_bits,
102        }
103    }
104
105    /// Construct a `Timestamp` from a Unix timestamp and up to a 128-bit counter, as used in version 7 UUIDs.
106    pub fn from_unix(
107        context: impl ClockSequence<Output = impl Into<u128>>,
108        seconds: u64,
109        subsec_nanos: u32,
110    ) -> Self {
111        let (counter, seconds, subsec_nanos) =
112            context.generate_timestamp_sequence(seconds, subsec_nanos);
113        let counter = counter.into();
114        let usable_counter_bits = context.usable_bits() as u8;
115
116        Timestamp {
117            seconds,
118            subsec_nanos,
119            counter,
120            usable_counter_bits,
121        }
122    }
123
124    /// Get the value of the timestamp as the number of 100 nanosecond ticks since 00:00:00.00,
125    /// 15 October 1582 and a 14-bit counter, as used in versions 1 and 6 UUIDs.
126    ///
127    /// # Overflow
128    ///
129    /// If conversion from the internal timestamp format to ticks would overflow
130    /// then it will wrap.
131    ///
132    /// If the internal counter is wider than 14 bits then it will be truncated to 14 bits.
133    pub const fn to_gregorian(&self) -> (u64, u16) {
134        (
135            Self::unix_to_gregorian_ticks(self.seconds, self.subsec_nanos),
136            (self.counter as u16) & 0x3FFF,
137        )
138    }
139
140    // NOTE: This method is not public; the usable counter bits are lost in a version 7 UUID
141    // so can't be reliably recovered.
142    #[cfg(feature = "v7")]
143    pub(crate) const fn counter(&self) -> (u128, u8) {
144        (self.counter, self.usable_counter_bits)
145    }
146
147    /// Get the value of the timestamp as a Unix timestamp, as used in version 7 UUIDs.
148    pub const fn to_unix(&self) -> (u64, u32) {
149        (self.seconds, self.subsec_nanos)
150    }
151
152    const fn unix_to_gregorian_ticks(seconds: u64, nanos: u32) -> u64 {
153        UUID_TICKS_BETWEEN_EPOCHS
154            .wrapping_add(seconds.wrapping_mul(10_000_000))
155            .wrapping_add(nanos as u64 / 100)
156    }
157
158    const fn gregorian_to_unix(ticks: u64) -> (u64, u32) {
159        (
160            ticks.wrapping_sub(UUID_TICKS_BETWEEN_EPOCHS) / 10_000_000,
161            (ticks.wrapping_sub(UUID_TICKS_BETWEEN_EPOCHS) % 10_000_000) as u32 * 100,
162        )
163    }
164}
165
166#[doc(hidden)]
167impl Timestamp {
168    #[deprecated(
169        since = "1.10.0",
170        note = "use `Timestamp::from_gregorian(ticks, counter)`"
171    )]
172    pub const fn from_rfc4122(ticks: u64, counter: u16) -> Self {
173        Timestamp::from_gregorian(ticks, counter)
174    }
175
176    #[deprecated(since = "1.10.0", note = "use `Timestamp::to_gregorian()`")]
177    pub const fn to_rfc4122(&self) -> (u64, u16) {
178        self.to_gregorian()
179    }
180
181    #[deprecated(
182        since = "1.2.0",
183        note = "`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`"
184    )]
185    pub const fn to_unix_nanos(&self) -> u32 {
186        panic!("`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`")
187    }
188}
189
190#[cfg(feature = "std")]
191impl std::convert::TryFrom<std::time::SystemTime> for Timestamp {
192    type Error = crate::Error;
193
194    /// Perform the conversion.
195    /// 
196    /// This method will fail if the system time is earlier than the Unix Epoch.
197    /// On some platforms it may panic instead.
198    fn try_from(st: std::time::SystemTime) -> Result<Self, Self::Error> {
199        let dur = st.duration_since(std::time::UNIX_EPOCH).map_err(|_| crate::Error(crate::error::ErrorKind::InvalidSystemTime("unable to convert the system tie into a Unix timestamp")))?;
200
201        Ok(Self::from_unix_time(
202            dur.as_secs(),
203            dur.subsec_nanos(),
204            0,
205            0,
206        ))
207    }
208}
209
210#[cfg(feature = "std")]
211impl From<Timestamp> for std::time::SystemTime {
212    fn from(ts: Timestamp) -> Self {
213        let (seconds, subsec_nanos) = ts.to_unix();
214
215        Self::UNIX_EPOCH + std::time::Duration::new(seconds, subsec_nanos)
216    }
217}
218
219pub(crate) const fn encode_gregorian_timestamp(
220    ticks: u64,
221    counter: u16,
222    node_id: &[u8; 6],
223) -> Uuid {
224    let time_low = (ticks & 0xFFFF_FFFF) as u32;
225    let time_mid = ((ticks >> 32) & 0xFFFF) as u16;
226    let time_high_and_version = (((ticks >> 48) & 0x0FFF) as u16) | (1 << 12);
227
228    let mut d4 = [0; 8];
229
230    d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
231    d4[1] = (counter & 0xFF) as u8;
232    d4[2] = node_id[0];
233    d4[3] = node_id[1];
234    d4[4] = node_id[2];
235    d4[5] = node_id[3];
236    d4[6] = node_id[4];
237    d4[7] = node_id[5];
238
239    Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
240}
241
242pub(crate) const fn decode_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
243    let bytes = uuid.as_bytes();
244
245    let ticks: u64 = ((bytes[6] & 0x0F) as u64) << 56
246        | (bytes[7] as u64) << 48
247        | (bytes[4] as u64) << 40
248        | (bytes[5] as u64) << 32
249        | (bytes[0] as u64) << 24
250        | (bytes[1] as u64) << 16
251        | (bytes[2] as u64) << 8
252        | (bytes[3] as u64);
253
254    let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
255
256    (ticks, counter)
257}
258
259pub(crate) const fn encode_sorted_gregorian_timestamp(
260    ticks: u64,
261    counter: u16,
262    node_id: &[u8; 6],
263) -> Uuid {
264    let time_high = ((ticks >> 28) & 0xFFFF_FFFF) as u32;
265    let time_mid = ((ticks >> 12) & 0xFFFF) as u16;
266    let time_low_and_version = ((ticks & 0x0FFF) as u16) | (0x6 << 12);
267
268    let mut d4 = [0; 8];
269
270    d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
271    d4[1] = (counter & 0xFF) as u8;
272    d4[2] = node_id[0];
273    d4[3] = node_id[1];
274    d4[4] = node_id[2];
275    d4[5] = node_id[3];
276    d4[6] = node_id[4];
277    d4[7] = node_id[5];
278
279    Uuid::from_fields(time_high, time_mid, time_low_and_version, &d4)
280}
281
282pub(crate) const fn decode_sorted_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
283    let bytes = uuid.as_bytes();
284
285    let ticks: u64 = ((bytes[0]) as u64) << 52
286        | (bytes[1] as u64) << 44
287        | (bytes[2] as u64) << 36
288        | (bytes[3] as u64) << 28
289        | (bytes[4] as u64) << 20
290        | (bytes[5] as u64) << 12
291        | ((bytes[6] & 0xF) as u64) << 8
292        | (bytes[7] as u64);
293
294    let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
295
296    (ticks, counter)
297}
298
299pub(crate) const fn encode_unix_timestamp_millis(
300    millis: u64,
301    counter_random_bytes: &[u8; 10],
302) -> Uuid {
303    let millis_high = ((millis >> 16) & 0xFFFF_FFFF) as u32;
304    let millis_low = (millis & 0xFFFF) as u16;
305
306    let counter_random_version = (counter_random_bytes[1] as u16
307        | ((counter_random_bytes[0] as u16) << 8) & 0x0FFF)
308        | (0x7 << 12);
309
310    let mut d4 = [0; 8];
311
312    d4[0] = (counter_random_bytes[2] & 0x3F) | 0x80;
313    d4[1] = counter_random_bytes[3];
314    d4[2] = counter_random_bytes[4];
315    d4[3] = counter_random_bytes[5];
316    d4[4] = counter_random_bytes[6];
317    d4[5] = counter_random_bytes[7];
318    d4[6] = counter_random_bytes[8];
319    d4[7] = counter_random_bytes[9];
320
321    Uuid::from_fields(millis_high, millis_low, counter_random_version, &d4)
322}
323
324pub(crate) const fn decode_unix_timestamp_millis(uuid: &Uuid) -> u64 {
325    let bytes = uuid.as_bytes();
326
327    let millis: u64 = (bytes[0] as u64) << 40
328        | (bytes[1] as u64) << 32
329        | (bytes[2] as u64) << 24
330        | (bytes[3] as u64) << 16
331        | (bytes[4] as u64) << 8
332        | (bytes[5] as u64);
333
334    millis
335}
336
337#[cfg(all(
338    feature = "std",
339    feature = "js",
340    all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))
341))]
342fn now() -> (u64, u32) {
343    use wasm_bindgen::prelude::*;
344
345    #[wasm_bindgen]
346    extern "C" {
347        // NOTE: This signature works around https://bugzilla.mozilla.org/show_bug.cgi?id=1787770
348        #[wasm_bindgen(js_namespace = Date, catch)]
349        fn now() -> Result<f64, JsValue>;
350    }
351
352    let now = now().unwrap_throw();
353
354    let secs = (now / 1_000.0) as u64;
355    let nanos = ((now % 1_000.0) * 1_000_000.0) as u32;
356
357    (secs, nanos)
358}
359
360#[cfg(all(
361    feature = "std",
362    not(miri),
363    any(
364        not(feature = "js"),
365        not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))
366    )
367))]
368fn now() -> (u64, u32) {
369    let dur = std::time::SystemTime::UNIX_EPOCH.elapsed().expect(
370        "Getting elapsed time since UNIX_EPOCH. If this fails, we've somehow violated causality",
371    );
372
373    (dur.as_secs(), dur.subsec_nanos())
374}
375
376#[cfg(all(feature = "std", miri))]
377fn now() -> (u64, u32) {
378    use std::{sync::Mutex, time::Duration};
379
380    static TS: Mutex<u64> = Mutex::new(0);
381
382    let ts = Duration::from_nanos({
383        let mut ts = TS.lock().unwrap();
384        *ts += 1;
385        *ts
386    });
387
388    (ts.as_secs(), ts.subsec_nanos())
389}
390
391/// A counter that can be used by versions 1 and 6 UUIDs to support
392/// the uniqueness of timestamps.
393///
394/// # References
395///
396/// * [UUID Version 1 in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-5.1)
397/// * [UUID Version 6 in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-5.6)
398/// * [UUID Generator States in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-6.3)
399pub trait ClockSequence {
400    /// The type of sequence returned by this counter.
401    type Output;
402
403    /// Get the next value in the sequence to feed into a timestamp.
404    ///
405    /// This method will be called each time a [`Timestamp`] is constructed.
406    ///
407    /// Any bits beyond [`ClockSequence::usable_bits`] in the output must be unset.
408    fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output;
409
410    /// Get the next value in the sequence, potentially also adjusting the timestamp.
411    ///
412    /// This method should be preferred over `generate_sequence`.
413    ///
414    /// Any bits beyond [`ClockSequence::usable_bits`] in the output must be unset.
415    fn generate_timestamp_sequence(
416        &self,
417        seconds: u64,
418        subsec_nanos: u32,
419    ) -> (Self::Output, u64, u32) {
420        (
421            self.generate_sequence(seconds, subsec_nanos),
422            seconds,
423            subsec_nanos,
424        )
425    }
426
427    /// The number of usable bits from the least significant bit in the result of [`ClockSequence::generate_sequence`]
428    /// or [`ClockSequence::generate_timestamp_sequence`].
429    ///
430    /// The number of usable bits must not exceed 128.
431    ///
432    /// The number of usable bits is not expected to change between calls. An implementation of `ClockSequence` should
433    /// always return the same value from this method.
434    fn usable_bits(&self) -> usize
435    where
436        Self::Output: Sized,
437    {
438        cmp::min(128, core::mem::size_of::<Self::Output>())
439    }
440}
441
442impl<'a, T: ClockSequence + ?Sized> ClockSequence for &'a T {
443    type Output = T::Output;
444
445    fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
446        (**self).generate_sequence(seconds, subsec_nanos)
447    }
448
449    fn generate_timestamp_sequence(
450        &self,
451        seconds: u64,
452        subsec_nanos: u32,
453    ) -> (Self::Output, u64, u32) {
454        (**self).generate_timestamp_sequence(seconds, subsec_nanos)
455    }
456
457    fn usable_bits(&self) -> usize
458    where
459        Self::Output: Sized,
460    {
461        (**self).usable_bits()
462    }
463}
464
465/// Default implementations for the [`ClockSequence`] trait.
466pub mod context {
467    use super::ClockSequence;
468
469    #[cfg(any(feature = "v1", feature = "v6"))]
470    mod v1_support {
471        use super::*;
472
473        use atomic::{Atomic, Ordering};
474
475        #[cfg(all(feature = "std", feature = "rng"))]
476        static CONTEXT: Context = Context {
477            count: Atomic::new(0),
478        };
479
480        #[cfg(all(feature = "std", feature = "rng"))]
481        static CONTEXT_INITIALIZED: Atomic<bool> = Atomic::new(false);
482
483        #[cfg(all(feature = "std", feature = "rng"))]
484        pub(crate) fn shared_context() -> &'static Context {
485            // If the context is in its initial state then assign it to a random value
486            // It doesn't matter if multiple threads observe `false` here and initialize the context
487            if CONTEXT_INITIALIZED
488                .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
489                .is_ok()
490            {
491                CONTEXT.count.store(crate::rng::u16(), Ordering::Release);
492            }
493
494            &CONTEXT
495        }
496
497        /// A thread-safe, wrapping counter that produces 14-bit values.
498        ///
499        /// This type works by:
500        ///
501        /// 1. Atomically incrementing the counter value for each timestamp.
502        /// 2. Wrapping the counter back to zero if it overflows its 14-bit storage.
503        ///
504        /// This type should be used when constructing versions 1 and 6 UUIDs.
505        ///
506        /// This type should not be used when constructing version 7 UUIDs. When used to
507        /// construct a version 7 UUID, the 14-bit counter will be padded with random data.
508        /// Counter overflows are more likely with a 14-bit counter than they are with a
509        /// 42-bit counter when working at millisecond precision. This type doesn't attempt
510        /// to adjust the timestamp on overflow.
511        #[derive(Debug)]
512        pub struct Context {
513            count: Atomic<u16>,
514        }
515
516        impl Context {
517            /// Construct a new context that's initialized with the given value.
518            ///
519            /// The starting value should be a random number, so that UUIDs from
520            /// different systems with the same timestamps are less likely to collide.
521            /// When the `rng` feature is enabled, prefer the [`Context::new_random`] method.
522            pub const fn new(count: u16) -> Self {
523                Self {
524                    count: Atomic::<u16>::new(count),
525                }
526            }
527
528            /// Construct a new context that's initialized with a random value.
529            #[cfg(feature = "rng")]
530            pub fn new_random() -> Self {
531                Self {
532                    count: Atomic::<u16>::new(crate::rng::u16()),
533                }
534            }
535        }
536
537        impl ClockSequence for Context {
538            type Output = u16;
539
540            fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
541                // RFC 9562 reserves 2 bits of the clock sequence so the actual
542                // maximum value is smaller than `u16::MAX`. Since we unconditionally
543                // increment the clock sequence we want to wrap once it becomes larger
544                // than what we can represent in a "u14". Otherwise there'd be patches
545                // where the clock sequence doesn't change regardless of the timestamp
546                self.count.fetch_add(1, Ordering::AcqRel) & (u16::MAX >> 2)
547            }
548
549            fn usable_bits(&self) -> usize {
550                14
551            }
552        }
553
554        #[cfg(test)]
555        mod tests {
556            use crate::Timestamp;
557
558            use super::*;
559
560            #[test]
561            fn context() {
562                let seconds = 1_496_854_535;
563                let subsec_nanos = 812_946_000;
564
565                let context = Context::new(u16::MAX >> 2);
566
567                let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
568                assert_eq!(16383, ts.counter);
569                assert_eq!(14, ts.usable_counter_bits);
570
571                let seconds = 1_496_854_536;
572
573                let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
574                assert_eq!(0, ts.counter);
575
576                let seconds = 1_496_854_535;
577
578                let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
579                assert_eq!(1, ts.counter);
580            }
581
582            #[test]
583            fn context_overflow() {
584                let seconds = u64::MAX;
585                let subsec_nanos = u32::MAX;
586
587                let context = Context::new(u16::MAX);
588
589                // Ensure we don't panic
590                Timestamp::from_unix(&context, seconds, subsec_nanos);
591            }
592        }
593    }
594
595    #[cfg(any(feature = "v1", feature = "v6"))]
596    pub use v1_support::*;
597
598    #[cfg(feature = "std")]
599    mod std_support {
600        use super::*;
601
602        use core::panic::{AssertUnwindSafe, RefUnwindSafe};
603        use std::{sync::Mutex, thread::LocalKey};
604
605        /// A wrapper for a context that uses thread-local storage.
606        pub struct ThreadLocalContext<C: 'static>(&'static LocalKey<C>);
607
608        impl<C> std::fmt::Debug for ThreadLocalContext<C> {
609            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
610                f.debug_struct("ThreadLocalContext").finish_non_exhaustive()
611            }
612        }
613
614        impl<C: 'static> ThreadLocalContext<C> {
615            /// Wrap a thread-local container with a context.
616            pub const fn new(local_key: &'static LocalKey<C>) -> Self {
617                ThreadLocalContext(local_key)
618            }
619        }
620
621        impl<C: ClockSequence + 'static> ClockSequence for ThreadLocalContext<C> {
622            type Output = C::Output;
623
624            fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
625                self.0
626                    .with(|ctxt| ctxt.generate_sequence(seconds, subsec_nanos))
627            }
628
629            fn generate_timestamp_sequence(
630                &self,
631                seconds: u64,
632                subsec_nanos: u32,
633            ) -> (Self::Output, u64, u32) {
634                self.0
635                    .with(|ctxt| ctxt.generate_timestamp_sequence(seconds, subsec_nanos))
636            }
637
638            fn usable_bits(&self) -> usize {
639                self.0.with(|ctxt| ctxt.usable_bits())
640            }
641        }
642
643        impl<C: ClockSequence> ClockSequence for AssertUnwindSafe<C> {
644            type Output = C::Output;
645
646            fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
647                self.0.generate_sequence(seconds, subsec_nanos)
648            }
649
650            fn generate_timestamp_sequence(
651                &self,
652                seconds: u64,
653                subsec_nanos: u32,
654            ) -> (Self::Output, u64, u32) {
655                self.0.generate_timestamp_sequence(seconds, subsec_nanos)
656            }
657
658            fn usable_bits(&self) -> usize
659            where
660                Self::Output: Sized,
661            {
662                self.0.usable_bits()
663            }
664        }
665
666        impl<C: ClockSequence + RefUnwindSafe> ClockSequence for Mutex<C> {
667            type Output = C::Output;
668
669            fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
670                self.lock()
671                    .unwrap_or_else(|err| err.into_inner())
672                    .generate_sequence(seconds, subsec_nanos)
673            }
674
675            fn generate_timestamp_sequence(
676                &self,
677                seconds: u64,
678                subsec_nanos: u32,
679            ) -> (Self::Output, u64, u32) {
680                self.lock()
681                    .unwrap_or_else(|err| err.into_inner())
682                    .generate_timestamp_sequence(seconds, subsec_nanos)
683            }
684
685            fn usable_bits(&self) -> usize
686            where
687                Self::Output: Sized,
688            {
689                self.lock()
690                    .unwrap_or_else(|err| err.into_inner())
691                    .usable_bits()
692            }
693        }
694    }
695
696    #[cfg(feature = "std")]
697    pub use std_support::*;
698
699    #[cfg(feature = "v7")]
700    mod v7_support {
701        use super::*;
702
703        use core::{cell::Cell, cmp, panic::RefUnwindSafe};
704
705        #[cfg(feature = "std")]
706        static CONTEXT_V7: SharedContextV7 =
707            SharedContextV7(std::sync::Mutex::new(ContextV7::new()));
708
709        #[cfg(feature = "std")]
710        pub(crate) fn shared_context_v7() -> &'static SharedContextV7 {
711            &CONTEXT_V7
712        }
713
714        const USABLE_BITS: usize = 42;
715
716        // Leave the most significant bit unset
717        // This guarantees the counter has at least 2,199,023,255,552
718        // values before it will overflow, which is exceptionally unlikely
719        // even in the worst case
720        const RESEED_MASK: u64 = u64::MAX >> 23;
721        const MAX_COUNTER: u64 = u64::MAX >> 22;
722
723        /// An unsynchronized, reseeding counter that produces 42-bit values.
724        ///
725        /// This type works by:
726        ///
727        /// 1. Reseeding the counter each millisecond with a random 41-bit value. The 42nd bit
728        ///    is left unset so the counter can safely increment over the millisecond.
729        /// 2. Wrapping the counter back to zero if it overflows its 42-bit storage and adding a
730        ///    millisecond to the timestamp.
731        ///
732        /// The counter can use additional sub-millisecond precision from the timestamp to better
733        /// synchronize UUID sorting in distributed systems. In these cases, the additional precision
734        /// is masked into the left-most 12 bits of the counter. The counter is still reseeded on
735        /// each new millisecond, and incremented within the millisecond. This behavior may change
736        /// in the future. The only guarantee is monotonicity.
737        ///
738        /// This type can be used when constructing version 7 UUIDs. When used to construct a
739        /// version 7 UUID, the 42-bit counter will be padded with random data. This type can
740        /// be used to maintain ordering of UUIDs within the same millisecond.
741        ///
742        /// This type should not be used when constructing version 1 or version 6 UUIDs.
743        /// When used to construct a version 1 or version 6 UUID, only the 14 least significant
744        /// bits of the counter will be used.
745        #[derive(Debug)]
746        pub struct ContextV7 {
747            timestamp: Cell<ReseedingTimestamp>,
748            counter: Cell<Counter>,
749            adjust: Adjust,
750            precision: Precision,
751        }
752
753        impl RefUnwindSafe for ContextV7 {}
754
755        impl ContextV7 {
756            /// Construct a new context that will reseed its counter on the first
757            /// non-zero timestamp it receives.
758            pub const fn new() -> Self {
759                ContextV7 {
760                    timestamp: Cell::new(ReseedingTimestamp {
761                        last_seed: 0,
762                        seconds: 0,
763                        subsec_nanos: 0,
764                    }),
765                    counter: Cell::new(Counter { value: 0 }),
766                    adjust: Adjust { by_ns: 0 },
767                    precision: Precision {
768                        bits: 0,
769                        mask: 0,
770                        factor: 0,
771                        shift: 0,
772                    },
773                }
774            }
775
776            /// Specify an amount to shift timestamps by to obfuscate their actual generation time.
777            pub fn with_adjust_by_millis(mut self, millis: u32) -> Self {
778                self.adjust = Adjust::by_millis(millis);
779                self
780            }
781
782            /// Use the leftmost 12 bits of the counter for additional timestamp precision.
783            ///
784            /// This method can provide better sorting for distributed applications that generate frequent UUIDs
785            /// by trading a small amount of entropy for better counter synchronization. Note that the counter
786            /// will still be reseeded on millisecond boundaries, even though some of its storage will be
787            /// dedicated to the timestamp.
788            pub fn with_additional_precision(mut self) -> Self {
789                self.precision = Precision::new(12);
790                self
791            }
792        }
793
794        impl ClockSequence for ContextV7 {
795            type Output = u64;
796
797            fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
798                self.generate_timestamp_sequence(seconds, subsec_nanos).0
799            }
800
801            fn generate_timestamp_sequence(
802                &self,
803                seconds: u64,
804                subsec_nanos: u32,
805            ) -> (Self::Output, u64, u32) {
806                let (seconds, subsec_nanos) = self.adjust.apply(seconds, subsec_nanos);
807
808                let mut counter;
809                let (mut timestamp, should_reseed) =
810                    self.timestamp.get().advance(seconds, subsec_nanos);
811
812                if should_reseed {
813                    // If the observed system time has shifted forwards then regenerate the counter
814                    counter = Counter::reseed(&self.precision, &timestamp);
815                } else {
816                    // If the observed system time has not shifted forwards then increment the counter
817
818                    // If the incoming timestamp is earlier than the last observed one then
819                    // use it instead. This may happen if the system clock jitters, or if the counter
820                    // has wrapped and the timestamp is artificially incremented
821
822                    counter = self.counter.get().increment(&self.precision, &timestamp);
823
824                    // Unlikely: If the counter has overflowed its 42-bit storage then wrap it
825                    // and increment the timestamp. Until the observed system time shifts past
826                    // this incremented value, all timestamps will use it to maintain monotonicity
827                    if counter.has_overflowed() {
828                        // Increment the timestamp by 1 milli and reseed the counter
829                        timestamp = timestamp.increment();
830                        counter = Counter::reseed(&self.precision, &timestamp);
831                    }
832                };
833
834                self.timestamp.set(timestamp);
835                self.counter.set(counter);
836
837                (counter.value, timestamp.seconds, timestamp.subsec_nanos)
838            }
839
840            fn usable_bits(&self) -> usize {
841                USABLE_BITS
842            }
843        }
844
845        #[derive(Debug)]
846        struct Adjust {
847            by_ns: u128,
848        }
849
850        impl Adjust {
851            #[inline]
852            fn by_millis(millis: u32) -> Self {
853                Adjust {
854                    by_ns: (millis as u128).saturating_mul(1_000_000),
855                }
856            }
857
858            #[inline]
859            fn apply(&self, seconds: u64, subsec_nanos: u32) -> (u64, u32) {
860                if self.by_ns == 0 {
861                    // No shift applied
862                    return (seconds, subsec_nanos);
863                }
864
865                let ts = (seconds as u128)
866                    .saturating_mul(1_000_000_000)
867                    .saturating_add(subsec_nanos as u128)
868                    .saturating_add(self.by_ns as u128);
869
870                ((ts / 1_000_000_000) as u64, (ts % 1_000_000_000) as u32)
871            }
872        }
873
874        #[derive(Debug, Default, Clone, Copy)]
875        struct ReseedingTimestamp {
876            last_seed: u64,
877            seconds: u64,
878            subsec_nanos: u32,
879        }
880
881        impl ReseedingTimestamp {
882            #[inline]
883            fn advance(&self, seconds: u64, subsec_nanos: u32) -> (Self, bool) {
884                let incoming = ReseedingTimestamp::from_ts(seconds, subsec_nanos);
885
886                if incoming.last_seed > self.last_seed {
887                    // The incoming value is part of a new millisecond
888                    (incoming, true)
889                } else {
890                    // The incoming value is part of the same or an earlier millisecond
891                    // We may still have advanced the subsecond portion, so use the larger value
892                    let mut value = *self;
893                    value.subsec_nanos = cmp::max(self.subsec_nanos, subsec_nanos);
894
895                    (value, false)
896                }
897            }
898
899            #[inline]
900            fn from_ts(seconds: u64, subsec_nanos: u32) -> Self {
901                // Reseed when the millisecond advances
902                let last_seed = seconds
903                    .saturating_mul(1_000)
904                    .saturating_add((subsec_nanos / 1_000_000) as u64);
905
906                ReseedingTimestamp {
907                    last_seed,
908                    seconds,
909                    subsec_nanos,
910                }
911            }
912
913            #[inline]
914            fn increment(&self) -> Self {
915                let (seconds, subsec_nanos) =
916                    Adjust::by_millis(1).apply(self.seconds, self.subsec_nanos);
917
918                ReseedingTimestamp::from_ts(seconds, subsec_nanos)
919            }
920
921            #[inline]
922            fn submilli_nanos(&self) -> u32 {
923                self.subsec_nanos % 1_000_000
924            }
925        }
926
927        #[derive(Debug)]
928        struct Precision {
929            bits: usize,
930            factor: u64,
931            mask: u64,
932            shift: u64,
933        }
934
935        impl Precision {
936            fn new(bits: usize) -> Self {
937                // The mask and shift are used to paste the sub-millisecond precision
938                // into the most significant bits of the counter
939                let mask = u64::MAX >> (64 - USABLE_BITS + bits);
940                let shift = (USABLE_BITS - bits) as u64;
941
942                // The factor reduces the size of the sub-millisecond precision to
943                // fit into the specified number of bits
944                let factor = (999_999 / u64::pow(2, bits as u32)) + 1;
945
946                Precision {
947                    bits,
948                    factor,
949                    mask,
950                    shift,
951                }
952            }
953
954            #[inline]
955            fn apply(&self, value: u64, timestamp: &ReseedingTimestamp) -> u64 {
956                if self.bits == 0 {
957                    // No additional precision is being used
958                    return value;
959                }
960
961                let additional = timestamp.submilli_nanos() as u64 / self.factor;
962
963                (value & self.mask) | (additional << self.shift)
964            }
965        }
966
967        #[derive(Debug, Clone, Copy)]
968        struct Counter {
969            value: u64,
970        }
971
972        impl Counter {
973            #[inline]
974            fn reseed(precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
975                Counter {
976                    value: precision.apply(crate::rng::u64() & RESEED_MASK, timestamp),
977                }
978            }
979
980            #[inline]
981            fn increment(&self, precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
982                let mut counter = Counter {
983                    value: precision.apply(self.value, timestamp),
984                };
985
986                // We unconditionally increment the counter even though the precision
987                // may have set higher bits already. This could technically be avoided,
988                // but the higher bits are a coarse approximation so we just avoid the
989                // `if` branch and increment it either way
990
991                // Guaranteed to never overflow u64
992                counter.value += 1;
993
994                counter
995            }
996
997            #[inline]
998            fn has_overflowed(&self) -> bool {
999                self.value > MAX_COUNTER
1000            }
1001        }
1002
1003        #[cfg(feature = "std")]
1004        pub(crate) struct SharedContextV7(std::sync::Mutex<ContextV7>);
1005
1006        #[cfg(feature = "std")]
1007        impl ClockSequence for SharedContextV7 {
1008            type Output = u64;
1009
1010            fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
1011                self.0.generate_sequence(seconds, subsec_nanos)
1012            }
1013
1014            fn generate_timestamp_sequence(
1015                &self,
1016                seconds: u64,
1017                subsec_nanos: u32,
1018            ) -> (Self::Output, u64, u32) {
1019                self.0.generate_timestamp_sequence(seconds, subsec_nanos)
1020            }
1021
1022            fn usable_bits(&self) -> usize
1023            where
1024                Self::Output: Sized,
1025            {
1026                USABLE_BITS
1027            }
1028        }
1029
1030        #[cfg(test)]
1031        mod tests {
1032            use core::time::Duration;
1033
1034            use super::*;
1035
1036            use crate::{Timestamp, Uuid};
1037
1038            #[test]
1039            fn context() {
1040                let seconds = 1_496_854_535;
1041                let subsec_nanos = 812_946_000;
1042
1043                let context = ContextV7::new();
1044
1045                let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1046                assert_eq!(42, ts1.usable_counter_bits);
1047
1048                // Backwards second
1049                let seconds = 1_496_854_534;
1050
1051                let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1052
1053                // The backwards time should be ignored
1054                // The counter should still increment
1055                assert_eq!(ts1.seconds, ts2.seconds);
1056                assert_eq!(ts1.subsec_nanos, ts2.subsec_nanos);
1057                assert_eq!(ts1.counter + 1, ts2.counter);
1058
1059                // Forwards second
1060                let seconds = 1_496_854_536;
1061
1062                let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1063
1064                // The counter should have reseeded
1065                assert_ne!(ts2.counter + 1, ts3.counter);
1066                assert_ne!(0, ts3.counter);
1067            }
1068
1069            #[test]
1070            fn context_wrap() {
1071                let seconds = 1_496_854_535u64;
1072                let subsec_nanos = 812_946_000u32;
1073
1074                // This context will wrap
1075                let context = ContextV7 {
1076                    timestamp: Cell::new(ReseedingTimestamp::from_ts(seconds, subsec_nanos)),
1077                    adjust: Adjust::by_millis(0),
1078                    precision: Precision {
1079                        bits: 0,
1080                        mask: 0,
1081                        factor: 0,
1082                        shift: 0,
1083                    },
1084                    counter: Cell::new(Counter {
1085                        value: u64::MAX >> 22,
1086                    }),
1087                };
1088
1089                let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1090
1091                // The timestamp should be incremented by 1ms
1092                let expected_ts = Duration::new(seconds, subsec_nanos) + Duration::from_millis(1);
1093                assert_eq!(expected_ts.as_secs(), ts.seconds);
1094                assert_eq!(expected_ts.subsec_nanos(), ts.subsec_nanos);
1095
1096                // The counter should have reseeded
1097                assert!(ts.counter < (u64::MAX >> 22) as u128);
1098                assert_ne!(0, ts.counter);
1099            }
1100
1101            #[test]
1102            fn context_shift() {
1103                let seconds = 1_496_854_535;
1104                let subsec_nanos = 812_946_000;
1105
1106                let context = ContextV7::new().with_adjust_by_millis(1);
1107
1108                let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1109
1110                assert_eq!((1_496_854_535, 813_946_000), ts.to_unix());
1111            }
1112
1113            #[test]
1114            fn context_additional_precision() {
1115                let seconds = 1_496_854_535;
1116                let subsec_nanos = 812_946_000;
1117
1118                let context = ContextV7::new().with_additional_precision();
1119
1120                let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1121
1122                // NOTE: Future changes in rounding may change this value slightly
1123                assert_eq!(3861, ts1.counter >> 30);
1124
1125                assert!(ts1.counter < (u64::MAX >> 22) as u128);
1126
1127                // Generate another timestamp; it should continue to sort
1128                let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1129
1130                assert!(Uuid::new_v7(ts2) > Uuid::new_v7(ts1));
1131
1132                // Generate another timestamp with an extra nanosecond
1133                let subsec_nanos = subsec_nanos + 1;
1134
1135                let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1136
1137                assert!(Uuid::new_v7(ts3) > Uuid::new_v7(ts2));
1138            }
1139
1140            #[test]
1141            fn context_overflow() {
1142                let seconds = u64::MAX;
1143                let subsec_nanos = u32::MAX;
1144
1145                // Ensure we don't panic
1146                for context in [
1147                    ContextV7::new(),
1148                    ContextV7::new().with_additional_precision(),
1149                    ContextV7::new().with_adjust_by_millis(u32::MAX),
1150                ] {
1151                    Timestamp::from_unix(&context, seconds, subsec_nanos);
1152                }
1153            }
1154        }
1155    }
1156
1157    #[cfg(feature = "v7")]
1158    pub use v7_support::*;
1159
1160    /// An empty counter that will always return the value `0`.
1161    ///
1162    /// This type can be used when constructing version 7 UUIDs. When used to
1163    /// construct a version 7 UUID, the entire counter segment of the UUID will be
1164    /// filled with a random value. This type does not maintain ordering of UUIDs
1165    /// within a millisecond but is efficient.
1166    ///
1167    /// This type should not be used when constructing version 1 or version 6 UUIDs.
1168    /// When used to construct a version 1 or version 6 UUID, the counter
1169    /// segment will remain zero.
1170    #[derive(Debug, Clone, Copy, Default)]
1171    pub struct NoContext;
1172
1173    impl ClockSequence for NoContext {
1174        type Output = u16;
1175
1176        fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
1177            0
1178        }
1179
1180        fn usable_bits(&self) -> usize {
1181            0
1182        }
1183    }
1184}
1185
1186#[cfg(all(test, any(feature = "v1", feature = "v6")))]
1187mod tests {
1188    use super::*;
1189
1190    #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))]
1191    use wasm_bindgen_test::*;
1192
1193    #[test]
1194    #[cfg_attr(
1195        all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1196        wasm_bindgen_test
1197    )]
1198    fn gregorian_unix_does_not_panic() {
1199        // Ensure timestamp conversions never panic
1200        Timestamp::unix_to_gregorian_ticks(u64::MAX, 0);
1201        Timestamp::unix_to_gregorian_ticks(0, u32::MAX);
1202        Timestamp::unix_to_gregorian_ticks(u64::MAX, u32::MAX);
1203
1204        Timestamp::gregorian_to_unix(u64::MAX);
1205    }
1206
1207    #[test]
1208    #[cfg_attr(
1209        all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1210        wasm_bindgen_test
1211    )]
1212    fn to_gregorian_truncates_to_usable_bits() {
1213        let ts = Timestamp::from_gregorian(123, u16::MAX);
1214
1215        assert_eq!((123, u16::MAX >> 2), ts.to_gregorian());
1216    }
1217}
1218
1219/// Tests for conversion between `std::time::SystemTime` and `Timestamp`.
1220#[cfg(all(test, feature = "std", not(miri)))]
1221mod test_conversion {
1222    use std::{
1223        convert::{TryFrom, TryInto},
1224        time::{Duration, SystemTime},
1225    };
1226
1227    use super::Timestamp;
1228
1229    // Components of an arbitrary timestamp with non-zero nanoseconds.
1230    const KNOWN_SECONDS: u64 = 1_501_520_400;
1231    const KNOWN_NANOS: u32 = 1_000;
1232
1233    fn known_system_time() -> SystemTime {
1234        SystemTime::UNIX_EPOCH
1235            .checked_add(Duration::new(KNOWN_SECONDS, KNOWN_NANOS))
1236            .unwrap()
1237    }
1238
1239    fn known_timestamp() -> Timestamp {
1240        Timestamp::from_unix_time(KNOWN_SECONDS, KNOWN_NANOS, 0, 0)
1241    }
1242
1243    #[test]
1244    fn to_system_time() {
1245        let st: SystemTime = known_timestamp().into();
1246
1247        assert_eq!(known_system_time(), st);
1248    }
1249
1250    #[test]
1251    fn from_system_time() {
1252        let ts: Timestamp = known_system_time().try_into().unwrap();
1253
1254        assert_eq!(known_timestamp(), ts);
1255    }
1256
1257    #[test]
1258    fn from_system_time_before_epoch() {
1259        let before_epoch = match SystemTime::UNIX_EPOCH.checked_sub(Duration::from_nanos(1_000)) {
1260            Some(st) => st,
1261            None => return,
1262        };
1263
1264        Timestamp::try_from(before_epoch)
1265            .expect_err("Timestamp should not be created from before epoch");
1266    }
1267}