Skip to main content

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