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)
2324use core::cmp;
2526use crate::Uuid;
2728/// 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;
3132/// 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}
4950impl 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")]
55pub fn now(context: impl ClockSequence<Output = impl Into<u128>>) -> Self {
56let (seconds, subsec_nanos) = now();
5758let (counter, seconds, subsec_nanos) =
59context.generate_timestamp_sequence(seconds, subsec_nanos);
60let counter = counter.into();
61let usable_counter_bits = context.usable_bits() as u8;
6263Timestamp {
64seconds,
65subsec_nanos,
66counter,
67usable_counter_bits,
68 }
69 }
7071/// 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.
79pub const fn from_gregorian_time(ticks: u64, counter: u16) -> Self {
80let (seconds, subsec_nanos) = Self::gregorian_to_unix(ticks);
8182Timestamp {
83seconds,
84subsec_nanos,
85 counter: counteras u128,
86 usable_counter_bits: 14,
87 }
88 }
8990/// Construct a `Timestamp` from a Unix timestamp and up to a 128-bit counter, as used in version 7 UUIDs.
91pub const fn from_unix_time(
92 seconds: u64,
93 subsec_nanos: u32,
94 counter: u128,
95 usable_counter_bits: u8,
96 ) -> Self {
97Timestamp {
98seconds,
99subsec_nanos,
100counter,
101usable_counter_bits,
102 }
103 }
104105/// Construct a `Timestamp` from a Unix timestamp and up to a 128-bit counter, as used in version 7 UUIDs.
106pub fn from_unix(
107 context: impl ClockSequence<Output = impl Into<u128>>,
108 seconds: u64,
109 subsec_nanos: u32,
110 ) -> Self {
111let (counter, seconds, subsec_nanos) =
112context.generate_timestamp_sequence(seconds, subsec_nanos);
113let counter = counter.into();
114let usable_counter_bits = context.usable_bits() as u8;
115116Timestamp {
117seconds,
118subsec_nanos,
119counter,
120usable_counter_bits,
121 }
122 }
123124/// 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.
133pub const fn to_gregorian(&self) -> (u64, u16) {
134 (
135Self::unix_to_gregorian_ticks(self.seconds, self.subsec_nanos),
136 (self.counter as u16) & 0x3FFF,
137 )
138 }
139140// 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")]
143pub(crate) const fn counter(&self) -> (u128, u8) {
144 (self.counter, self.usable_counter_bits)
145 }
146147/// Get the value of the timestamp as a Unix timestamp, as used in version 7 UUIDs.
148pub const fn to_unix(&self) -> (u64, u32) {
149 (self.seconds, self.subsec_nanos)
150 }
151152const fn unix_to_gregorian_ticks(seconds: u64, nanos: u32) -> u64 {
153UUID_TICKS_BETWEEN_EPOCHS154 .wrapping_add(seconds.wrapping_mul(10_000_000))
155 .wrapping_add(nanosas u64 / 100)
156 }
157158const fn gregorian_to_unix(ticks: u64) -> (u64, u32) {
159 (
160ticks.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}
165166#[doc(hidden)]
167impl Timestamp {
168#[deprecated(
169 since = "1.10.0",
170 note = "use `Timestamp::from_gregorian_time(ticks, counter)`"
171)]
172pub const fn from_rfc4122(ticks: u64, counter: u16) -> Self {
173Timestamp::from_gregorian_time(ticks, counter)
174 }
175176#[deprecated(since = "1.10.0", note = "use `Timestamp::to_gregorian()`")]
177pub const fn to_rfc4122(&self) -> (u64, u16) {
178self.to_gregorian()
179 }
180181#[deprecated(
182 since = "1.2.0",
183 note = "`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`"
184)]
185pub 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 }
188189#[deprecated(
190 since = "1.23.0",
191 note = "use `Timestamp::from_gregorian_time(ticks, counter)`"
192)]
193pub const fn from_gregorian(ticks: u64, counter: u16) -> Self {
194Timestamp::from_gregorian_time(ticks, counter)
195 }
196}
197198#[cfg(feature = "std")]
199impl TryFrom<std::time::SystemTime> for Timestamp {
200type Error = crate::Error;
201202/// 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.
206fn try_from(st: std::time::SystemTime) -> Result<Self, Self::Error> {
207let dur = st.duration_since(std::time::UNIX_EPOCH).map_err(|_| {
208crate::Error(crate::error::ErrorKind::InvalidSystemTime(
209"unable to convert the system tie into a Unix timestamp",
210 ))
211 })?;
212213Ok(Self::from_unix_time(
214dur.as_secs(),
215dur.subsec_nanos(),
2160,
2170,
218 ))
219 }
220}
221222#[cfg(feature = "std")]
223impl From<Timestamp> for std::time::SystemTime {
224fn from(ts: Timestamp) -> Self {
225let (seconds, subsec_nanos) = ts.to_unix();
226227Self::UNIX_EPOCH + std::time::Duration::new(seconds, subsec_nanos)
228 }
229}
230231pub(crate) const fn encode_gregorian_timestamp(
232 ticks: u64,
233 counter: u16,
234 node_id: &[u8; 6],
235) -> Uuid {
236let time_low = (ticks & 0xFFFF_FFFF) as u32;
237let time_mid = ((ticks >> 32) & 0xFFFF) as u16;
238let time_high_and_version = (((ticks >> 48) & 0x0FFF) as u16) | (1 << 12);
239240let mut d4 = [0; 8];
241242d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
243d4[1] = (counter & 0xFF) as u8;
244d4[2] = node_id[0];
245d4[3] = node_id[1];
246d4[4] = node_id[2];
247d4[5] = node_id[3];
248d4[6] = node_id[4];
249d4[7] = node_id[5];
250251Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
252}
253254pub(crate) const fn decode_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
255let bytes = uuid.as_bytes();
256257let 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);
265266let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
267268 (ticks, counter)
269}
270271pub(crate) const fn encode_sorted_gregorian_timestamp(
272 ticks: u64,
273 counter: u16,
274 node_id: &[u8; 6],
275) -> Uuid {
276let time_high = ((ticks >> 28) & 0xFFFF_FFFF) as u32;
277let time_mid = ((ticks >> 12) & 0xFFFF) as u16;
278let time_low_and_version = ((ticks & 0x0FFF) as u16) | (0x6 << 12);
279280let mut d4 = [0; 8];
281282d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
283d4[1] = (counter & 0xFF) as u8;
284d4[2] = node_id[0];
285d4[3] = node_id[1];
286d4[4] = node_id[2];
287d4[5] = node_id[3];
288d4[6] = node_id[4];
289d4[7] = node_id[5];
290291Uuid::from_fields(time_high, time_mid, time_low_and_version, &d4)
292}
293294pub(crate) const fn decode_sorted_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
295let bytes = uuid.as_bytes();
296297let 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);
305306let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
307308 (ticks, counter)
309}
310311pub(crate) const fn encode_unix_timestamp_millis(
312 millis: u64,
313 counter_random_bytes: &[u8; 10],
314) -> Uuid {
315let millis_high = ((millis >> 16) & 0xFFFF_FFFF) as u32;
316let millis_low = (millis & 0xFFFF) as u16;
317318let counter_random_version = (counter_random_bytes[1] as u16319 | ((counter_random_bytes[0] as u16) << 8) & 0x0FFF)
320 | (0x7 << 12);
321322let mut d4 = [0; 8];
323324d4[0] = (counter_random_bytes[2] & 0x3F) | 0x80;
325d4[1] = counter_random_bytes[3];
326d4[2] = counter_random_bytes[4];
327d4[3] = counter_random_bytes[5];
328d4[4] = counter_random_bytes[6];
329d4[5] = counter_random_bytes[7];
330d4[6] = counter_random_bytes[8];
331d4[7] = counter_random_bytes[9];
332333Uuid::from_fields(millis_high, millis_low, counter_random_version, &d4)
334}
335336pub(crate) const fn decode_unix_timestamp_millis(uuid: &Uuid) -> u64 {
337let bytes = uuid.as_bytes();
338339let 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);
345346millis347}
348349#[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) {
355use wasm_bindgen::prelude::*;
356357#[wasm_bindgen]
358extern "C" {
359// NOTE: This signature works around https://bugzilla.mozilla.org/show_bug.cgi?id=1787770
360#[wasm_bindgen(js_namespace = Date, catch)]
361fn now() -> Result<f64, JsValue>;
362 }
363364let now = now().unwrap_throw();
365366let secs = (now / 1_000.0) as u64;
367let nanos = ((now % 1_000.0) * 1_000_000.0) as u32;
368369 (secs, nanos)
370}
371372#[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) {
381let dur = std::time::SystemTime::UNIX_EPOCH.elapsed().expect(
382"Getting elapsed time since UNIX_EPOCH. If this fails, we've somehow violated causality",
383 );
384385 (dur.as_secs(), dur.subsec_nanos())
386}
387388#[cfg(all(feature = "std", miri))]
389fn now() -> (u64, u32) {
390use std::{sync::Mutex, time::Duration};
391392static TS: Mutex<u64> = Mutex::new(0);
393394let ts = Duration::from_nanos({
395let mut ts = TS.lock().unwrap();
396*ts += 1;
397*ts
398 });
399400 (ts.as_secs(), ts.subsec_nanos())
401}
402403/// 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.
413type Output;
414415/// 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.
420fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output;
421422/// 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.
427fn generate_timestamp_sequence(
428&self,
429 seconds: u64,
430 subsec_nanos: u32,
431 ) -> (Self::Output, u64, u32) {
432 (
433self.generate_sequence(seconds, subsec_nanos),
434seconds,
435subsec_nanos,
436 )
437 }
438439/// 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.
446fn usable_bits(&self) -> usize447where
448Self::Output: Sized,
449 {
450 cmp::min(128, core::mem::size_of::<Self::Output>() * 8)
451 }
452}
453454impl<T: ClockSequence + ?Sized> ClockSequencefor &T {
455type Output = T::Output;
456457fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
458 (**self).generate_sequence(seconds, subsec_nanos)
459 }
460461fn 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 }
468469fn usable_bits(&self) -> usize470where
471Self::Output: Sized,
472 {
473 (**self).usable_bits()
474 }
475}
476477/// Default implementations for the [`ClockSequence`] trait.
478pub mod context {
479use super::ClockSequence;
480481#[cfg(any(feature = "v1", feature = "v6"))]
482mod v1_support {
483use super::*;
484485#[cfg(all(feature = "std", feature = "rng"))]
486use crate::std::sync::LazyLock;
487488use atomic::{Atomic, Ordering};
489490#[cfg(all(feature = "std", feature = "rng"))]
491static CONTEXT: LazyLock<ContextV1> = LazyLock::new(ContextV1::new_random);
492493#[cfg(all(feature = "std", feature = "rng"))]
494pub(crate) fn shared_context_v1() -> &'static ContextV1 {
495&*CONTEXT
496 }
497498/// 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)]
514pub struct ContextV1 {
515 count: Atomic<u16>,
516 }
517518impl 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.
524pub const fn new(count: u16) -> Self {
525Self {
526 count: Atomic::<u16>::new(count),
527 }
528 }
529530/// Construct a new context that's initialized with a random value.
531#[cfg(feature = "rng")]
532pub fn new_random() -> Self {
533Self {
534 count: Atomic::<u16>::new(crate::rng::u16()),
535 }
536 }
537 }
538539impl ClockSequence for ContextV1 {
540type Output = u16;
541542fn 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
548self.count.fetch_add(1, Ordering::AcqRel) & (u16::MAX >> 2)
549 }
550551fn usable_bits(&self) -> usize {
55214
553}
554 }
555556#[deprecated(since = "1.23.0", note = "renamed to `ContextV1`")]
557 #[doc(hidden)]
558pub type Context = ContextV1;
559560#[cfg(test)]
561mod tests {
562use crate::Timestamp;
563564use super::*;
565566#[test]
567fn context() {
568let seconds = 1_496_854_535;
569let subsec_nanos = 812_946_000;
570571let context = ContextV1::new(u16::MAX >> 2);
572573let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
574assert_eq!(16383, ts.counter);
575assert_eq!(14, ts.usable_counter_bits);
576577let seconds = 1_496_854_536;
578579let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
580assert_eq!(0, ts.counter);
581582let seconds = 1_496_854_535;
583584let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
585assert_eq!(1, ts.counter);
586 }
587588#[test]
589fn context_overflow() {
590let seconds = u64::MAX;
591let subsec_nanos = u32::MAX;
592593let context = ContextV1::new(u16::MAX);
594595// Ensure we don't panic
596Timestamp::from_unix(&context, seconds, subsec_nanos);
597 }
598 }
599 }
600601#[cfg(any(feature = "v1", feature = "v6"))]
602pub use v1_support::*;
603604#[cfg(feature = "std")]
605mod std_support {
606use super::*;
607608use core::panic::{AssertUnwindSafe, RefUnwindSafe};
609use std::{sync::Mutex, thread::LocalKey};
610611/// A wrapper for a context that uses thread-local storage.
612pub struct ThreadLocalContext<C: 'static>(&'static LocalKey<C>);
613614impl<C> std::fmt::Debugfor ThreadLocalContext<C> {
615fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
616f.debug_struct("ThreadLocalContext").finish_non_exhaustive()
617 }
618 }
619620impl<C: 'static> ThreadLocalContext<C> {
621/// Wrap a thread-local container with a context.
622pub const fn new(local_key: &'static LocalKey<C>) -> Self {
623ThreadLocalContext(local_key)
624 }
625 }
626627impl<C: ClockSequence + 'static> ClockSequencefor ThreadLocalContext<C> {
628type Output = C::Output;
629630fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
631self.0
632.with(|ctxt| ctxt.generate_sequence(seconds, subsec_nanos))
633 }
634635fn generate_timestamp_sequence(
636&self,
637 seconds: u64,
638 subsec_nanos: u32,
639 ) -> (Self::Output, u64, u32) {
640self.0
641.with(|ctxt| ctxt.generate_timestamp_sequence(seconds, subsec_nanos))
642 }
643644fn usable_bits(&self) -> usize {
645self.0.with(|ctxt| ctxt.usable_bits())
646 }
647 }
648649impl<C: ClockSequence> ClockSequencefor AssertUnwindSafe<C> {
650type Output = C::Output;
651652fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
653self.0.generate_sequence(seconds, subsec_nanos)
654 }
655656fn generate_timestamp_sequence(
657&self,
658 seconds: u64,
659 subsec_nanos: u32,
660 ) -> (Self::Output, u64, u32) {
661self.0.generate_timestamp_sequence(seconds, subsec_nanos)
662 }
663664fn usable_bits(&self) -> usize665where
666Self::Output: Sized,
667 {
668self.0.usable_bits()
669 }
670 }
671672impl<C: ClockSequence + RefUnwindSafe> ClockSequencefor Mutex<C> {
673type Output = C::Output;
674675fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
676self.lock()
677 .unwrap_or_else(|err| err.into_inner())
678 .generate_sequence(seconds, subsec_nanos)
679 }
680681fn generate_timestamp_sequence(
682&self,
683 seconds: u64,
684 subsec_nanos: u32,
685 ) -> (Self::Output, u64, u32) {
686self.lock()
687 .unwrap_or_else(|err| err.into_inner())
688 .generate_timestamp_sequence(seconds, subsec_nanos)
689 }
690691fn usable_bits(&self) -> usize692where
693Self::Output: Sized,
694 {
695self.lock()
696 .unwrap_or_else(|err| err.into_inner())
697 .usable_bits()
698 }
699 }
700 }
701702#[cfg(feature = "std")]
703pub use std_support::*;
704705#[cfg(feature = "v7")]
706mod v7_support {
707use super::*;
708709use core::{cell::Cell, cmp, panic::RefUnwindSafe};
710711#[cfg(feature = "std")]
712static CONTEXT_V7: SharedContextV7 =
713 SharedContextV7(std::sync::Mutex::new(ContextV7::new()));
714715#[cfg(feature = "std")]
716pub(crate) fn shared_context_v7() -> &'static SharedContextV7 {
717&CONTEXT_V7
718 }
719720const USABLE_BITS: usize = 42;
721722// 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
726const RESEED_MASK: u64 = u64::MAX >> 23;
727const MAX_COUNTER: u64 = u64::MAX >> 22;
728729/// 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)]
755pub struct ContextV7 {
756 timestamp: Cell<ReseedingTimestamp>,
757 counter: Cell<Counter>,
758 adjust: Adjust,
759 precision: Precision,
760 }
761762impl RefUnwindSafe for ContextV7 {}
763764impl ContextV7 {
765/// Construct a new context that will reseed its counter on the first
766 /// non-zero timestamp it receives.
767pub 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 }
784785/// Specify an amount to shift timestamps by to obfuscate their actual generation time.
786pub fn with_adjust_by_millis(mut self, millis: u32) -> Self {
787self.adjust = Adjust::by_millis(millis);
788self
789}
790791/// 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.
797pub fn with_additional_precision(self) -> Self {
798self.with_additional_precision_bits(12)
799 }
800801/// 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.
810pub fn with_additional_precision_bits(mut self, bits: usize) -> Self {
811self.precision = Precision::new(cmp::min(bits, 12));
812self
813}
814 }
815816impl ClockSequence for ContextV7 {
817type Output = u64;
818819fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
820self.generate_timestamp_sequence(seconds, subsec_nanos).0
821}
822823fn generate_timestamp_sequence(
824&self,
825 seconds: u64,
826 subsec_nanos: u32,
827 ) -> (Self::Output, u64, u32) {
828let (seconds, subsec_nanos) = self.adjust.apply(seconds, subsec_nanos);
829830let mut counter;
831let (mut timestamp, should_reseed) =
832self.timestamp.get().advance(seconds, subsec_nanos);
833834if should_reseed {
835// If the observed system time has shifted forwards then regenerate the counter
836counter = Counter::reseed(&self.precision, ×tamp);
837 } else {
838// If the observed system time has not shifted forwards then increment the counter
839840 // 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
843844counter = self.counter.get().increment(&self.precision, ×tamp);
845846// 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
849if counter.has_overflowed() {
850// Increment the timestamp by 1 milli and reseed the counter
851timestamp = timestamp.increment();
852 counter = Counter::reseed(&self.precision, ×tamp);
853 }
854 };
855856self.timestamp.set(timestamp);
857self.counter.set(counter);
858859 (counter.value, timestamp.seconds, timestamp.subsec_nanos)
860 }
861862fn usable_bits(&self) -> usize {
863 USABLE_BITS
864 }
865 }
866867/// A timestamp that keeps track of whether a reseed is necessary.
868#[derive(Debug, Default, Clone, Copy)]
869struct ReseedingTimestamp {
870 last_seed: u64,
871 seconds: u64,
872 subsec_nanos: u32,
873 }
874875impl ReseedingTimestamp {
876#[inline]
877fn from_ts(seconds: u64, subsec_nanos: u32) -> Self {
878// Reseed when the millisecond advances
879let last_seed = seconds
880 .saturating_mul(1_000)
881 .saturating_add((subsec_nanos / 1_000_000) as u64);
882883 ReseedingTimestamp {
884 last_seed,
885 seconds,
886 subsec_nanos,
887 }
888 }
889890/// Advance the timestamp to a new value, returning whether a reseed is necessary.
891#[inline]
892fn advance(&self, seconds: u64, subsec_nanos: u32) -> (Self, bool) {
893let incoming = ReseedingTimestamp::from_ts(seconds, subsec_nanos);
894895if 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
901let mut value = *self;
902 value.subsec_nanos = cmp::max(self.subsec_nanos, subsec_nanos);
903904 (value, false)
905 }
906 }
907908/// Advance the timestamp by a millisecond.
909#[inline]
910fn increment(&self) -> Self {
911let (seconds, subsec_nanos) =
912 Adjust::by_millis(1).apply(self.seconds, self.subsec_nanos);
913914 ReseedingTimestamp::from_ts(seconds, subsec_nanos)
915 }
916917#[inline]
918fn submilli_nanos(&self) -> u32 {
919self.subsec_nanos % 1_000_000
920}
921 }
922923/// A counter that initializes to a safe random seed and tracks overflow.
924#[derive(Debug, Clone, Copy)]
925struct Counter {
926 value: u64,
927 }
928929impl Counter {
930#[inline]
931fn reseed(precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
932 Counter {
933 value: precision.apply(crate::rng::u64() & RESEED_MASK, timestamp),
934 }
935 }
936937/// Advance the counter.
938#[inline]
939fn increment(&self, precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
940let mut counter = Counter {
941 value: precision.apply(self.value, timestamp),
942 };
943944// 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
948949 // Guaranteed to never overflow u64
950counter.value += 1;
951952 counter
953 }
954955#[inline]
956fn has_overflowed(&self) -> bool {
957self.value > MAX_COUNTER
958 }
959 }
960961/// A utility that adjusts an input timestamp by a given number of nanoseconds.
962#[derive(Debug)]
963struct Adjust {
964 by_ns: u128,
965 }
966967impl Adjust {
968#[inline]
969fn by_millis(millis: u32) -> Self {
970 Adjust {
971 by_ns: (millis as u128).saturating_mul(1_000_000),
972 }
973 }
974975/// Apply the adjustment, returning the adjusted timestamp.
976#[inline]
977fn apply(&self, seconds: u64, subsec_nanos: u32) -> (u64, u32) {
978if self.by_ns == 0 {
979// No shift applied
980return (seconds, subsec_nanos);
981 }
982983let ts = (seconds as u128)
984 .saturating_mul(1_000_000_000)
985 .saturating_add(subsec_nanos as u128)
986 .saturating_add(self.by_ns);
987988 ((ts / 1_000_000_000) as u64, (ts % 1_000_000_000) as u32)
989 }
990 }
991992/// A utility that overwrites some number of counter bits with additional timestamp precision.
993#[derive(Debug)]
994struct Precision {
995 bits: usize,
996 factor: u64,
997 mask: u64,
998 shift: u64,
999 }
10001001impl Precision {
1002fn 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
1005let mask = u64::MAX >> (64 - USABLE_BITS + bits);
1006let shift = (USABLE_BITS - bits) as u64;
10071008// The factor reduces the size of the sub-millisecond precision to
1009 // fit into the specified number of bits
1010let factor = (999_999 / u64::pow(2, bits as u32)) + 1;
10111012 Precision {
1013 bits,
1014 factor,
1015 mask,
1016 shift,
1017 }
1018 }
10191020/// Apply additional precision from the given timestamp to the counter.
1021#[inline]
1022fn apply(&self, counter: u64, timestamp: &ReseedingTimestamp) -> u64 {
1023if self.bits == 0 {
1024// No additional precision is being used
1025return counter;
1026 }
10271028let additional = timestamp.submilli_nanos() as u64 / self.factor;
10291030 (counter & self.mask) | (additional << self.shift)
1031 }
1032 }
10331034#[cfg(feature = "std")]
1035pub(crate) struct SharedContextV7(std::sync::Mutex<ContextV7>);
10361037#[cfg(feature = "std")]
1038impl ClockSequence for SharedContextV7 {
1039type Output = u64;
10401041fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
1042self.0.generate_sequence(seconds, subsec_nanos)
1043 }
10441045fn generate_timestamp_sequence(
1046&self,
1047 seconds: u64,
1048 subsec_nanos: u32,
1049 ) -> (Self::Output, u64, u32) {
1050self.0.generate_timestamp_sequence(seconds, subsec_nanos)
1051 }
10521053fn usable_bits(&self) -> usize
1054where
1055Self::Output: Sized,
1056 {
1057 USABLE_BITS
1058 }
1059 }
10601061#[cfg(test)]
1062mod tests {
1063use core::time::Duration;
10641065use super::*;
10661067use crate::{Timestamp, Uuid};
10681069#[test]
1070fn context() {
1071let seconds = 1_496_854_535;
1072let subsec_nanos = 812_946_000;
10731074let context = ContextV7::new();
10751076let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1077assert_eq!(42, ts1.usable_counter_bits);
10781079// Backwards second
1080let seconds = 1_496_854_534;
10811082let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
10831084// The backwards time should be ignored
1085 // The counter should still increment
1086assert_eq!(ts1.seconds, ts2.seconds);
1087assert_eq!(ts1.subsec_nanos, ts2.subsec_nanos);
1088assert_eq!(ts1.counter + 1, ts2.counter);
10891090// Forwards second
1091let seconds = 1_496_854_536;
10921093let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
10941095// The counter should have reseeded
1096assert_ne!(ts2.counter + 1, ts3.counter);
1097assert_ne!(0, ts3.counter);
1098 }
10991100#[test]
1101fn context_wrap() {
1102let seconds = 1_496_854_535u64;
1103let subsec_nanos = 812_946_000u32;
11041105// This context will wrap
1106let 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 };
11191120let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
11211122// The timestamp should be incremented by 1ms
1123let expected_ts = Duration::new(seconds, subsec_nanos) + Duration::from_millis(1);
1124assert_eq!(expected_ts.as_secs(), ts.seconds);
1125assert_eq!(expected_ts.subsec_nanos(), ts.subsec_nanos);
11261127// The counter should have reseeded
1128assert!(ts.counter < (u64::MAX >> 22) as u128);
1129assert_ne!(0, ts.counter);
1130 }
11311132#[test]
1133fn context_shift() {
1134let seconds = 1_496_854_535;
1135let subsec_nanos = 812_946_000;
11361137let context = ContextV7::new().with_adjust_by_millis(1);
11381139let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
11401141assert_eq!((1_496_854_535, 813_946_000), ts.to_unix());
1142 }
11431144#[test]
1145fn context_additional_precision() {
1146let seconds = 1_496_854_535;
1147let subsec_nanos = 812_946_000;
11481149let context = ContextV7::new().with_additional_precision();
11501151let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
11521153// NOTE: Future changes in rounding may change this value slightly
1154assert_eq!(3861, ts1.counter >> 30);
11551156assert!(ts1.counter < (u64::MAX >> 22) as u128);
11571158// Generate another timestamp; it should continue to sort
1159let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
11601161assert!(Uuid::new_v7(ts2) > Uuid::new_v7(ts1));
11621163// Generate another timestamp with an extra nanosecond
1164let subsec_nanos = subsec_nanos + 1;
11651166let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
11671168assert!(Uuid::new_v7(ts3) > Uuid::new_v7(ts2));
1169 }
11701171#[test]
1172fn context_additional_precision_bits() {
1173let seconds = 1_496_854_535;
1174let subsec_nanos = 812_946_000;
11751176// 10 bits leaves the low 2 bits of `rand_a` for random data, which suits
1177 // platforms with microsecond precision
1178let context = ContextV7::new().with_additional_precision_bits(10);
11791180let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
11811182// The submillisecond precision occupies the leftmost 10 of the 42 counter bits
1183 // NOTE: Future changes in rounding may change this value slightly
1184assert_eq!(968, ts.counter >> 32);
11851186assert!(ts.counter < (u64::MAX >> 22) as u128);
11871188// The full method is just the 12-bit form of this one
1189let full = Timestamp::from_unix(
1190&ContextV7::new().with_additional_precision(),
1191 seconds,
1192 subsec_nanos,
1193 );
1194let bits12 = Timestamp::from_unix(
1195&ContextV7::new().with_additional_precision_bits(12),
1196 seconds,
1197 subsec_nanos,
1198 );
1199assert_eq!(full.counter >> 30, bits12.counter >> 30);
12001201// Values above 12 are capped at 12
1202let capped = Timestamp::from_unix(
1203&ContextV7::new().with_additional_precision_bits(64),
1204 seconds,
1205 subsec_nanos,
1206 );
1207assert_eq!(bits12.counter >> 30, capped.counter >> 30);
12081209// Zero bits disables additional precision entirely
1210let none = ContextV7::new().with_additional_precision_bits(0);
1211assert_eq!(0, none.precision.bits);
1212 }
12131214#[test]
1215fn context_overflow() {
1216let seconds = u64::MAX;
1217let subsec_nanos = u32::MAX;
12181219// Ensure we don't panic
1220for 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 }
12301231#[cfg(feature = "v7")]
1232pub use v7_support::*;
12331234/// 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)]
1245pub struct NoContext;
12461247impl ClockSequencefor NoContext {
1248type Output = u16;
12491250fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
12510
1252}
12531254fn usable_bits(&self) -> usize {
12550
1256}
1257 }
1258}
12591260#[cfg(all(test, any(feature = "v1", feature = "v6")))]
1261mod tests {
1262use super::*;
12631264#[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))]
1265use wasm_bindgen_test::*;
12661267#[test]
1268 #[cfg_attr(
1269 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1270 wasm_bindgen_test
1271 )]
1272fn gregorian_unix_does_not_panic() {
1273// Ensure timestamp conversions never panic
1274Timestamp::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);
12771278 Timestamp::gregorian_to_unix(u64::MAX);
1279 }
12801281#[test]
1282 #[cfg_attr(
1283 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1284 wasm_bindgen_test
1285 )]
1286fn to_gregorian_truncates_to_usable_bits() {
1287let ts = Timestamp::from_gregorian_time(123, u16::MAX);
12881289assert_eq!((123, u16::MAX >> 2), ts.to_gregorian());
1290 }
12911292#[test]
1293 #[cfg_attr(
1294 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1295 wasm_bindgen_test
1296 )]
1297fn clock_sequence_usable_bits() {
1298struct MyContext;
12991300impl ClockSequence for MyContext {
1301type Output = u16;
13021303fn generate_sequence(&self, _: u64, _: u32) -> Self::Output {
13040
1305}
1306 }
13071308assert_eq!(16, MyContext.usable_bits());
1309 }
13101311#[cfg(all(test, feature = "std", not(miri)))]
1312mod std_support {
1313use super::*;
13141315use std::time::{Duration, SystemTime};
13161317// Components of an arbitrary timestamp with non-zero nanoseconds.
1318const KNOWN_SECONDS: u64 = 1_501_520_400;
1319const KNOWN_NANOS: u32 = 1_000;
13201321fn known_system_time() -> SystemTime {
1322 SystemTime::UNIX_EPOCH
1323 .checked_add(Duration::new(KNOWN_SECONDS, KNOWN_NANOS))
1324 .unwrap()
1325 }
13261327fn known_timestamp() -> Timestamp {
1328 Timestamp::from_unix_time(KNOWN_SECONDS, KNOWN_NANOS, 0, 0)
1329 }
13301331#[test]
1332fn to_system_time() {
1333let st: SystemTime = known_timestamp().into();
13341335assert_eq!(known_system_time(), st);
1336 }
13371338#[test]
1339fn from_system_time() {
1340let ts: Timestamp = known_system_time().try_into().unwrap();
13411342assert_eq!(known_timestamp(), ts);
1343 }
13441345#[test]
1346fn from_system_time_before_epoch() {
1347let before_epoch = match SystemTime::UNIX_EPOCH.checked_sub(Duration::from_nanos(1_000))
1348 {
1349Some(st) => st,
1350None => return,
1351 };
13521353 Timestamp::try_from(before_epoch)
1354 .expect_err("Timestamp should not be created from before epoch");
1355 }
1356 }
1357}