Coverage Report

Created: 2026-11-12 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/uuid-1.29.2/src/timestamp.rs
Line
Count
Source
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
24
use core::cmp;
25
26
use 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`).
30
pub 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)]
43
pub struct Timestamp {
44
    unix_nanos: u128,
45
    counter: u128,
46
    usable_counter_bits: u8,
47
}
48
49
impl Timestamp {
50
    /// Get a timestamp representing the current system time and up to a 128-bit counter.
51
    ///
52
    /// This method defers to the standard library's `SystemTime` type.
53
    #[cfg(feature = "std")]
54
0
    pub fn now(context: impl ClockSequence<Output = impl Into<u128>>) -> Self {
55
0
        let (seconds, subsec_nanos) = nanos_to_parts(now());
56
57
0
        let (counter, seconds, subsec_nanos) =
58
0
            context.generate_timestamp_sequence(seconds, subsec_nanos);
59
0
        let counter = counter.into();
60
0
        let usable_counter_bits = context.usable_bits() as u8;
61
62
0
        Timestamp {
63
0
            unix_nanos: parts_to_nanos(seconds, subsec_nanos),
64
0
            counter,
65
0
            usable_counter_bits,
66
0
        }
67
0
    }
68
69
    /// Construct a `Timestamp` from the number of 100 nanosecond ticks since 00:00:00.00,
70
    /// 15 October 1582 (the date of Gregorian reform to the Christian calendar) and a 14-bit
71
    /// counter, as used in versions 1 and 6 UUIDs.
72
    ///
73
    /// # Overflow
74
    ///
75
    /// If conversion from RFC 9562 ticks to the internal timestamp format would overflow
76
    /// it will wrap.
77
0
    pub const fn from_gregorian_time(ticks: u64, counter: u16) -> Self {
78
0
        let (seconds, subsec_nanos) = Self::gregorian_to_unix(ticks);
79
80
0
        Timestamp {
81
0
            unix_nanos: parts_to_nanos(seconds, subsec_nanos),
82
0
            counter: counter as u128,
83
0
            usable_counter_bits: 14,
84
0
        }
85
0
    }
86
87
    /// Construct a `Timestamp` from a Unix timestamp and up to a 128-bit counter, as used in version 7 UUIDs.
88
0
    pub const fn from_unix_time(
89
0
        seconds: u64,
90
0
        subsec_nanos: u32,
91
0
        counter: u128,
92
0
        usable_counter_bits: u8,
93
0
    ) -> Self {
94
0
        Timestamp {
95
0
            unix_nanos: parts_to_nanos(seconds, subsec_nanos),
96
0
            counter,
97
0
            usable_counter_bits,
98
0
        }
99
0
    }
100
101
    /// Construct a `Timestamp` from a Unix timestamp and up to a 128-bit counter, as used in version 7 UUIDs.
102
0
    pub fn from_unix(
103
0
        context: impl ClockSequence<Output = impl Into<u128>>,
104
0
        seconds: u64,
105
0
        subsec_nanos: u32,
106
0
    ) -> Self {
107
0
        let (counter, seconds, subsec_nanos) =
108
0
            context.generate_timestamp_sequence(seconds, subsec_nanos);
109
0
        let counter = counter.into();
110
0
        let usable_counter_bits = context.usable_bits() as u8;
111
112
0
        Timestamp {
113
0
            unix_nanos: parts_to_nanos(seconds, subsec_nanos),
114
0
            counter,
115
0
            usable_counter_bits,
116
0
        }
117
0
    }
118
119
    /// Get the value of the timestamp as the number of 100 nanosecond ticks since 00:00:00.00,
120
    /// 15 October 1582 and a 14-bit counter, as used in versions 1 and 6 UUIDs.
121
    ///
122
    /// # Overflow
123
    ///
124
    /// If conversion from the internal timestamp format to ticks would overflow
125
    /// then it will wrap.
126
    ///
127
    /// If the internal counter is wider than 14 bits then it will be truncated to 14 bits.
128
0
    pub const fn to_gregorian(&self) -> (u64, u16) {
129
0
        let (seconds, subsec_nanos) = nanos_to_parts(self.unix_nanos);
130
131
0
        (
132
0
            Self::unix_to_gregorian_ticks(seconds, subsec_nanos),
133
0
            (self.counter as u16) & 0x3FFF,
134
0
        )
135
0
    }
136
137
    // NOTE: This method is not public; the usable counter bits are lost in a version 7 UUID
138
    // so can't be reliably recovered.
139
    #[cfg(feature = "v7")]
140
    pub(crate) const fn counter(&self) -> (u128, u8) {
141
        (self.counter, self.usable_counter_bits)
142
    }
143
144
    /// Get the value of the timestamp as a Unix timestamp, as used in version 7 UUIDs.
145
0
    pub const fn to_unix(&self) -> (u64, u32) {
146
0
        nanos_to_parts(self.unix_nanos)
147
0
    }
148
149
0
    const fn unix_to_gregorian_ticks(seconds: u64, nanos: u32) -> u64 {
150
        UUID_TICKS_BETWEEN_EPOCHS
151
0
            .wrapping_add(seconds.wrapping_mul(10_000_000))
152
0
            .wrapping_add(nanos as u64 / 100)
153
0
    }
154
155
0
    const fn gregorian_to_unix(ticks: u64) -> (u64, u32) {
156
0
        (
157
0
            ticks.wrapping_sub(UUID_TICKS_BETWEEN_EPOCHS) / 10_000_000,
158
0
            (ticks.wrapping_sub(UUID_TICKS_BETWEEN_EPOCHS) % 10_000_000) as u32 * 100,
159
0
        )
160
0
    }
161
}
162
163
#[doc(hidden)]
164
impl Timestamp {
165
    #[deprecated(
166
        since = "1.10.0",
167
        note = "use `Timestamp::from_gregorian_time(ticks, counter)`"
168
    )]
169
0
    pub const fn from_rfc4122(ticks: u64, counter: u16) -> Self {
170
0
        Timestamp::from_gregorian_time(ticks, counter)
171
0
    }
172
173
    #[deprecated(since = "1.10.0", note = "use `Timestamp::to_gregorian()`")]
174
0
    pub const fn to_rfc4122(&self) -> (u64, u16) {
175
0
        self.to_gregorian()
176
0
    }
177
178
    #[deprecated(
179
        since = "1.2.0",
180
        note = "`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`"
181
    )]
182
0
    pub const fn to_unix_nanos(&self) -> u32 {
183
0
        panic!("`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`")
184
    }
185
186
    #[deprecated(
187
        since = "1.23.0",
188
        note = "use `Timestamp::from_gregorian_time(ticks, counter)`"
189
    )]
190
0
    pub const fn from_gregorian(ticks: u64, counter: u16) -> Self {
191
0
        Timestamp::from_gregorian_time(ticks, counter)
192
0
    }
193
}
194
195
#[cfg(feature = "std")]
196
impl TryFrom<std::time::SystemTime> for Timestamp {
197
    type Error = crate::Error;
198
199
    /// Perform the conversion.
200
    ///
201
    /// This method will fail if the system time is earlier than the Unix Epoch.
202
    /// On some platforms it may panic instead.
203
0
    fn try_from(st: std::time::SystemTime) -> Result<Self, Self::Error> {
204
0
        let dur = st.duration_since(std::time::UNIX_EPOCH).map_err(|_| {
205
0
            crate::Error(crate::error::ErrorKind::InvalidSystemTime(
206
0
                "unable to convert the system tie into a Unix timestamp",
207
0
            ))
208
0
        })?;
209
210
0
        Ok(Self::from_unix_time(
211
0
            dur.as_secs(),
212
0
            dur.subsec_nanos(),
213
0
            0,
214
0
            0,
215
0
        ))
216
0
    }
217
}
218
219
#[cfg(feature = "std")]
220
impl From<Timestamp> for std::time::SystemTime {
221
    /// Perform the conversion.
222
    ///
223
    /// If the conversion would fail, an undefined `SystemTime` will be returned instead.
224
    /// This can happen if the `Timestamp` would overflow the max value allowed by `SystemTime` on the target platform.
225
    /// Use `TryFrom` to catch conversion failures and handle them explicitly.
226
0
    fn from(ts: Timestamp) -> Self {
227
0
        let (seconds, subsec_nanos) = ts.to_unix();
228
229
        // NOTE: The actual value on overflow is undefined and may change
230
        // See: https://github.com/rust-lang/rust/issues/151199
231
0
        std::time::Duration::from_secs(seconds)
232
0
            .checked_add(std::time::Duration::from_nanos(subsec_nanos as u64))
233
0
            .and_then(|dur| Self::UNIX_EPOCH.checked_add(dur))
234
0
            .unwrap_or(std::time::SystemTime::UNIX_EPOCH)
235
0
    }
236
}
237
238
0
pub(crate) const fn encode_gregorian_timestamp(
239
0
    ticks: u64,
240
0
    counter: u16,
241
0
    node_id: &[u8; 6],
242
0
) -> Uuid {
243
0
    let time_low = (ticks & 0xFFFF_FFFF) as u32;
244
0
    let time_mid = ((ticks >> 32) & 0xFFFF) as u16;
245
0
    let time_high_and_version = (((ticks >> 48) & 0x0FFF) as u16) | (1 << 12);
246
247
0
    let mut d4 = [0; 8];
248
249
0
    d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
250
0
    d4[1] = (counter & 0xFF) as u8;
251
0
    d4[2] = node_id[0];
252
0
    d4[3] = node_id[1];
253
0
    d4[4] = node_id[2];
254
0
    d4[5] = node_id[3];
255
0
    d4[6] = node_id[4];
256
0
    d4[7] = node_id[5];
257
258
0
    Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
259
0
}
260
261
0
pub(crate) const fn decode_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
262
0
    let bytes = uuid.as_bytes();
263
264
0
    let ticks: u64 = ((bytes[6] & 0x0F) as u64) << 56
265
0
        | (bytes[7] as u64) << 48
266
0
        | (bytes[4] as u64) << 40
267
0
        | (bytes[5] as u64) << 32
268
0
        | (bytes[0] as u64) << 24
269
0
        | (bytes[1] as u64) << 16
270
0
        | (bytes[2] as u64) << 8
271
0
        | (bytes[3] as u64);
272
273
0
    let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
274
275
0
    (ticks, counter)
276
0
}
277
278
0
pub(crate) const fn encode_sorted_gregorian_timestamp(
279
0
    ticks: u64,
280
0
    counter: u16,
281
0
    node_id: &[u8; 6],
282
0
) -> Uuid {
283
0
    let time_high = ((ticks >> 28) & 0xFFFF_FFFF) as u32;
284
0
    let time_mid = ((ticks >> 12) & 0xFFFF) as u16;
285
0
    let time_low_and_version = ((ticks & 0x0FFF) as u16) | (0x6 << 12);
286
287
0
    let mut d4 = [0; 8];
288
289
0
    d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
290
0
    d4[1] = (counter & 0xFF) as u8;
291
0
    d4[2] = node_id[0];
292
0
    d4[3] = node_id[1];
293
0
    d4[4] = node_id[2];
294
0
    d4[5] = node_id[3];
295
0
    d4[6] = node_id[4];
296
0
    d4[7] = node_id[5];
297
298
0
    Uuid::from_fields(time_high, time_mid, time_low_and_version, &d4)
299
0
}
300
301
0
pub(crate) const fn decode_sorted_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
302
0
    let bytes = uuid.as_bytes();
303
304
0
    let ticks: u64 = ((bytes[0]) as u64) << 52
305
0
        | (bytes[1] as u64) << 44
306
0
        | (bytes[2] as u64) << 36
307
0
        | (bytes[3] as u64) << 28
308
0
        | (bytes[4] as u64) << 20
309
0
        | (bytes[5] as u64) << 12
310
0
        | ((bytes[6] & 0xF) as u64) << 8
311
0
        | (bytes[7] as u64);
312
313
0
    let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
314
315
0
    (ticks, counter)
316
0
}
317
318
0
pub(crate) const fn encode_unix_timestamp_millis(
319
0
    millis: u64,
320
0
    counter_random_bytes: &[u8; 10],
321
0
) -> Uuid {
322
0
    let millis_high = ((millis >> 16) & 0xFFFF_FFFF) as u32;
323
0
    let millis_low = (millis & 0xFFFF) as u16;
324
325
0
    let counter_random_version = (counter_random_bytes[1] as u16
326
0
        | ((counter_random_bytes[0] as u16) << 8) & 0x0FFF)
327
0
        | (0x7 << 12);
328
329
0
    let mut d4 = [0; 8];
330
331
0
    d4[0] = (counter_random_bytes[2] & 0x3F) | 0x80;
332
0
    d4[1] = counter_random_bytes[3];
333
0
    d4[2] = counter_random_bytes[4];
334
0
    d4[3] = counter_random_bytes[5];
335
0
    d4[4] = counter_random_bytes[6];
336
0
    d4[5] = counter_random_bytes[7];
337
0
    d4[6] = counter_random_bytes[8];
338
0
    d4[7] = counter_random_bytes[9];
339
340
0
    Uuid::from_fields(millis_high, millis_low, counter_random_version, &d4)
341
0
}
342
343
0
pub(crate) const fn decode_unix_timestamp_millis(uuid: &Uuid) -> u64 {
344
0
    let bytes = uuid.as_bytes();
345
346
0
    let millis: u64 = (bytes[0] as u64) << 40
347
0
        | (bytes[1] as u64) << 32
348
0
        | (bytes[2] as u64) << 24
349
0
        | (bytes[3] as u64) << 16
350
0
        | (bytes[4] as u64) << 8
351
0
        | (bytes[5] as u64);
352
353
0
    millis
354
0
}
355
356
#[cfg(all(
357
    feature = "std",
358
    feature = "js",
359
    all(target_family = "wasm", any(target_os = "unknown", target_os = "none"))
360
))]
361
fn now() -> u128 {
362
    use wasm_bindgen::prelude::*;
363
364
    #[wasm_bindgen]
365
    extern "C" {
366
        // NOTE: This signature works around https://bugzilla.mozilla.org/show_bug.cgi?id=1787770
367
        #[wasm_bindgen(js_namespace = Date, catch)]
368
        fn now() -> Result<f64, JsValue>;
369
    }
370
371
    let now = now().unwrap_throw();
372
373
    (now * 1_000_000.0) as u128
374
}
375
376
#[cfg(all(
377
    feature = "std",
378
    not(miri),
379
    any(
380
        not(feature = "js"),
381
        not(all(target_family = "wasm", any(target_os = "unknown", target_os = "none")))
382
    )
383
))]
384
0
fn now() -> u128 {
385
0
    let dur = std::time::SystemTime::UNIX_EPOCH.elapsed().expect(
386
0
        "Getting elapsed time since UNIX_EPOCH. If this fails, we've somehow violated causality",
387
    );
388
389
0
    dur.as_nanos()
390
0
}
391
392
#[cfg(all(feature = "std", miri))]
393
fn now() -> u128 {
394
    use std::{sync::Mutex, time::Duration};
395
396
    static TS: Mutex<u128> = Mutex::new(0);
397
398
    let mut ts = TS.lock().unwrap();
399
    *ts += 1;
400
    *ts
401
}
402
403
/**
404
Convert a 128bit nanosecond value into a pair of 64bit seconds, and 32bit subsecond nanos.
405
406
The 32bit subsecond nano value is normalized to be less than `1_000_000_000` wherever the 64bit
407
seconds can hold the carry. Above `(u64::MAX, 999_999_999)` the remainder is left in the subsecond
408
nanos instead, so every value produced by `parts_to_nanos` converts back exactly.
409
410
Only values beyond `(u64::MAX, u32::MAX)` saturate to it. A `Timestamp` never holds one.
411
*/
412
0
const fn nanos_to_parts(nanos: u128) -> (u64, u32) {
413
    const MAX_NANOS: u128 = parts_to_nanos(u64::MAX, u32::MAX);
414
415
0
    if nanos > MAX_NANOS {
416
0
        return (u64::MAX, u32::MAX);
417
0
    }
418
419
0
    let secs = nanos / 1_000_000_000;
420
421
0
    if secs > u64::MAX as u128 {
422
        // Seconds can't take the carry, so leave the rest in the subsecond nanos (at most `u32::MAX`)
423
0
        (u64::MAX, (nanos - u64::MAX as u128 * 1_000_000_000) as u32)
424
    } else {
425
0
        (secs as u64, (nanos % 1_000_000_000) as u32)
426
    }
427
0
}
428
429
/**
430
Convert a potentially un-normalized part of 64bit seconds and 32bit subsecond nanos to a single
431
128bit number of nanoseconds.
432
433
This function will never overflow. `subsec_nanos` isn't required to be less than `1_000_000_000`.
434
*/
435
0
const fn parts_to_nanos(secs: u64, subsec_nanos: u32) -> u128 {
436
0
    (secs as u128 * 1_000_000_000) + subsec_nanos as u128
437
0
}
438
439
/// A counter that can be used by versions 1 and 6 UUIDs to support
440
/// the uniqueness of timestamps.
441
///
442
/// # References
443
///
444
/// * [UUID Version 1 in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-5.1)
445
/// * [UUID Version 6 in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-5.6)
446
/// * [UUID Generator States in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-6.3)
447
pub trait ClockSequence {
448
    /// The type of sequence returned by this counter.
449
    type Output;
450
451
    /// Get the next value in the sequence to feed into a timestamp.
452
    ///
453
    /// This method will be called each time a [`Timestamp`] is constructed.
454
    ///
455
    /// Any bits beyond [`ClockSequence::usable_bits`] in the output must be unset.
456
    ///
457
    /// Note that a caller is not required to pass normalized values, so `subsec_nanos` may
458
    /// be greater than the actual number of nanoseconds in a second (1,000,000,000).
459
    /// Implementations are also not required to return normalized values, but values
460
    /// outside the range supported by a given UUID variant may weaken uniqueness or monotonicity.
461
    fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output;
462
463
    /// Get the next value in the sequence, potentially also adjusting the timestamp.
464
    ///
465
    /// This method should be preferred over `generate_sequence`.
466
    ///
467
    /// Any bits beyond [`ClockSequence::usable_bits`] in the output must be unset.
468
    ///
469
    /// Note that a caller is not required to pass normalized values, so `subsec_nanos` may
470
    /// be greater than the actual number of nanoseconds in a second (1,000,000,000).
471
    /// Implementations are also not required to return normalized values, but values
472
    /// outside the range supported by a given UUID variant may weaken uniqueness or monotonicity.
473
    ///
474
    /// The returned timestamp isn't required to be normalized either. Any `(seconds, subsec_nanos)`
475
    /// value is preserved exactly by [`Timestamp`], and [`Timestamp::to_unix`] normalizes it where possible.
476
0
    fn generate_timestamp_sequence(
477
0
        &self,
478
0
        seconds: u64,
479
0
        subsec_nanos: u32,
480
0
    ) -> (Self::Output, u64, u32) {
481
0
        (
482
0
            self.generate_sequence(seconds, subsec_nanos),
483
0
            seconds,
484
0
            subsec_nanos,
485
0
        )
486
0
    }
487
488
    /// The number of usable bits from the least significant bit in the result of [`ClockSequence::generate_sequence`]
489
    /// or [`ClockSequence::generate_timestamp_sequence`].
490
    ///
491
    /// The number of usable bits must not exceed 128.
492
    ///
493
    /// The number of usable bits is not expected to change between calls. An implementation of `ClockSequence` should
494
    /// always return the same value from this method.
495
0
    fn usable_bits(&self) -> usize
496
0
    where
497
0
        Self::Output: Sized,
498
    {
499
0
        cmp::min(128, core::mem::size_of::<Self::Output>() * 8)
500
0
    }
501
}
502
503
impl<T: ClockSequence + ?Sized> ClockSequence for &T {
504
    type Output = T::Output;
505
506
0
    fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
507
0
        (**self).generate_sequence(seconds, subsec_nanos)
508
0
    }
509
510
0
    fn generate_timestamp_sequence(
511
0
        &self,
512
0
        seconds: u64,
513
0
        subsec_nanos: u32,
514
0
    ) -> (Self::Output, u64, u32) {
515
0
        (**self).generate_timestamp_sequence(seconds, subsec_nanos)
516
0
    }
517
518
0
    fn usable_bits(&self) -> usize
519
0
    where
520
0
        Self::Output: Sized,
521
    {
522
0
        (**self).usable_bits()
523
0
    }
524
}
525
526
/// Default implementations for the [`ClockSequence`] trait.
527
pub mod context {
528
    use super::ClockSequence;
529
530
    #[cfg(any(feature = "v1", feature = "v6"))]
531
    mod v1_support {
532
        use super::*;
533
534
        #[cfg(all(feature = "std", feature = "rng"))]
535
        use crate::std::sync::LazyLock;
536
537
        use atomic::{Atomic, Ordering};
538
539
        #[cfg(all(feature = "std", feature = "rng"))]
540
        static CONTEXT: LazyLock<ContextV1> = LazyLock::new(ContextV1::new_random);
541
542
        #[cfg(all(feature = "std", feature = "rng"))]
543
        pub(crate) fn shared_context_v1() -> &'static ContextV1 {
544
            &CONTEXT
545
        }
546
547
        /// An internally synchronized, wrapping counter that produces 14-bit values for version 1 and version 6 UUIDs.
548
        ///
549
        /// This type is:
550
        ///
551
        /// - **Non-reseeding:** The counter is not reseeded on each time interval (100ns).
552
        /// - **Non-adjusting:** The timestamp is not incremented when the counter wraps within a time interval (100ns).
553
        /// - **Thread-safe:** The underlying counter is atomic, so can be shared across threads.
554
        ///
555
        /// This type should be used when constructing versions 1 and 6 UUIDs.
556
        ///
557
        /// This type should not be used when constructing version 7 UUIDs. When used to
558
        /// construct a version 7 UUID, the 14-bit counter will be padded with random data.
559
        /// Counter overflows are more likely with a 14-bit counter than they are with a
560
        /// 42-bit counter when working at millisecond precision. This type doesn't attempt
561
        /// to adjust the timestamp on overflow.
562
        #[derive(Debug)]
563
        pub struct ContextV1 {
564
            count: Atomic<u16>,
565
        }
566
567
        impl ContextV1 {
568
            /// Construct a new context that's initialized with the given value.
569
            ///
570
            /// The starting value should be a random number, so that UUIDs from
571
            /// different systems with the same timestamps are less likely to collide.
572
            /// When the `rng` feature is enabled, prefer the [`ContextV1::new_random`] method.
573
            pub const fn new(count: u16) -> Self {
574
                Self {
575
                    count: Atomic::<u16>::new(count),
576
                }
577
            }
578
579
            /// Construct a new context that's initialized with a random value.
580
            #[cfg(feature = "rng")]
581
            pub fn new_random() -> Self {
582
                Self {
583
                    count: Atomic::<u16>::new(crate::rng::u16()),
584
                }
585
            }
586
        }
587
588
        impl ClockSequence for ContextV1 {
589
            type Output = u16;
590
591
            fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
592
                // RFC 9562 reserves 2 bits of the clock sequence so the actual
593
                // maximum value is smaller than `u16::MAX`. Since we unconditionally
594
                // increment the clock sequence we want to wrap once it becomes larger
595
                // than what we can represent in a "u14". Otherwise there'd be patches
596
                // where the clock sequence doesn't change regardless of the timestamp
597
                self.count.fetch_add(1, Ordering::AcqRel) & (u16::MAX >> 2)
598
            }
599
600
            fn usable_bits(&self) -> usize {
601
                14
602
            }
603
        }
604
605
        #[deprecated(since = "1.23.0", note = "renamed to `ContextV1`")]
606
        #[doc(hidden)]
607
        pub type Context = ContextV1;
608
609
        #[cfg(test)]
610
        mod tests {
611
            use crate::Timestamp;
612
613
            use super::*;
614
615
            #[test]
616
            fn context() {
617
                let seconds = 1_496_854_535;
618
                let subsec_nanos = 812_946_000;
619
620
                let context = ContextV1::new(u16::MAX >> 2);
621
622
                let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
623
                assert_eq!(16383, ts.counter);
624
                assert_eq!(14, ts.usable_counter_bits);
625
626
                let seconds = 1_496_854_536;
627
628
                let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
629
                assert_eq!(0, ts.counter);
630
631
                let seconds = 1_496_854_535;
632
633
                let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
634
                assert_eq!(1, ts.counter);
635
            }
636
637
            #[test]
638
            fn context_overflow() {
639
                let seconds = u64::MAX;
640
                let subsec_nanos = u32::MAX;
641
642
                let context = ContextV1::new(u16::MAX);
643
644
                // Ensure we don't panic
645
                Timestamp::from_unix(&context, seconds, subsec_nanos);
646
            }
647
        }
648
    }
649
650
    #[cfg(any(feature = "v1", feature = "v6"))]
651
    pub use v1_support::*;
652
653
    #[cfg(feature = "std")]
654
    mod std_support {
655
        use super::*;
656
657
        use core::panic::{AssertUnwindSafe, RefUnwindSafe};
658
        use std::{sync::Mutex, thread::LocalKey};
659
660
        /// A wrapper for a context that uses thread-local storage.
661
        pub struct ThreadLocalContext<C: 'static>(&'static LocalKey<C>);
662
663
        impl<C> std::fmt::Debug for ThreadLocalContext<C> {
664
0
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
665
0
                f.debug_struct("ThreadLocalContext").finish_non_exhaustive()
666
0
            }
667
        }
668
669
        impl<C: 'static> ThreadLocalContext<C> {
670
            /// Wrap a thread-local container with a context.
671
0
            pub const fn new(local_key: &'static LocalKey<C>) -> Self {
672
0
                ThreadLocalContext(local_key)
673
0
            }
674
        }
675
676
        impl<C: ClockSequence + 'static> ClockSequence for ThreadLocalContext<C> {
677
            type Output = C::Output;
678
679
0
            fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
680
0
                self.0
681
0
                    .with(|ctxt| ctxt.generate_sequence(seconds, subsec_nanos))
682
0
            }
683
684
0
            fn generate_timestamp_sequence(
685
0
                &self,
686
0
                seconds: u64,
687
0
                subsec_nanos: u32,
688
0
            ) -> (Self::Output, u64, u32) {
689
0
                self.0
690
0
                    .with(|ctxt| ctxt.generate_timestamp_sequence(seconds, subsec_nanos))
691
0
            }
692
693
0
            fn usable_bits(&self) -> usize {
694
0
                self.0.with(|ctxt| ctxt.usable_bits())
695
0
            }
696
        }
697
698
        impl<C: ClockSequence> ClockSequence for AssertUnwindSafe<C> {
699
            type Output = C::Output;
700
701
0
            fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
702
0
                self.0.generate_sequence(seconds, subsec_nanos)
703
0
            }
704
705
0
            fn generate_timestamp_sequence(
706
0
                &self,
707
0
                seconds: u64,
708
0
                subsec_nanos: u32,
709
0
            ) -> (Self::Output, u64, u32) {
710
0
                self.0.generate_timestamp_sequence(seconds, subsec_nanos)
711
0
            }
712
713
0
            fn usable_bits(&self) -> usize
714
0
            where
715
0
                Self::Output: Sized,
716
            {
717
0
                self.0.usable_bits()
718
0
            }
719
        }
720
721
        impl<C: ClockSequence + RefUnwindSafe> ClockSequence for Mutex<C> {
722
            type Output = C::Output;
723
724
0
            fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
725
0
                self.lock()
726
0
                    .unwrap_or_else(|err| err.into_inner())
727
0
                    .generate_sequence(seconds, subsec_nanos)
728
0
            }
729
730
0
            fn generate_timestamp_sequence(
731
0
                &self,
732
0
                seconds: u64,
733
0
                subsec_nanos: u32,
734
0
            ) -> (Self::Output, u64, u32) {
735
0
                self.lock()
736
0
                    .unwrap_or_else(|err| err.into_inner())
737
0
                    .generate_timestamp_sequence(seconds, subsec_nanos)
738
0
            }
739
740
0
            fn usable_bits(&self) -> usize
741
0
            where
742
0
                Self::Output: Sized,
743
            {
744
0
                self.lock()
745
0
                    .unwrap_or_else(|err| err.into_inner())
746
0
                    .usable_bits()
747
0
            }
748
        }
749
    }
750
751
    #[cfg(feature = "std")]
752
    pub use std_support::*;
753
754
    #[cfg(feature = "v7")]
755
    mod v7_support {
756
        use super::*;
757
758
        use crate::timestamp::parts_to_nanos;
759
        use core::{cell::Cell, cmp, panic::RefUnwindSafe};
760
761
        #[cfg(feature = "std")]
762
        static CONTEXT_V7: SharedContextV7 =
763
            SharedContextV7(std::sync::Mutex::new(ContextV7::new()));
764
765
        #[cfg(feature = "std")]
766
        pub(crate) fn shared_context_v7() -> &'static SharedContextV7 {
767
            &CONTEXT_V7
768
        }
769
770
        const USABLE_BITS: usize = 42;
771
772
        // Leave the most significant bit unset
773
        // This guarantees the counter has at least 2,199,023,255,552
774
        // values before it will overflow, which is exceptionally unlikely
775
        // even in the worst case
776
        const RESEED_MASK: u64 = u64::MAX >> 23;
777
        const MAX_COUNTER: u64 = u64::MAX >> 22;
778
779
        /// An unsynchronized, reseeding counter that produces 42-bit values for version 7 UUIDs.
780
        ///
781
        /// This type is:
782
        ///
783
        /// - **Reseeding:** The counter is reseeded on each time interval (1ms) with a random 41-bit value.
784
        ///   The 42nd bit is left unset so the counter can safely increment over the millisecond.
785
        /// - **Adjusting:** The timestamp is incremented when the counter wraps within a time interval (1ms).
786
        ///   All subsequent timestamps in that same interval will also be incremented until it changes and
787
        ///   the counter is reseeded.
788
        /// - **Non-thread-safe:** The underlying counter uses unsynchronized cells, so needs to be wrapped in
789
        ///   a mutex to share.
790
        ///
791
        /// The counter can use additional sub-millisecond precision from the timestamp to better
792
        /// synchronize UUID sorting in distributed systems. In these cases, the additional precision
793
        /// is masked into the left-most 12 bits of the counter. The counter is still reseeded on
794
        /// each new millisecond, and incremented within the millisecond. This behavior may change
795
        /// in the future. The only guarantee is monotonicity.
796
        ///
797
        /// This type can be used when constructing version 7 UUIDs. When used to construct a
798
        /// version 7 UUID, the 42-bit counter will be padded with random data. This type can
799
        /// be used to maintain ordering of UUIDs within the same millisecond.
800
        ///
801
        /// This type should not be used when constructing version 1 or version 6 UUIDs.
802
        /// When used to construct a version 1 or version 6 UUID, only the 14 least significant
803
        /// bits of the counter will be used.
804
        #[derive(Debug, Default)]
805
        pub struct ContextV7 {
806
            timestamp: Cell<ReseedingTimestamp>,
807
            counter: Cell<Counter>,
808
            adjust: Adjust,
809
            precision: Precision,
810
        }
811
812
        impl RefUnwindSafe for ContextV7 {}
813
814
        impl ContextV7 {
815
            /// Construct a new context that will reseed its counter on the first
816
            /// non-zero timestamp it receives.
817
            pub const fn new() -> Self {
818
                ContextV7 {
819
                    timestamp: Cell::new(ReseedingTimestamp {
820
                        last_seed: 0,
821
                        unix_nanos: 0,
822
                    }),
823
                    counter: Cell::new(Counter { value: 0 }),
824
                    adjust: Adjust { by_ns: 0 },
825
                    precision: Precision {
826
                        bits: 0,
827
                        mask: 0,
828
                        factor: 0,
829
                        shift: 0,
830
                    },
831
                }
832
            }
833
834
            /// Specify an amount to shift timestamps by to obfuscate their actual generation time.
835
            pub fn with_adjust_by_millis(mut self, millis: u32) -> Self {
836
                self.adjust = Adjust::by_millis(millis);
837
                self
838
            }
839
840
            /// Use the leftmost 12 bits of the counter for additional timestamp precision.
841
            ///
842
            /// This method can provide better sorting for distributed applications that generate frequent UUIDs
843
            /// by trading a small amount of entropy for better counter synchronization. Note that the counter
844
            /// will still be reseeded on millisecond boundaries, even though some of its storage will be
845
            /// dedicated to the timestamp.
846
            pub fn with_additional_precision(self) -> Self {
847
                self.with_additional_precision_bits(12)
848
            }
849
850
            /// Use the leftmost `bits` bits of the counter for additional timestamp precision.
851
            ///
852
            /// This is a more general form of [`ContextV7::with_additional_precision`] for platforms
853
            /// whose clocks don't have the resolution to make use of the full 12 bits. A platform with
854
            /// microsecond precision can set 10 bits here, leaving the remaining 2 bits of the `rand_a`
855
            /// field free for random data.
856
            ///
857
            /// `bits` is capped at 12, matching the size of the `rand_a` field in a version 7 UUID.
858
            /// Passing 0 disables additional precision, the same as never calling this method.
859
            pub fn with_additional_precision_bits(mut self, bits: usize) -> Self {
860
                self.precision = Precision::new(cmp::min(bits, 12));
861
                self
862
            }
863
        }
864
865
        impl ClockSequence for ContextV7 {
866
            type Output = u64;
867
868
            fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
869
                self.generate_timestamp_sequence(seconds, subsec_nanos).0
870
            }
871
872
            fn generate_timestamp_sequence(
873
                &self,
874
                seconds: u64,
875
                subsec_nanos: u32,
876
            ) -> (Self::Output, u64, u32) {
877
                let unix_nanos = self.adjust.apply(parts_to_nanos(seconds, subsec_nanos));
878
879
                let mut counter;
880
                let (mut timestamp, should_reseed) = self.timestamp.get().advance(unix_nanos);
881
882
                if should_reseed {
883
                    // If the observed system time has shifted forwards then regenerate the counter
884
                    counter = Counter::reseed(&self.precision, &timestamp);
885
                } else {
886
                    // If the observed system time has not shifted forwards then increment the counter
887
888
                    // If the incoming timestamp is earlier than the last observed one then
889
                    // use it instead. This may happen if the system clock jitters, or if the counter
890
                    // has wrapped and the timestamp is artificially incremented
891
892
                    counter = self.counter.get().increment(&self.precision, &timestamp);
893
894
                    // Unlikely: If the counter has overflowed its 42-bit storage then wrap it
895
                    // and increment the timestamp. Until the observed system time shifts past
896
                    // this incremented value, all timestamps will use it to maintain monotonicity
897
                    if counter.has_overflowed() {
898
                        // Increment the timestamp by 1 milli and reseed the counter
899
                        timestamp = timestamp.increment();
900
                        counter = Counter::reseed(&self.precision, &timestamp);
901
                    }
902
                };
903
904
                self.timestamp.set(timestamp);
905
                self.counter.set(counter);
906
907
                let (seconds, subsec_nanos) = timestamp.to_parts();
908
909
                (counter.value, seconds, subsec_nanos)
910
            }
911
912
            fn usable_bits(&self) -> usize {
913
                USABLE_BITS
914
            }
915
        }
916
917
        /// A timestamp that keeps track of whether a reseed is necessary.
918
        #[derive(Debug, Default, Clone, Copy)]
919
        struct ReseedingTimestamp {
920
            last_seed: u64,
921
            unix_nanos: u128,
922
        }
923
924
        impl ReseedingTimestamp {
925
            #[inline]
926
            fn saturating_from_unix_nanos(unix_nanos: u128) -> Self {
927
                const MAX_UNIX_NANOS: u128 = (u64::MAX as u128) * 1_000_000 + 999_999;
928
929
                let unix_nanos = cmp::min(unix_nanos, MAX_UNIX_NANOS);
930
931
                // Reseed when the millisecond advances
932
                let last_seed = (unix_nanos / 1_000_000) as u64;
933
934
                ReseedingTimestamp {
935
                    last_seed,
936
                    unix_nanos,
937
                }
938
            }
939
940
            #[inline]
941
            fn to_parts(&self) -> (u64, u32) {
942
                // Guaranteed never to overflow `(u64::MAX, 999_999_999)`
943
                (
944
                    (self.unix_nanos / 1_000_000_000) as u64,
945
                    (self.unix_nanos % 1_000_000_000) as u32,
946
                )
947
            }
948
949
            /// Advance the timestamp to a new value, returning whether a reseed is necessary.
950
            #[inline]
951
            fn advance(&self, unix_nanos: u128) -> (Self, bool) {
952
                let incoming = ReseedingTimestamp::saturating_from_unix_nanos(unix_nanos);
953
954
                (
955
                    ReseedingTimestamp::saturating_from_unix_nanos(cmp::max(
956
                        self.unix_nanos,
957
                        unix_nanos,
958
                    )),
959
                    incoming.last_seed > self.last_seed,
960
                )
961
            }
962
963
            /// Advance the timestamp by a millisecond.
964
            #[inline]
965
            fn increment(&self) -> Self {
966
                ReseedingTimestamp::saturating_from_unix_nanos(
967
                    Adjust::by_millis(1).apply(self.unix_nanos),
968
                )
969
            }
970
        }
971
972
        /// A counter that initializes to a safe random seed and tracks overflow.
973
        #[derive(Debug, Default, Clone, Copy)]
974
        struct Counter {
975
            value: u64,
976
        }
977
978
        impl Counter {
979
            #[inline]
980
            fn reseed(precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
981
                Counter {
982
                    value: precision.apply(crate::rng::u64() & RESEED_MASK, timestamp),
983
                }
984
            }
985
986
            /// Advance the counter.
987
            ///
988
            /// This method is guaranteed to return a counter with a higher value than the current one.
989
            /// Additional precision from the timestamp will be used, unless it cause the counter
990
            /// to shift backwards.
991
            #[inline]
992
            fn increment(&self, precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
993
                // We unconditionally increment the counter even though the precision
994
                // may have set higher bits anyway. This could technically be avoided,
995
                // but the higher bits are a coarse approximation so we just avoid the
996
                // `if` branch and increment it either way
997
998
                // Guaranteed to never overflow u64
999
                let next = self.value + 1;
1000
1001
                Counter {
1002
                    value: cmp::max(next, precision.apply(next, timestamp)),
1003
                }
1004
            }
1005
1006
            #[inline]
1007
            fn has_overflowed(&self) -> bool {
1008
                self.value > MAX_COUNTER
1009
            }
1010
        }
1011
1012
        /// A utility that adjusts an input timestamp by a given number of nanoseconds.
1013
        #[derive(Debug, Default)]
1014
        struct Adjust {
1015
            by_ns: u128,
1016
        }
1017
1018
        impl Adjust {
1019
            #[inline]
1020
            fn by_millis(millis: u32) -> Self {
1021
                Adjust {
1022
                    by_ns: (millis as u128).saturating_mul(1_000_000),
1023
                }
1024
            }
1025
1026
            /// Apply the adjustment, returning the adjusted timestamp.
1027
            #[inline]
1028
            fn apply(&self, nanos: u128) -> u128 {
1029
                nanos.saturating_add(self.by_ns)
1030
            }
1031
        }
1032
1033
        /// A utility that overwrites some number of counter bits with additional timestamp precision.
1034
        #[derive(Debug, Default)]
1035
        struct Precision {
1036
            bits: usize,
1037
            factor: u64,
1038
            mask: u64,
1039
            shift: u64,
1040
        }
1041
1042
        impl Precision {
1043
            fn new(bits: usize) -> Self {
1044
                // The mask and shift are used to paste the sub-millisecond precision
1045
                // into the most significant bits of the counter
1046
                let mask = u64::MAX >> (64 - USABLE_BITS + bits);
1047
                let shift = (USABLE_BITS - bits) as u64;
1048
1049
                // The factor reduces the size of the sub-millisecond precision to
1050
                // fit into the specified number of bits
1051
                let factor = (999_999 / u64::pow(2, bits as u32)) + 1;
1052
1053
                Precision {
1054
                    bits,
1055
                    factor,
1056
                    mask,
1057
                    shift,
1058
                }
1059
            }
1060
1061
            /// Apply additional precision from the given timestamp to the counter.
1062
            #[inline]
1063
            fn apply(&self, counter: u64, timestamp: &ReseedingTimestamp) -> u64 {
1064
                if self.bits == 0 {
1065
                    // No additional precision is being used
1066
                    return counter;
1067
                }
1068
1069
                let additional = (timestamp.unix_nanos % 1_000_000) as u64 / self.factor;
1070
1071
                (counter & self.mask) | (additional << self.shift)
1072
            }
1073
        }
1074
1075
        #[cfg(feature = "std")]
1076
        pub(crate) struct SharedContextV7(std::sync::Mutex<ContextV7>);
1077
1078
        #[cfg(feature = "std")]
1079
        impl ClockSequence for SharedContextV7 {
1080
            type Output = u64;
1081
1082
            fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
1083
                self.0.generate_sequence(seconds, subsec_nanos)
1084
            }
1085
1086
            fn generate_timestamp_sequence(
1087
                &self,
1088
                seconds: u64,
1089
                subsec_nanos: u32,
1090
            ) -> (Self::Output, u64, u32) {
1091
                self.0.generate_timestamp_sequence(seconds, subsec_nanos)
1092
            }
1093
1094
            fn usable_bits(&self) -> usize
1095
            where
1096
                Self::Output: Sized,
1097
            {
1098
                USABLE_BITS
1099
            }
1100
        }
1101
1102
        #[cfg(test)]
1103
        mod tests {
1104
            use core::time::Duration;
1105
            use std::boxed::Box;
1106
1107
            use super::*;
1108
1109
            use crate::{Timestamp, Uuid};
1110
1111
            fn builder(f: impl Fn() -> ContextV7 + 'static) -> Box<dyn Fn() -> ContextV7> {
1112
                Box::new(f)
1113
            }
1114
1115
            #[test]
1116
            fn context() {
1117
                let seconds = 1_496_854_535;
1118
                let subsec_nanos = 812_946_000;
1119
1120
                let context = ContextV7::new();
1121
1122
                let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1123
                assert_eq!(42, ts1.usable_counter_bits);
1124
1125
                // Backwards second
1126
                let seconds = 1_496_854_534;
1127
1128
                let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1129
1130
                // The backwards time should be ignored
1131
                // The counter should still increment
1132
                assert_eq!(ts1.unix_nanos, ts2.unix_nanos);
1133
                assert_eq!(ts1.counter + 1, ts2.counter);
1134
1135
                // Forwards second
1136
                let seconds = 1_496_854_536;
1137
1138
                let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1139
1140
                // The counter should have reseeded
1141
                assert_ne!(ts2.counter + 1, ts3.counter);
1142
                assert_ne!(0, ts3.counter);
1143
            }
1144
1145
            #[test]
1146
            fn context_wrap() {
1147
                let seconds = 1_496_854_535u64;
1148
                let subsec_nanos = 812_946_000u32;
1149
1150
                // This context will wrap
1151
                let context = ContextV7 {
1152
                    timestamp: Cell::new(ReseedingTimestamp::saturating_from_unix_nanos(
1153
                        parts_to_nanos(seconds, subsec_nanos),
1154
                    )),
1155
                    adjust: Adjust::by_millis(0),
1156
                    precision: Precision {
1157
                        bits: 0,
1158
                        mask: 0,
1159
                        factor: 0,
1160
                        shift: 0,
1161
                    },
1162
                    counter: Cell::new(Counter {
1163
                        value: u64::MAX >> 22,
1164
                    }),
1165
                };
1166
1167
                let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1168
1169
                // The timestamp should be incremented by 1ms
1170
                let expected_ts = Duration::new(seconds, subsec_nanos) + Duration::from_millis(1);
1171
                assert_eq!(expected_ts.as_secs(), ts.to_unix().0);
1172
                assert_eq!(expected_ts.subsec_nanos(), ts.to_unix().1);
1173
1174
                // The counter should have reseeded
1175
                assert!(ts.counter < (u64::MAX >> 22) as u128);
1176
                assert_ne!(0, ts.counter);
1177
            }
1178
1179
            #[test]
1180
            fn context_shift() {
1181
                let seconds = 1_496_854_535;
1182
                let subsec_nanos = 812_946_000;
1183
1184
                let context = ContextV7::new().with_adjust_by_millis(1);
1185
1186
                let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1187
1188
                assert_eq!((1_496_854_535, 813_946_000), ts.to_unix());
1189
            }
1190
1191
            #[test]
1192
            fn context_additional_precision() {
1193
                let seconds = 1_496_854_535;
1194
                let subsec_nanos = 812_946_000;
1195
1196
                let context = ContextV7::new().with_additional_precision();
1197
1198
                let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1199
1200
                // NOTE: Future changes in rounding may change this value slightly
1201
                assert_eq!(3861, ts1.counter >> 30);
1202
1203
                assert!(ts1.counter < (u64::MAX >> 22) as u128);
1204
1205
                // Generate another timestamp; it should continue to sort
1206
                let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1207
1208
                assert!(Uuid::new_v7(ts2) > Uuid::new_v7(ts1));
1209
1210
                // Generate another timestamp with an extra nanosecond
1211
                let subsec_nanos = subsec_nanos + 1;
1212
1213
                let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1214
1215
                assert!(Uuid::new_v7(ts3) > Uuid::new_v7(ts2));
1216
            }
1217
1218
            #[test]
1219
            fn context_additional_precision_bits() {
1220
                let seconds = 1_496_854_535;
1221
                let subsec_nanos = 812_946_000;
1222
1223
                // 10 bits leaves the low 2 bits of `rand_a` for random data, which suits
1224
                // platforms with microsecond precision
1225
                let context = ContextV7::new().with_additional_precision_bits(10);
1226
1227
                let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1228
1229
                // The submillisecond precision occupies the leftmost 10 of the 42 counter bits
1230
                // NOTE: Future changes in rounding may change this value slightly
1231
                assert_eq!(968, ts.counter >> 32);
1232
1233
                assert!(ts.counter < (u64::MAX >> 22) as u128);
1234
1235
                // The full method is just the 12-bit form of this one
1236
                let full = Timestamp::from_unix(
1237
                    &ContextV7::new().with_additional_precision(),
1238
                    seconds,
1239
                    subsec_nanos,
1240
                );
1241
                let bits12 = Timestamp::from_unix(
1242
                    &ContextV7::new().with_additional_precision_bits(12),
1243
                    seconds,
1244
                    subsec_nanos,
1245
                );
1246
                assert_eq!(full.counter >> 30, bits12.counter >> 30);
1247
1248
                // Values above 12 are capped at 12
1249
                let capped = Timestamp::from_unix(
1250
                    &ContextV7::new().with_additional_precision_bits(64),
1251
                    seconds,
1252
                    subsec_nanos,
1253
                );
1254
                assert_eq!(bits12.counter >> 30, capped.counter >> 30);
1255
1256
                // Zero bits disables additional precision entirely
1257
                let none = ContextV7::new().with_additional_precision_bits(0);
1258
                assert_eq!(0, none.precision.bits);
1259
            }
1260
1261
            #[test]
1262
            fn context_additional_precision_carry() {
1263
                let seconds = 1_496_854_535;
1264
                let subsec_nanos = 812_946_000;
1265
1266
                for bits in 1..=12 {
1267
                    let precision = Precision::new(bits);
1268
                    let timestamp = ReseedingTimestamp::saturating_from_unix_nanos(parts_to_nanos(
1269
                        seconds,
1270
                        subsec_nanos,
1271
                    ));
1272
1273
                    // This context will carry into the additional precision
1274
                    let context = ContextV7 {
1275
                        counter: Cell::new(Counter {
1276
                            value: precision.apply(u64::MAX, &timestamp),
1277
                        }),
1278
                        timestamp: Cell::new(timestamp),
1279
                        adjust: Adjust::by_millis(0),
1280
                        precision,
1281
                    };
1282
1283
                    let a = Timestamp::from_unix(&context, seconds, subsec_nanos);
1284
                    let b = Timestamp::from_unix(&context, seconds, subsec_nanos);
1285
                    let c = Timestamp::from_unix(&context, seconds, subsec_nanos);
1286
1287
                    assert!(Uuid::new_v7(a) < Uuid::new_v7(b), "a: {a:?} < b: {b:?}");
1288
                    assert!(Uuid::new_v7(b) < Uuid::new_v7(c), "b: {b:?} < c: {c:?}");
1289
                }
1290
            }
1291
1292
            #[test]
1293
            fn context_overflow() {
1294
                let seconds = u64::MAX;
1295
                let subsec_nanos = u32::MAX;
1296
1297
                // Ensure we don't panic
1298
                for context in [
1299
                    builder(|| ContextV7::new()),
1300
                    builder(|| ContextV7::new().with_additional_precision()),
1301
                    builder(|| ContextV7::new().with_adjust_by_millis(u32::MAX)),
1302
                    builder(|| {
1303
                        ContextV7::new()
1304
                            .with_additional_precision()
1305
                            .with_adjust_by_millis(u32::MAX)
1306
                    }),
1307
                ] {
1308
                    Timestamp::from_unix(&context(), seconds, subsec_nanos);
1309
                }
1310
            }
1311
1312
            #[test]
1313
            fn context_subsec_ordering() {
1314
                for context in [
1315
                    builder(|| ContextV7::new()),
1316
                    builder(|| ContextV7::new().with_additional_precision()),
1317
                    builder(|| ContextV7::new().with_adjust_by_millis(u32::MAX)),
1318
                    builder(|| {
1319
                        ContextV7::new()
1320
                            .with_additional_precision()
1321
                            .with_adjust_by_millis(u32::MAX)
1322
                    }),
1323
                ] {
1324
                    for (a, b, c) in [
1325
                        // Wall-clock order of incoming timestamps is b, a, c
1326
                        ((100, 0), (99, 2_000_000), (100, 1_000_000)),
1327
                        ((100, 0), (99, 1_000_900_000), (100, 1_000_000)),
1328
                    ] {
1329
                        let context = context();
1330
1331
                        // UUID order is a, b, c
1332
                        let a = Timestamp::from_unix(&context, a.0, a.1);
1333
                        let b = Timestamp::from_unix(&context, b.0, b.1);
1334
                        let c = Timestamp::from_unix(&context, c.0, c.1);
1335
1336
                        assert!(Uuid::new_v7(a) < Uuid::new_v7(b), "a: {a:?} < b: {b:?}");
1337
                        assert!(Uuid::new_v7(b) < Uuid::new_v7(c), "b: {b:?} < c: {c:?}");
1338
                    }
1339
                }
1340
            }
1341
1342
            #[test]
1343
            fn context_subsec_saturated_ordering() {
1344
                for context in [
1345
                    builder(|| ContextV7::new()),
1346
                    builder(|| ContextV7::new().with_additional_precision()),
1347
                    builder(|| ContextV7::new().with_adjust_by_millis(u32::MAX)),
1348
                    builder(|| {
1349
                        ContextV7::new()
1350
                            .with_additional_precision()
1351
                            .with_adjust_by_millis(u32::MAX)
1352
                    }),
1353
                ] {
1354
                    let context = context();
1355
1356
                    let secs = (u64::MAX / 1_000) + 1;
1357
1358
                    let a = Timestamp::from_unix(&context, secs, 900_000);
1359
                    let b = Timestamp::from_unix(&context, secs, 1_000_000);
1360
1361
                    assert!(Uuid::new_v7(a) < Uuid::new_v7(b), "a: {a:?} < b: {b:?}");
1362
                }
1363
            }
1364
1365
            #[test]
1366
            fn context_additional_precision_within_millisecond() {
1367
                let seconds = 1_496_854_535;
1368
                let subsec_nanos = 812_100_000;
1369
1370
                let context = ContextV7::new().with_additional_precision();
1371
1372
                let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1373
1374
                // Later in the same millisecond
1375
                let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos + 500_000);
1376
1377
                assert!(
1378
                    ts2.counter >> 30 > ts1.counter >> 30,
1379
                    "ts1: {ts1:?}, ts2: {ts2:?}"
1380
                );
1381
1382
                // Earlier in the same millisecond
1383
                let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1384
1385
                assert_eq!(
1386
                    ts2.counter >> 30,
1387
                    ts3.counter >> 30,
1388
                    "ts2: {ts2:?}, ts3: {ts3:?}"
1389
                );
1390
                assert_eq!(ts2.to_unix(), ts3.to_unix());
1391
1392
                assert!(Uuid::new_v7(ts1) < Uuid::new_v7(ts2));
1393
                assert!(Uuid::new_v7(ts2) < Uuid::new_v7(ts3));
1394
            }
1395
1396
            #[test]
1397
            fn reseeding_timestamp_saturating() {
1398
                const MAX_UNIX_NANOS: u128 = (u64::MAX as u128) * 1_000_000 + 999_999;
1399
                const MAX_PARTS: (u64, u32) = (u64::MAX / 1_000, 615_999_999);
1400
1401
                // Values at or below the ceiling pass through
1402
                let below =
1403
                    ReseedingTimestamp::saturating_from_unix_nanos(MAX_UNIX_NANOS - 1_000_000);
1404
                assert_eq!(MAX_UNIX_NANOS - 1_000_000, below.unix_nanos);
1405
                assert_eq!(u64::MAX - 1, below.last_seed);
1406
                assert_eq!((u64::MAX / 1_000, 614_999_999), below.to_parts());
1407
1408
                // Values beyond the ceiling are clamped to it
1409
                for unix_nanos in [
1410
                    MAX_UNIX_NANOS,
1411
                    MAX_UNIX_NANOS + 1,
1412
                    parts_to_nanos(u64::MAX / 1_000 + 1, 0),
1413
                    parts_to_nanos(u64::MAX, 999_999_999),
1414
                    parts_to_nanos(u64::MAX, u32::MAX),
1415
                    u128::MAX,
1416
                ] {
1417
                    let ts = ReseedingTimestamp::saturating_from_unix_nanos(unix_nanos);
1418
1419
                    assert_eq!(MAX_UNIX_NANOS, ts.unix_nanos, "{unix_nanos}");
1420
                    assert_eq!(u64::MAX, ts.last_seed, "{unix_nanos}");
1421
                    assert_eq!(MAX_PARTS, ts.to_parts(), "{unix_nanos}");
1422
                }
1423
1424
                // Incrementing at the ceiling stays there instead of wrapping
1425
                let max = ReseedingTimestamp::saturating_from_unix_nanos(MAX_UNIX_NANOS);
1426
                let incremented = max.increment();
1427
                assert_eq!(MAX_UNIX_NANOS, incremented.unix_nanos);
1428
                assert_eq!(u64::MAX, incremented.last_seed);
1429
            }
1430
1431
            #[test]
1432
            fn context_saturated_parts() {
1433
                const MAX_PARTS: (u64, u32) = (u64::MAX / 1_000, 615_999_999);
1434
1435
                for context in [
1436
                    builder(|| ContextV7::new()),
1437
                    builder(|| ContextV7::new().with_adjust_by_millis(u32::MAX)),
1438
                ] {
1439
                    for (seconds, subsec_nanos) in [
1440
                        MAX_PARTS,
1441
                        (u64::MAX / 1_000 + 1, 0),
1442
                        (u64::MAX, 999_999_999),
1443
                        (u64::MAX, u32::MAX),
1444
                    ] {
1445
                        let ts = Timestamp::from_unix(&context(), seconds, subsec_nanos);
1446
1447
                        assert_eq!(MAX_PARTS, ts.to_unix(), "{seconds}, {subsec_nanos}");
1448
                    }
1449
                }
1450
1451
                // A counter overflow at the ceiling can't advance the timestamp, but it mustn't wrap it either
1452
                let context = ContextV7 {
1453
                    timestamp: Cell::new(ReseedingTimestamp::saturating_from_unix_nanos(u128::MAX)),
1454
                    adjust: Adjust::by_millis(0),
1455
                    precision: Precision::new(0),
1456
                    counter: Cell::new(Counter {
1457
                        value: u64::MAX >> 22,
1458
                    }),
1459
                };
1460
1461
                let ts = Timestamp::from_unix(&context, u64::MAX, u32::MAX);
1462
1463
                assert_eq!(MAX_PARTS, ts.to_unix());
1464
            }
1465
        }
1466
    }
1467
1468
    #[cfg(feature = "v7")]
1469
    pub use v7_support::*;
1470
1471
    /// An empty counter that will always return the value `0`.
1472
    ///
1473
    /// This type can be used when constructing version 7 UUIDs. When used to
1474
    /// construct a version 7 UUID, the entire counter segment of the UUID will be
1475
    /// filled with a random value. This type does not maintain ordering of UUIDs
1476
    /// within a millisecond but is efficient.
1477
    ///
1478
    /// This type should not be used when constructing version 1 or version 6 UUIDs.
1479
    /// When used to construct a version 1 or version 6 UUID, the counter
1480
    /// segment will remain zero.
1481
    #[derive(Debug, Clone, Copy, Default)]
1482
    pub struct NoContext;
1483
1484
    impl ClockSequence for NoContext {
1485
        type Output = u16;
1486
1487
0
        fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
1488
0
            0
1489
0
        }
1490
1491
0
        fn usable_bits(&self) -> usize {
1492
0
            0
1493
0
        }
1494
    }
1495
}
1496
1497
#[cfg(all(test, any(feature = "v1", feature = "v6")))]
1498
mod tests {
1499
    use super::*;
1500
1501
    #[cfg(all(target_family = "wasm", any(target_os = "unknown", target_os = "none")))]
1502
    use wasm_bindgen_test::*;
1503
1504
    #[test]
1505
    #[cfg_attr(
1506
        all(target_family = "wasm", any(target_os = "unknown", target_os = "none")),
1507
        wasm_bindgen_test
1508
    )]
1509
    fn gregorian_unix_does_not_panic() {
1510
        // Ensure timestamp conversions never panic
1511
        Timestamp::unix_to_gregorian_ticks(u64::MAX, 0);
1512
        Timestamp::unix_to_gregorian_ticks(0, u32::MAX);
1513
        Timestamp::unix_to_gregorian_ticks(u64::MAX, u32::MAX);
1514
1515
        Timestamp::gregorian_to_unix(u64::MAX);
1516
    }
1517
1518
    #[test]
1519
    #[cfg_attr(
1520
        all(target_family = "wasm", any(target_os = "unknown", target_os = "none")),
1521
        wasm_bindgen_test
1522
    )]
1523
    fn to_gregorian_truncates_to_usable_bits() {
1524
        let ts = Timestamp::from_gregorian_time(123, u16::MAX);
1525
1526
        assert_eq!((123, u16::MAX >> 2), ts.to_gregorian());
1527
    }
1528
1529
    #[test]
1530
    #[cfg_attr(
1531
        all(target_family = "wasm", any(target_os = "unknown", target_os = "none")),
1532
        wasm_bindgen_test
1533
    )]
1534
    fn clock_sequence_usable_bits() {
1535
        struct MyContext;
1536
1537
        impl ClockSequence for MyContext {
1538
            type Output = u16;
1539
1540
            fn generate_sequence(&self, _: u64, _: u32) -> Self::Output {
1541
                0
1542
            }
1543
        }
1544
1545
        assert_eq!(16, MyContext.usable_bits());
1546
    }
1547
1548
    const MAX_PARTS_NANOS: u128 = (u64::MAX as u128) * 1_000_000_000 + 999_999_999;
1549
1550
    #[test]
1551
    fn nanos_to_parts_roundtrip() {
1552
        for case in [
1553
            0,
1554
            1,
1555
            999_999_999,
1556
            1_000_000_000,
1557
            u64::MAX as u128,
1558
            u64::MAX as u128 + 1,
1559
            u64::MAX as u128 + u32::MAX as u128,
1560
            u64::MAX as u128 + u32::MAX as u128 + 1,
1561
            (u64::MAX as u128) * 1_000_000 + 999_999,
1562
            (u64::MAX as u128) * 1_000_000_000,
1563
            MAX_PARTS_NANOS - 1,
1564
            MAX_PARTS_NANOS,
1565
        ] {
1566
            let (seconds, subsec_nanos) = nanos_to_parts(case);
1567
1568
            assert!(subsec_nanos < 1_000_000_000, "{case}");
1569
            assert_eq!(case, parts_to_nanos(seconds, subsec_nanos), "{case}");
1570
        }
1571
    }
1572
1573
    #[test]
1574
    fn nanos_to_parts_unnormalized_roundtrip() {
1575
        // Beyond the largest normalized value, seconds can't take the carry,
1576
        // so the remainder stays in the subsecond nanos
1577
        for (case, expected) in [
1578
            (MAX_PARTS_NANOS + 1, (u64::MAX, 1_000_000_000)),
1579
            (MAX_PARTS_NANOS + 2, (u64::MAX, 1_000_000_001)),
1580
            (
1581
                parts_to_nanos(u64::MAX, u32::MAX) - 1,
1582
                (u64::MAX, u32::MAX - 1),
1583
            ),
1584
            (parts_to_nanos(u64::MAX, u32::MAX), (u64::MAX, u32::MAX)),
1585
        ] {
1586
            let (seconds, subsec_nanos) = nanos_to_parts(case);
1587
1588
            assert_eq!(expected, (seconds, subsec_nanos), "{case}");
1589
            assert_eq!(case, parts_to_nanos(seconds, subsec_nanos), "{case}");
1590
        }
1591
    }
1592
1593
    #[test]
1594
    fn nanos_to_parts_saturating() {
1595
        for case in [parts_to_nanos(u64::MAX, u32::MAX) + 1, u128::MAX] {
1596
            let (seconds, subsec_nanos) = nanos_to_parts(case);
1597
1598
            assert_eq!(u64::MAX, seconds, "{case}");
1599
            assert_eq!(u32::MAX, subsec_nanos, "{case}");
1600
        }
1601
    }
1602
1603
    #[test]
1604
    fn parts_to_nanos_unnormalized() {
1605
        assert_eq!(2_500_000_000, parts_to_nanos(1, 1_500_000_000));
1606
        assert_eq!(
1607
            parts_to_nanos(2, 500_000_000),
1608
            parts_to_nanos(1, 1_500_000_000)
1609
        );
1610
1611
        // The largest input doesn't overflow
1612
        assert_eq!(
1613
            (u64::MAX as u128) * 1_000_000_000 + u32::MAX as u128,
1614
            parts_to_nanos(u64::MAX, u32::MAX)
1615
        );
1616
    }
1617
1618
    #[test]
1619
    fn timestamp_unix_parts_boundaries() {
1620
        // Normalized values round-trip
1621
        for (seconds, subsec_nanos) in [
1622
            (0, 0),
1623
            (1, 999_999_999),
1624
            (u64::MAX, 0),
1625
            (u64::MAX, 999_999_999),
1626
        ] {
1627
            let ts = Timestamp::from_unix_time(seconds, subsec_nanos, 0, 0);
1628
1629
            assert_eq!((seconds, subsec_nanos), ts.to_unix());
1630
        }
1631
1632
        // Unnormalized values are normalized
1633
        let ts = Timestamp::from_unix_time(1, 1_500_000_000, 0, 0);
1634
        assert_eq!((2, 500_000_000), ts.to_unix());
1635
1636
        // Values beyond the largest normalized are preserved
1637
        for (seconds, subsec_nanos) in [(u64::MAX, 1_000_000_000), (u64::MAX, u32::MAX)] {
1638
            let ts = Timestamp::from_unix_time(seconds, subsec_nanos, 0, 0);
1639
1640
            assert_eq!((seconds, subsec_nanos), ts.to_unix());
1641
        }
1642
1643
        let ts = Timestamp::from_unix_time(u64::MAX - 1, u32::MAX, 0, 0);
1644
        assert_eq!((u64::MAX, u32::MAX - 1_000_000_000), ts.to_unix());
1645
    }
1646
1647
    #[cfg(all(test, feature = "std", not(miri)))]
1648
    mod std_support {
1649
        use super::*;
1650
1651
        use std::time::{Duration, SystemTime};
1652
1653
        // Components of an arbitrary timestamp with non-zero nanoseconds.
1654
        const KNOWN_SECONDS: u64 = 1_501_520_400;
1655
        const KNOWN_NANOS: u32 = 1_000;
1656
1657
        fn known_system_time() -> SystemTime {
1658
            SystemTime::UNIX_EPOCH
1659
                .checked_add(Duration::new(KNOWN_SECONDS, KNOWN_NANOS))
1660
                .unwrap()
1661
        }
1662
1663
        fn known_timestamp() -> Timestamp {
1664
            Timestamp::from_unix_time(KNOWN_SECONDS, KNOWN_NANOS, 0, 0)
1665
        }
1666
1667
        #[test]
1668
        fn to_system_time() {
1669
            let st: SystemTime = known_timestamp().into();
1670
1671
            assert_eq!(known_system_time(), st);
1672
        }
1673
1674
        #[test]
1675
        fn from_system_time() {
1676
            let ts: Timestamp = known_system_time().try_into().unwrap();
1677
1678
            assert_eq!(known_timestamp(), ts);
1679
        }
1680
1681
        #[test]
1682
        fn from_system_time_before_epoch() {
1683
            let before_epoch = match SystemTime::UNIX_EPOCH.checked_sub(Duration::from_nanos(1_000))
1684
            {
1685
                Some(st) => st,
1686
                None => return,
1687
            };
1688
1689
            Timestamp::try_from(before_epoch)
1690
                .expect_err("Timestamp should not be created from before epoch");
1691
        }
1692
1693
        #[test]
1694
        fn from_system_time_max() {
1695
            for (seconds, subsec_nanos) in [
1696
                (u64::MAX, 999_999_999),
1697
                (u64::MAX, 1_000_000_000),
1698
                (u64::MAX, u32::MAX),
1699
            ] {
1700
                let ts = Timestamp::from_unix_time(seconds, subsec_nanos, 0, 0);
1701
1702
                // Just make sure we don't panic
1703
                let _: SystemTime = ts.into();
1704
            }
1705
        }
1706
    }
1707
}