1use core::cmp;
25
26use crate::Uuid;
27
28pub const UUID_TICKS_BETWEEN_EPOCHS: u64 = 0x01B2_1DD2_1381_4000;
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
43pub struct Timestamp {
44 seconds: u64,
45 subsec_nanos: u32,
46 counter: u128,
47 usable_counter_bits: u8,
48}
49
50impl Timestamp {
51 #[cfg(feature = "std")]
55 pub fn now(context: impl ClockSequence<Output = impl Into<u128>>) -> Self {
56 let (seconds, subsec_nanos) = now();
57
58 let (counter, seconds, subsec_nanos) =
59 context.generate_timestamp_sequence(seconds, subsec_nanos);
60 let counter = counter.into();
61 let usable_counter_bits = context.usable_bits() as u8;
62
63 Timestamp {
64 seconds,
65 subsec_nanos,
66 counter,
67 usable_counter_bits,
68 }
69 }
70
71 pub const fn from_gregorian_time(ticks: u64, counter: u16) -> Self {
80 let (seconds, subsec_nanos) = Self::gregorian_to_unix(ticks);
81
82 Timestamp {
83 seconds,
84 subsec_nanos,
85 counter: counter as u128,
86 usable_counter_bits: 14,
87 }
88 }
89
90 pub const fn from_unix_time(
92 seconds: u64,
93 subsec_nanos: u32,
94 counter: u128,
95 usable_counter_bits: u8,
96 ) -> Self {
97 Timestamp {
98 seconds,
99 subsec_nanos,
100 counter,
101 usable_counter_bits,
102 }
103 }
104
105 pub fn from_unix(
107 context: impl ClockSequence<Output = impl Into<u128>>,
108 seconds: u64,
109 subsec_nanos: u32,
110 ) -> Self {
111 let (counter, seconds, subsec_nanos) =
112 context.generate_timestamp_sequence(seconds, subsec_nanos);
113 let counter = counter.into();
114 let usable_counter_bits = context.usable_bits() as u8;
115
116 Timestamp {
117 seconds,
118 subsec_nanos,
119 counter,
120 usable_counter_bits,
121 }
122 }
123
124 pub const fn to_gregorian(&self) -> (u64, u16) {
134 (
135 Self::unix_to_gregorian_ticks(self.seconds, self.subsec_nanos),
136 (self.counter as u16) & 0x3FFF,
137 )
138 }
139
140 #[cfg(feature = "v7")]
143 pub(crate) const fn counter(&self) -> (u128, u8) {
144 (self.counter, self.usable_counter_bits)
145 }
146
147 pub const fn to_unix(&self) -> (u64, u32) {
149 (self.seconds, self.subsec_nanos)
150 }
151
152 const fn unix_to_gregorian_ticks(seconds: u64, nanos: u32) -> u64 {
153 UUID_TICKS_BETWEEN_EPOCHS
154 .wrapping_add(seconds.wrapping_mul(10_000_000))
155 .wrapping_add(nanos as u64 / 100)
156 }
157
158 const fn gregorian_to_unix(ticks: u64) -> (u64, u32) {
159 (
160 ticks.wrapping_sub(UUID_TICKS_BETWEEN_EPOCHS) / 10_000_000,
161 (ticks.wrapping_sub(UUID_TICKS_BETWEEN_EPOCHS) % 10_000_000) as u32 * 100,
162 )
163 }
164}
165
166#[doc(hidden)]
167impl Timestamp {
168 #[deprecated(
169 since = "1.10.0",
170 note = "use `Timestamp::from_gregorian_time(ticks, counter)`"
171 )]
172 pub const fn from_rfc4122(ticks: u64, counter: u16) -> Self {
173 Timestamp::from_gregorian_time(ticks, counter)
174 }
175
176 #[deprecated(since = "1.10.0", note = "use `Timestamp::to_gregorian()`")]
177 pub const fn to_rfc4122(&self) -> (u64, u16) {
178 self.to_gregorian()
179 }
180
181 #[deprecated(
182 since = "1.2.0",
183 note = "`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`"
184 )]
185 pub const fn to_unix_nanos(&self) -> u32 {
186 panic!("`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`")
187 }
188
189 #[deprecated(
190 since = "1.23.0",
191 note = "use `Timestamp::from_gregorian_time(ticks, counter)`"
192 )]
193 pub const fn from_gregorian(ticks: u64, counter: u16) -> Self {
194 Timestamp::from_gregorian_time(ticks, counter)
195 }
196}
197
198#[cfg(feature = "std")]
199impl TryFrom<std::time::SystemTime> for Timestamp {
200 type Error = crate::Error;
201
202 fn try_from(st: std::time::SystemTime) -> Result<Self, Self::Error> {
207 let dur = st.duration_since(std::time::UNIX_EPOCH).map_err(|_| {
208 crate::Error(crate::error::ErrorKind::InvalidSystemTime(
209 "unable to convert the system tie into a Unix timestamp",
210 ))
211 })?;
212
213 Ok(Self::from_unix_time(
214 dur.as_secs(),
215 dur.subsec_nanos(),
216 0,
217 0,
218 ))
219 }
220}
221
222#[cfg(feature = "std")]
223impl From<Timestamp> for std::time::SystemTime {
224 fn from(ts: Timestamp) -> Self {
230 let (seconds, subsec_nanos) = ts.to_unix();
231
232 Self::UNIX_EPOCH
235 .checked_add(std::time::Duration::new(seconds, subsec_nanos))
236 .unwrap_or(std::time::SystemTime::UNIX_EPOCH)
237 }
238}
239
240pub(crate) const fn encode_gregorian_timestamp(
241 ticks: u64,
242 counter: u16,
243 node_id: &[u8; 6],
244) -> Uuid {
245 let time_low = (ticks & 0xFFFF_FFFF) as u32;
246 let time_mid = ((ticks >> 32) & 0xFFFF) as u16;
247 let time_high_and_version = (((ticks >> 48) & 0x0FFF) as u16) | (1 << 12);
248
249 let mut d4 = [0; 8];
250
251 d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
252 d4[1] = (counter & 0xFF) as u8;
253 d4[2] = node_id[0];
254 d4[3] = node_id[1];
255 d4[4] = node_id[2];
256 d4[5] = node_id[3];
257 d4[6] = node_id[4];
258 d4[7] = node_id[5];
259
260 Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
261}
262
263pub(crate) const fn decode_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
264 let bytes = uuid.as_bytes();
265
266 let ticks: u64 = ((bytes[6] & 0x0F) as u64) << 56
267 | (bytes[7] as u64) << 48
268 | (bytes[4] as u64) << 40
269 | (bytes[5] as u64) << 32
270 | (bytes[0] as u64) << 24
271 | (bytes[1] as u64) << 16
272 | (bytes[2] as u64) << 8
273 | (bytes[3] as u64);
274
275 let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
276
277 (ticks, counter)
278}
279
280pub(crate) const fn encode_sorted_gregorian_timestamp(
281 ticks: u64,
282 counter: u16,
283 node_id: &[u8; 6],
284) -> Uuid {
285 let time_high = ((ticks >> 28) & 0xFFFF_FFFF) as u32;
286 let time_mid = ((ticks >> 12) & 0xFFFF) as u16;
287 let time_low_and_version = ((ticks & 0x0FFF) as u16) | (0x6 << 12);
288
289 let mut d4 = [0; 8];
290
291 d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
292 d4[1] = (counter & 0xFF) as u8;
293 d4[2] = node_id[0];
294 d4[3] = node_id[1];
295 d4[4] = node_id[2];
296 d4[5] = node_id[3];
297 d4[6] = node_id[4];
298 d4[7] = node_id[5];
299
300 Uuid::from_fields(time_high, time_mid, time_low_and_version, &d4)
301}
302
303pub(crate) const fn decode_sorted_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
304 let bytes = uuid.as_bytes();
305
306 let ticks: u64 = ((bytes[0]) as u64) << 52
307 | (bytes[1] as u64) << 44
308 | (bytes[2] as u64) << 36
309 | (bytes[3] as u64) << 28
310 | (bytes[4] as u64) << 20
311 | (bytes[5] as u64) << 12
312 | ((bytes[6] & 0xF) as u64) << 8
313 | (bytes[7] as u64);
314
315 let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
316
317 (ticks, counter)
318}
319
320pub(crate) const fn encode_unix_timestamp_millis(
321 millis: u64,
322 counter_random_bytes: &[u8; 10],
323) -> Uuid {
324 let millis_high = ((millis >> 16) & 0xFFFF_FFFF) as u32;
325 let millis_low = (millis & 0xFFFF) as u16;
326
327 let counter_random_version = (counter_random_bytes[1] as u16
328 | ((counter_random_bytes[0] as u16) << 8) & 0x0FFF)
329 | (0x7 << 12);
330
331 let mut d4 = [0; 8];
332
333 d4[0] = (counter_random_bytes[2] & 0x3F) | 0x80;
334 d4[1] = counter_random_bytes[3];
335 d4[2] = counter_random_bytes[4];
336 d4[3] = counter_random_bytes[5];
337 d4[4] = counter_random_bytes[6];
338 d4[5] = counter_random_bytes[7];
339 d4[6] = counter_random_bytes[8];
340 d4[7] = counter_random_bytes[9];
341
342 Uuid::from_fields(millis_high, millis_low, counter_random_version, &d4)
343}
344
345pub(crate) const fn decode_unix_timestamp_millis(uuid: &Uuid) -> u64 {
346 let bytes = uuid.as_bytes();
347
348 let millis: u64 = (bytes[0] as u64) << 40
349 | (bytes[1] as u64) << 32
350 | (bytes[2] as u64) << 24
351 | (bytes[3] as u64) << 16
352 | (bytes[4] as u64) << 8
353 | (bytes[5] as u64);
354
355 millis
356}
357
358#[cfg(all(
359 feature = "std",
360 feature = "js",
361 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))
362))]
363fn now() -> (u64, u32) {
364 use wasm_bindgen::prelude::*;
365
366 #[wasm_bindgen]
367 extern "C" {
368 #[wasm_bindgen(js_namespace = Date, catch)]
370 fn now() -> Result<f64, JsValue>;
371 }
372
373 let now = now().unwrap_throw();
374
375 let secs = (now / 1_000.0) as u64;
376 let nanos = ((now % 1_000.0) * 1_000_000.0) as u32;
377
378 (secs, nanos)
379}
380
381#[cfg(all(
382 feature = "std",
383 not(miri),
384 any(
385 not(feature = "js"),
386 not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))
387 )
388))]
389fn now() -> (u64, u32) {
390 let dur = std::time::SystemTime::UNIX_EPOCH.elapsed().expect(
391 "Getting elapsed time since UNIX_EPOCH. If this fails, we've somehow violated causality",
392 );
393
394 (dur.as_secs(), dur.subsec_nanos())
395}
396
397#[cfg(all(feature = "std", miri))]
398fn now() -> (u64, u32) {
399 use std::{sync::Mutex, time::Duration};
400
401 static TS: Mutex<u64> = Mutex::new(0);
402
403 let ts = Duration::from_nanos({
404 let mut ts = TS.lock().unwrap();
405 *ts += 1;
406 *ts
407 });
408
409 (ts.as_secs(), ts.subsec_nanos())
410}
411
412pub trait ClockSequence {
421 type Output;
423
424 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output;
430
431 fn generate_timestamp_sequence(
437 &self,
438 seconds: u64,
439 subsec_nanos: u32,
440 ) -> (Self::Output, u64, u32) {
441 (
442 self.generate_sequence(seconds, subsec_nanos),
443 seconds,
444 subsec_nanos,
445 )
446 }
447
448 fn usable_bits(&self) -> usize
456 where
457 Self::Output: Sized,
458 {
459 cmp::min(128, core::mem::size_of::<Self::Output>() * 8)
460 }
461}
462
463impl<T: ClockSequence + ?Sized> ClockSequence for &T {
464 type Output = T::Output;
465
466 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
467 (**self).generate_sequence(seconds, subsec_nanos)
468 }
469
470 fn generate_timestamp_sequence(
471 &self,
472 seconds: u64,
473 subsec_nanos: u32,
474 ) -> (Self::Output, u64, u32) {
475 (**self).generate_timestamp_sequence(seconds, subsec_nanos)
476 }
477
478 fn usable_bits(&self) -> usize
479 where
480 Self::Output: Sized,
481 {
482 (**self).usable_bits()
483 }
484}
485
486pub mod context {
488 use super::ClockSequence;
489
490 #[cfg(any(feature = "v1", feature = "v6"))]
491 mod v1_support {
492 use super::*;
493
494 #[cfg(all(feature = "std", feature = "rng"))]
495 use crate::std::sync::LazyLock;
496
497 use atomic::{Atomic, Ordering};
498
499 #[cfg(all(feature = "std", feature = "rng"))]
500 static CONTEXT: LazyLock<ContextV1> = LazyLock::new(ContextV1::new_random);
501
502 #[cfg(all(feature = "std", feature = "rng"))]
503 pub(crate) fn shared_context_v1() -> &'static ContextV1 {
504 &*CONTEXT
505 }
506
507 #[derive(Debug)]
523 pub struct ContextV1 {
524 count: Atomic<u16>,
525 }
526
527 impl ContextV1 {
528 pub const fn new(count: u16) -> Self {
534 Self {
535 count: Atomic::<u16>::new(count),
536 }
537 }
538
539 #[cfg(feature = "rng")]
541 pub fn new_random() -> Self {
542 Self {
543 count: Atomic::<u16>::new(crate::rng::u16()),
544 }
545 }
546 }
547
548 impl ClockSequence for ContextV1 {
549 type Output = u16;
550
551 fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
552 self.count.fetch_add(1, Ordering::AcqRel) & (u16::MAX >> 2)
558 }
559
560 fn usable_bits(&self) -> usize {
561 14
562 }
563 }
564
565 #[deprecated(since = "1.23.0", note = "renamed to `ContextV1`")]
566 #[doc(hidden)]
567 pub type Context = ContextV1;
568
569 #[cfg(test)]
570 mod tests {
571 use crate::Timestamp;
572
573 use super::*;
574
575 #[test]
576 fn context() {
577 let seconds = 1_496_854_535;
578 let subsec_nanos = 812_946_000;
579
580 let context = ContextV1::new(u16::MAX >> 2);
581
582 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
583 assert_eq!(16383, ts.counter);
584 assert_eq!(14, ts.usable_counter_bits);
585
586 let seconds = 1_496_854_536;
587
588 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
589 assert_eq!(0, ts.counter);
590
591 let seconds = 1_496_854_535;
592
593 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
594 assert_eq!(1, ts.counter);
595 }
596
597 #[test]
598 fn context_overflow() {
599 let seconds = u64::MAX;
600 let subsec_nanos = u32::MAX;
601
602 let context = ContextV1::new(u16::MAX);
603
604 Timestamp::from_unix(&context, seconds, subsec_nanos);
606 }
607 }
608 }
609
610 #[cfg(any(feature = "v1", feature = "v6"))]
611 pub use v1_support::*;
612
613 #[cfg(feature = "std")]
614 mod std_support {
615 use super::*;
616
617 use core::panic::{AssertUnwindSafe, RefUnwindSafe};
618 use std::{sync::Mutex, thread::LocalKey};
619
620 pub struct ThreadLocalContext<C: 'static>(&'static LocalKey<C>);
622
623 impl<C> std::fmt::Debug for ThreadLocalContext<C> {
624 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
625 f.debug_struct("ThreadLocalContext").finish_non_exhaustive()
626 }
627 }
628
629 impl<C: 'static> ThreadLocalContext<C> {
630 pub const fn new(local_key: &'static LocalKey<C>) -> Self {
632 ThreadLocalContext(local_key)
633 }
634 }
635
636 impl<C: ClockSequence + 'static> ClockSequence for ThreadLocalContext<C> {
637 type Output = C::Output;
638
639 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
640 self.0
641 .with(|ctxt| ctxt.generate_sequence(seconds, subsec_nanos))
642 }
643
644 fn generate_timestamp_sequence(
645 &self,
646 seconds: u64,
647 subsec_nanos: u32,
648 ) -> (Self::Output, u64, u32) {
649 self.0
650 .with(|ctxt| ctxt.generate_timestamp_sequence(seconds, subsec_nanos))
651 }
652
653 fn usable_bits(&self) -> usize {
654 self.0.with(|ctxt| ctxt.usable_bits())
655 }
656 }
657
658 impl<C: ClockSequence> ClockSequence for AssertUnwindSafe<C> {
659 type Output = C::Output;
660
661 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
662 self.0.generate_sequence(seconds, subsec_nanos)
663 }
664
665 fn generate_timestamp_sequence(
666 &self,
667 seconds: u64,
668 subsec_nanos: u32,
669 ) -> (Self::Output, u64, u32) {
670 self.0.generate_timestamp_sequence(seconds, subsec_nanos)
671 }
672
673 fn usable_bits(&self) -> usize
674 where
675 Self::Output: Sized,
676 {
677 self.0.usable_bits()
678 }
679 }
680
681 impl<C: ClockSequence + RefUnwindSafe> ClockSequence for Mutex<C> {
682 type Output = C::Output;
683
684 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
685 self.lock()
686 .unwrap_or_else(|err| err.into_inner())
687 .generate_sequence(seconds, subsec_nanos)
688 }
689
690 fn generate_timestamp_sequence(
691 &self,
692 seconds: u64,
693 subsec_nanos: u32,
694 ) -> (Self::Output, u64, u32) {
695 self.lock()
696 .unwrap_or_else(|err| err.into_inner())
697 .generate_timestamp_sequence(seconds, subsec_nanos)
698 }
699
700 fn usable_bits(&self) -> usize
701 where
702 Self::Output: Sized,
703 {
704 self.lock()
705 .unwrap_or_else(|err| err.into_inner())
706 .usable_bits()
707 }
708 }
709 }
710
711 #[cfg(feature = "std")]
712 pub use std_support::*;
713
714 #[cfg(feature = "v7")]
715 mod v7_support {
716 use super::*;
717
718 use core::{cell::Cell, cmp, panic::RefUnwindSafe};
719
720 #[cfg(feature = "std")]
721 static CONTEXT_V7: SharedContextV7 =
722 SharedContextV7(std::sync::Mutex::new(ContextV7::new()));
723
724 #[cfg(feature = "std")]
725 pub(crate) fn shared_context_v7() -> &'static SharedContextV7 {
726 &CONTEXT_V7
727 }
728
729 const USABLE_BITS: usize = 42;
730
731 const RESEED_MASK: u64 = u64::MAX >> 23;
736 const MAX_COUNTER: u64 = u64::MAX >> 22;
737
738 #[derive(Debug)]
764 pub struct ContextV7 {
765 timestamp: Cell<ReseedingTimestamp>,
766 counter: Cell<Counter>,
767 adjust: Adjust,
768 precision: Precision,
769 }
770
771 impl RefUnwindSafe for ContextV7 {}
772
773 impl ContextV7 {
774 pub const fn new() -> Self {
777 ContextV7 {
778 timestamp: Cell::new(ReseedingTimestamp {
779 last_seed: 0,
780 seconds: 0,
781 subsec_nanos: 0,
782 }),
783 counter: Cell::new(Counter { value: 0 }),
784 adjust: Adjust { by_ns: 0 },
785 precision: Precision {
786 bits: 0,
787 mask: 0,
788 factor: 0,
789 shift: 0,
790 },
791 }
792 }
793
794 pub fn with_adjust_by_millis(mut self, millis: u32) -> Self {
796 self.adjust = Adjust::by_millis(millis);
797 self
798 }
799
800 pub fn with_additional_precision(self) -> Self {
807 self.with_additional_precision_bits(12)
808 }
809
810 pub fn with_additional_precision_bits(mut self, bits: usize) -> Self {
820 self.precision = Precision::new(cmp::min(bits, 12));
821 self
822 }
823 }
824
825 impl ClockSequence for ContextV7 {
826 type Output = u64;
827
828 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
829 self.generate_timestamp_sequence(seconds, subsec_nanos).0
830 }
831
832 fn generate_timestamp_sequence(
833 &self,
834 seconds: u64,
835 subsec_nanos: u32,
836 ) -> (Self::Output, u64, u32) {
837 let (seconds, subsec_nanos) = self.adjust.apply(seconds, subsec_nanos);
838
839 let mut counter;
840 let (mut timestamp, should_reseed) =
841 self.timestamp.get().advance(seconds, subsec_nanos);
842
843 if should_reseed {
844 counter = Counter::reseed(&self.precision, ×tamp);
846 } else {
847 counter = self.counter.get().increment(&self.precision, ×tamp);
854
855 if counter.has_overflowed() {
859 timestamp = timestamp.increment();
861 counter = Counter::reseed(&self.precision, ×tamp);
862 }
863 };
864
865 self.timestamp.set(timestamp);
866 self.counter.set(counter);
867
868 (counter.value, timestamp.seconds, timestamp.subsec_nanos)
869 }
870
871 fn usable_bits(&self) -> usize {
872 USABLE_BITS
873 }
874 }
875
876 #[derive(Debug, Default, Clone, Copy)]
878 struct ReseedingTimestamp {
879 last_seed: u64,
880 seconds: u64,
881 subsec_nanos: u32,
882 }
883
884 impl ReseedingTimestamp {
885 #[inline]
886 fn from_ts(seconds: u64, subsec_nanos: u32) -> Self {
887 let last_seed = seconds
889 .saturating_mul(1_000)
890 .saturating_add((subsec_nanos / 1_000_000) as u64);
891
892 ReseedingTimestamp {
893 last_seed,
894 seconds,
895 subsec_nanos,
896 }
897 }
898
899 #[inline]
901 fn advance(&self, seconds: u64, subsec_nanos: u32) -> (Self, bool) {
902 let incoming = ReseedingTimestamp::from_ts(seconds, subsec_nanos);
903
904 if incoming.last_seed > self.last_seed {
905 (incoming, true)
909 } else if incoming.last_seed == self.last_seed {
910 let mut value = *self;
914 value.subsec_nanos = cmp::max(self.subsec_nanos, subsec_nanos);
915
916 (value, false)
917 } else {
918 (*self, false)
922 }
923 }
924
925 #[inline]
927 fn increment(&self) -> Self {
928 let (seconds, subsec_nanos) =
929 Adjust::by_millis(1).apply(self.seconds, self.subsec_nanos);
930
931 ReseedingTimestamp::from_ts(seconds, subsec_nanos)
932 }
933
934 #[inline]
935 fn submilli_nanos(&self) -> u32 {
936 self.subsec_nanos % 1_000_000
937 }
938 }
939
940 #[derive(Debug, Clone, Copy)]
942 struct Counter {
943 value: u64,
944 }
945
946 impl Counter {
947 #[inline]
948 fn reseed(precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
949 Counter {
950 value: precision.apply(crate::rng::u64() & RESEED_MASK, timestamp),
951 }
952 }
953
954 #[inline]
956 fn increment(&self, precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
957 let mut counter = Counter {
958 value: precision.apply(self.value, timestamp),
959 };
960
961 counter.value += 1;
968
969 counter
970 }
971
972 #[inline]
973 fn has_overflowed(&self) -> bool {
974 self.value > MAX_COUNTER
975 }
976 }
977
978 #[derive(Debug)]
980 struct Adjust {
981 by_ns: u128,
982 }
983
984 impl Adjust {
985 #[inline]
986 fn by_millis(millis: u32) -> Self {
987 Adjust {
988 by_ns: (millis as u128).saturating_mul(1_000_000),
989 }
990 }
991
992 #[inline]
994 fn apply(&self, seconds: u64, subsec_nanos: u32) -> (u64, u32) {
995 if self.by_ns == 0 {
996 return (seconds, subsec_nanos);
998 }
999
1000 let ts = (seconds as u128)
1001 .saturating_mul(1_000_000_000)
1002 .saturating_add(subsec_nanos as u128)
1003 .saturating_add(self.by_ns);
1004
1005 ((ts / 1_000_000_000) as u64, (ts % 1_000_000_000) as u32)
1006 }
1007 }
1008
1009 #[derive(Debug)]
1011 struct Precision {
1012 bits: usize,
1013 factor: u64,
1014 mask: u64,
1015 shift: u64,
1016 }
1017
1018 impl Precision {
1019 fn new(bits: usize) -> Self {
1020 let mask = u64::MAX >> (64 - USABLE_BITS + bits);
1023 let shift = (USABLE_BITS - bits) as u64;
1024
1025 let factor = (999_999 / u64::pow(2, bits as u32)) + 1;
1028
1029 Precision {
1030 bits,
1031 factor,
1032 mask,
1033 shift,
1034 }
1035 }
1036
1037 #[inline]
1039 fn apply(&self, counter: u64, timestamp: &ReseedingTimestamp) -> u64 {
1040 if self.bits == 0 {
1041 return counter;
1043 }
1044
1045 let additional = timestamp.submilli_nanos() as u64 / self.factor;
1046
1047 (counter & self.mask) | (additional << self.shift)
1048 }
1049 }
1050
1051 #[cfg(feature = "std")]
1052 pub(crate) struct SharedContextV7(std::sync::Mutex<ContextV7>);
1053
1054 #[cfg(feature = "std")]
1055 impl ClockSequence for SharedContextV7 {
1056 type Output = u64;
1057
1058 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
1059 self.0.generate_sequence(seconds, subsec_nanos)
1060 }
1061
1062 fn generate_timestamp_sequence(
1063 &self,
1064 seconds: u64,
1065 subsec_nanos: u32,
1066 ) -> (Self::Output, u64, u32) {
1067 self.0.generate_timestamp_sequence(seconds, subsec_nanos)
1068 }
1069
1070 fn usable_bits(&self) -> usize
1071 where
1072 Self::Output: Sized,
1073 {
1074 USABLE_BITS
1075 }
1076 }
1077
1078 #[cfg(test)]
1079 mod tests {
1080 use core::time::Duration;
1081
1082 use super::*;
1083
1084 use crate::{Timestamp, Uuid};
1085
1086 #[test]
1087 fn context() {
1088 let seconds = 1_496_854_535;
1089 let subsec_nanos = 812_946_000;
1090
1091 let context = ContextV7::new();
1092
1093 let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1094 assert_eq!(42, ts1.usable_counter_bits);
1095
1096 let seconds = 1_496_854_534;
1098
1099 let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1100
1101 assert_eq!(ts1.seconds, ts2.seconds);
1104 assert_eq!(ts1.subsec_nanos, ts2.subsec_nanos);
1105 assert_eq!(ts1.counter + 1, ts2.counter);
1106
1107 let seconds = 1_496_854_536;
1109
1110 let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1111
1112 assert_ne!(ts2.counter + 1, ts3.counter);
1114 assert_ne!(0, ts3.counter);
1115 }
1116
1117 #[test]
1118 fn context_wrap() {
1119 let seconds = 1_496_854_535u64;
1120 let subsec_nanos = 812_946_000u32;
1121
1122 let context = ContextV7 {
1124 timestamp: Cell::new(ReseedingTimestamp::from_ts(seconds, subsec_nanos)),
1125 adjust: Adjust::by_millis(0),
1126 precision: Precision {
1127 bits: 0,
1128 mask: 0,
1129 factor: 0,
1130 shift: 0,
1131 },
1132 counter: Cell::new(Counter {
1133 value: u64::MAX >> 22,
1134 }),
1135 };
1136
1137 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1138
1139 let expected_ts = Duration::new(seconds, subsec_nanos) + Duration::from_millis(1);
1141 assert_eq!(expected_ts.as_secs(), ts.seconds);
1142 assert_eq!(expected_ts.subsec_nanos(), ts.subsec_nanos);
1143
1144 assert!(ts.counter < (u64::MAX >> 22) as u128);
1146 assert_ne!(0, ts.counter);
1147 }
1148
1149 #[test]
1150 fn context_shift() {
1151 let seconds = 1_496_854_535;
1152 let subsec_nanos = 812_946_000;
1153
1154 let context = ContextV7::new().with_adjust_by_millis(1);
1155
1156 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1157
1158 assert_eq!((1_496_854_535, 813_946_000), ts.to_unix());
1159 }
1160
1161 #[test]
1162 fn context_additional_precision() {
1163 let seconds = 1_496_854_535;
1164 let subsec_nanos = 812_946_000;
1165
1166 let context = ContextV7::new().with_additional_precision();
1167
1168 let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1169
1170 assert_eq!(3861, ts1.counter >> 30);
1172
1173 assert!(ts1.counter < (u64::MAX >> 22) as u128);
1174
1175 let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1177
1178 assert!(Uuid::new_v7(ts2) > Uuid::new_v7(ts1));
1179
1180 let subsec_nanos = subsec_nanos + 1;
1182
1183 let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1184
1185 assert!(Uuid::new_v7(ts3) > Uuid::new_v7(ts2));
1186 }
1187
1188 #[test]
1189 fn context_additional_precision_bits() {
1190 let seconds = 1_496_854_535;
1191 let subsec_nanos = 812_946_000;
1192
1193 let context = ContextV7::new().with_additional_precision_bits(10);
1196
1197 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1198
1199 assert_eq!(968, ts.counter >> 32);
1202
1203 assert!(ts.counter < (u64::MAX >> 22) as u128);
1204
1205 let full = Timestamp::from_unix(
1207 &ContextV7::new().with_additional_precision(),
1208 seconds,
1209 subsec_nanos,
1210 );
1211 let bits12 = Timestamp::from_unix(
1212 &ContextV7::new().with_additional_precision_bits(12),
1213 seconds,
1214 subsec_nanos,
1215 );
1216 assert_eq!(full.counter >> 30, bits12.counter >> 30);
1217
1218 let capped = Timestamp::from_unix(
1220 &ContextV7::new().with_additional_precision_bits(64),
1221 seconds,
1222 subsec_nanos,
1223 );
1224 assert_eq!(bits12.counter >> 30, capped.counter >> 30);
1225
1226 let none = ContextV7::new().with_additional_precision_bits(0);
1228 assert_eq!(0, none.precision.bits);
1229 }
1230
1231 #[test]
1232 fn context_overflow() {
1233 let seconds = u64::MAX;
1234 let subsec_nanos = u32::MAX;
1235
1236 for context in [
1238 ContextV7::new(),
1239 ContextV7::new().with_additional_precision(),
1240 ContextV7::new().with_adjust_by_millis(u32::MAX),
1241 ] {
1242 Timestamp::from_unix(&context, seconds, subsec_nanos);
1243 }
1244 }
1245
1246 #[test]
1247 fn context_subsec_ordering() {
1248 let context = ContextV7::new();
1249
1250 let a = Timestamp::from_unix(&context, 100, 0);
1253 let b = Timestamp::from_unix(&context, 99, 2_000_000);
1254 let c = Timestamp::from_unix(&context, 100, 1_000_000);
1255
1256 assert!(Uuid::new_v7(a) < Uuid::new_v7(b), "a: {a:?} < b: {b:?}");
1257 assert!(Uuid::new_v7(b) < Uuid::new_v7(c), "b: {b:?} < c: {c:?}");
1258 }
1259 }
1260 }
1261
1262 #[cfg(feature = "v7")]
1263 pub use v7_support::*;
1264
1265 #[derive(Debug, Clone, Copy, Default)]
1276 pub struct NoContext;
1277
1278 impl ClockSequence for NoContext {
1279 type Output = u16;
1280
1281 fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
1282 0
1283 }
1284
1285 fn usable_bits(&self) -> usize {
1286 0
1287 }
1288 }
1289}
1290
1291#[cfg(all(test, any(feature = "v1", feature = "v6")))]
1292mod tests {
1293 use super::*;
1294
1295 #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))]
1296 use wasm_bindgen_test::*;
1297
1298 #[test]
1299 #[cfg_attr(
1300 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1301 wasm_bindgen_test
1302 )]
1303 fn gregorian_unix_does_not_panic() {
1304 Timestamp::unix_to_gregorian_ticks(u64::MAX, 0);
1306 Timestamp::unix_to_gregorian_ticks(0, u32::MAX);
1307 Timestamp::unix_to_gregorian_ticks(u64::MAX, u32::MAX);
1308
1309 Timestamp::gregorian_to_unix(u64::MAX);
1310 }
1311
1312 #[test]
1313 #[cfg_attr(
1314 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1315 wasm_bindgen_test
1316 )]
1317 fn to_gregorian_truncates_to_usable_bits() {
1318 let ts = Timestamp::from_gregorian_time(123, u16::MAX);
1319
1320 assert_eq!((123, u16::MAX >> 2), ts.to_gregorian());
1321 }
1322
1323 #[test]
1324 #[cfg_attr(
1325 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1326 wasm_bindgen_test
1327 )]
1328 fn clock_sequence_usable_bits() {
1329 struct MyContext;
1330
1331 impl ClockSequence for MyContext {
1332 type Output = u16;
1333
1334 fn generate_sequence(&self, _: u64, _: u32) -> Self::Output {
1335 0
1336 }
1337 }
1338
1339 assert_eq!(16, MyContext.usable_bits());
1340 }
1341
1342 #[cfg(all(test, feature = "std", not(miri)))]
1343 mod std_support {
1344 use super::*;
1345
1346 use std::time::{Duration, SystemTime};
1347
1348 const KNOWN_SECONDS: u64 = 1_501_520_400;
1350 const KNOWN_NANOS: u32 = 1_000;
1351
1352 fn known_system_time() -> SystemTime {
1353 SystemTime::UNIX_EPOCH
1354 .checked_add(Duration::new(KNOWN_SECONDS, KNOWN_NANOS))
1355 .unwrap()
1356 }
1357
1358 fn known_timestamp() -> Timestamp {
1359 Timestamp::from_unix_time(KNOWN_SECONDS, KNOWN_NANOS, 0, 0)
1360 }
1361
1362 #[test]
1363 fn to_system_time() {
1364 let st: SystemTime = known_timestamp().into();
1365
1366 assert_eq!(known_system_time(), st);
1367 }
1368
1369 #[test]
1370 fn from_system_time() {
1371 let ts: Timestamp = known_system_time().try_into().unwrap();
1372
1373 assert_eq!(known_timestamp(), ts);
1374 }
1375
1376 #[test]
1377 fn from_system_time_before_epoch() {
1378 let before_epoch = match SystemTime::UNIX_EPOCH.checked_sub(Duration::from_nanos(1_000))
1379 {
1380 Some(st) => st,
1381 None => return,
1382 };
1383
1384 Timestamp::try_from(before_epoch)
1385 .expect_err("Timestamp should not be created from before epoch");
1386 }
1387
1388 #[test]
1389 fn from_system_time_max() {
1390 let ts = Timestamp::from_unix_time(u64::MAX, 999_999_999, 0, 0);
1391
1392 let _: SystemTime = ts.into();
1394 }
1395 }
1396}