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(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(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 {
225 let (seconds, subsec_nanos) = ts.to_unix();
226
227 Self::UNIX_EPOCH + std::time::Duration::new(seconds, subsec_nanos)
228 }
229}
230
231pub(crate) const fn encode_gregorian_timestamp(
232 ticks: u64,
233 counter: u16,
234 node_id: &[u8; 6],
235) -> Uuid {
236 let time_low = (ticks & 0xFFFF_FFFF) as u32;
237 let time_mid = ((ticks >> 32) & 0xFFFF) as u16;
238 let time_high_and_version = (((ticks >> 48) & 0x0FFF) as u16) | (1 << 12);
239
240 let mut d4 = [0; 8];
241
242 d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
243 d4[1] = (counter & 0xFF) as u8;
244 d4[2] = node_id[0];
245 d4[3] = node_id[1];
246 d4[4] = node_id[2];
247 d4[5] = node_id[3];
248 d4[6] = node_id[4];
249 d4[7] = node_id[5];
250
251 Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
252}
253
254pub(crate) const fn decode_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
255 let bytes = uuid.as_bytes();
256
257 let ticks: u64 = ((bytes[6] & 0x0F) as u64) << 56
258 | (bytes[7] as u64) << 48
259 | (bytes[4] as u64) << 40
260 | (bytes[5] as u64) << 32
261 | (bytes[0] as u64) << 24
262 | (bytes[1] as u64) << 16
263 | (bytes[2] as u64) << 8
264 | (bytes[3] as u64);
265
266 let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
267
268 (ticks, counter)
269}
270
271pub(crate) const fn encode_sorted_gregorian_timestamp(
272 ticks: u64,
273 counter: u16,
274 node_id: &[u8; 6],
275) -> Uuid {
276 let time_high = ((ticks >> 28) & 0xFFFF_FFFF) as u32;
277 let time_mid = ((ticks >> 12) & 0xFFFF) as u16;
278 let time_low_and_version = ((ticks & 0x0FFF) as u16) | (0x6 << 12);
279
280 let mut d4 = [0; 8];
281
282 d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
283 d4[1] = (counter & 0xFF) as u8;
284 d4[2] = node_id[0];
285 d4[3] = node_id[1];
286 d4[4] = node_id[2];
287 d4[5] = node_id[3];
288 d4[6] = node_id[4];
289 d4[7] = node_id[5];
290
291 Uuid::from_fields(time_high, time_mid, time_low_and_version, &d4)
292}
293
294pub(crate) const fn decode_sorted_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
295 let bytes = uuid.as_bytes();
296
297 let ticks: u64 = ((bytes[0]) as u64) << 52
298 | (bytes[1] as u64) << 44
299 | (bytes[2] as u64) << 36
300 | (bytes[3] as u64) << 28
301 | (bytes[4] as u64) << 20
302 | (bytes[5] as u64) << 12
303 | ((bytes[6] & 0xF) as u64) << 8
304 | (bytes[7] as u64);
305
306 let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
307
308 (ticks, counter)
309}
310
311pub(crate) const fn encode_unix_timestamp_millis(
312 millis: u64,
313 counter_random_bytes: &[u8; 10],
314) -> Uuid {
315 let millis_high = ((millis >> 16) & 0xFFFF_FFFF) as u32;
316 let millis_low = (millis & 0xFFFF) as u16;
317
318 let counter_random_version = (counter_random_bytes[1] as u16
319 | ((counter_random_bytes[0] as u16) << 8) & 0x0FFF)
320 | (0x7 << 12);
321
322 let mut d4 = [0; 8];
323
324 d4[0] = (counter_random_bytes[2] & 0x3F) | 0x80;
325 d4[1] = counter_random_bytes[3];
326 d4[2] = counter_random_bytes[4];
327 d4[3] = counter_random_bytes[5];
328 d4[4] = counter_random_bytes[6];
329 d4[5] = counter_random_bytes[7];
330 d4[6] = counter_random_bytes[8];
331 d4[7] = counter_random_bytes[9];
332
333 Uuid::from_fields(millis_high, millis_low, counter_random_version, &d4)
334}
335
336pub(crate) const fn decode_unix_timestamp_millis(uuid: &Uuid) -> u64 {
337 let bytes = uuid.as_bytes();
338
339 let millis: u64 = (bytes[0] as u64) << 40
340 | (bytes[1] as u64) << 32
341 | (bytes[2] as u64) << 24
342 | (bytes[3] as u64) << 16
343 | (bytes[4] as u64) << 8
344 | (bytes[5] as u64);
345
346 millis
347}
348
349#[cfg(all(
350 feature = "std",
351 feature = "js",
352 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))
353))]
354fn now() -> (u64, u32) {
355 use wasm_bindgen::prelude::*;
356
357 #[wasm_bindgen]
358 extern "C" {
359 #[wasm_bindgen(js_namespace = Date, catch)]
361 fn now() -> Result<f64, JsValue>;
362 }
363
364 let now = now().unwrap_throw();
365
366 let secs = (now / 1_000.0) as u64;
367 let nanos = ((now % 1_000.0) * 1_000_000.0) as u32;
368
369 (secs, nanos)
370}
371
372#[cfg(all(
373 feature = "std",
374 not(miri),
375 any(
376 not(feature = "js"),
377 not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))
378 )
379))]
380fn now() -> (u64, u32) {
381 let dur = std::time::SystemTime::UNIX_EPOCH.elapsed().expect(
382 "Getting elapsed time since UNIX_EPOCH. If this fails, we've somehow violated causality",
383 );
384
385 (dur.as_secs(), dur.subsec_nanos())
386}
387
388#[cfg(all(feature = "std", miri))]
389fn now() -> (u64, u32) {
390 use std::{sync::Mutex, time::Duration};
391
392 static TS: Mutex<u64> = Mutex::new(0);
393
394 let ts = Duration::from_nanos({
395 let mut ts = TS.lock().unwrap();
396 *ts += 1;
397 *ts
398 });
399
400 (ts.as_secs(), ts.subsec_nanos())
401}
402
403pub trait ClockSequence {
412 type Output;
414
415 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output;
421
422 fn generate_timestamp_sequence(
428 &self,
429 seconds: u64,
430 subsec_nanos: u32,
431 ) -> (Self::Output, u64, u32) {
432 (
433 self.generate_sequence(seconds, subsec_nanos),
434 seconds,
435 subsec_nanos,
436 )
437 }
438
439 fn usable_bits(&self) -> usize
447 where
448 Self::Output: Sized,
449 {
450 cmp::min(128, core::mem::size_of::<Self::Output>() * 8)
451 }
452}
453
454impl<T: ClockSequence + ?Sized> ClockSequence for &T {
455 type Output = T::Output;
456
457 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
458 (**self).generate_sequence(seconds, subsec_nanos)
459 }
460
461 fn generate_timestamp_sequence(
462 &self,
463 seconds: u64,
464 subsec_nanos: u32,
465 ) -> (Self::Output, u64, u32) {
466 (**self).generate_timestamp_sequence(seconds, subsec_nanos)
467 }
468
469 fn usable_bits(&self) -> usize
470 where
471 Self::Output: Sized,
472 {
473 (**self).usable_bits()
474 }
475}
476
477pub mod context {
479 use super::ClockSequence;
480
481 #[cfg(any(feature = "v1", feature = "v6"))]
482 mod v1_support {
483 use super::*;
484
485 #[cfg(all(feature = "std", feature = "rng"))]
486 use crate::std::sync::LazyLock;
487
488 use atomic::{Atomic, Ordering};
489
490 #[cfg(all(feature = "std", feature = "rng"))]
491 static CONTEXT: LazyLock<ContextV1> = LazyLock::new(ContextV1::new_random);
492
493 #[cfg(all(feature = "std", feature = "rng"))]
494 pub(crate) fn shared_context_v1() -> &'static ContextV1 {
495 &*CONTEXT
496 }
497
498 #[derive(Debug)]
514 pub struct ContextV1 {
515 count: Atomic<u16>,
516 }
517
518 impl ContextV1 {
519 pub const fn new(count: u16) -> Self {
525 Self {
526 count: Atomic::<u16>::new(count),
527 }
528 }
529
530 #[cfg(feature = "rng")]
532 pub fn new_random() -> Self {
533 Self {
534 count: Atomic::<u16>::new(crate::rng::u16()),
535 }
536 }
537 }
538
539 impl ClockSequence for ContextV1 {
540 type Output = u16;
541
542 fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
543 self.count.fetch_add(1, Ordering::AcqRel) & (u16::MAX >> 2)
549 }
550
551 fn usable_bits(&self) -> usize {
552 14
553 }
554 }
555
556 #[deprecated(since = "1.23.0", note = "renamed to `ContextV1`")]
557 #[doc(hidden)]
558 pub type Context = ContextV1;
559
560 #[cfg(test)]
561 mod tests {
562 use crate::Timestamp;
563
564 use super::*;
565
566 #[test]
567 fn context() {
568 let seconds = 1_496_854_535;
569 let subsec_nanos = 812_946_000;
570
571 let context = ContextV1::new(u16::MAX >> 2);
572
573 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
574 assert_eq!(16383, ts.counter);
575 assert_eq!(14, ts.usable_counter_bits);
576
577 let seconds = 1_496_854_536;
578
579 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
580 assert_eq!(0, ts.counter);
581
582 let seconds = 1_496_854_535;
583
584 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
585 assert_eq!(1, ts.counter);
586 }
587
588 #[test]
589 fn context_overflow() {
590 let seconds = u64::MAX;
591 let subsec_nanos = u32::MAX;
592
593 let context = ContextV1::new(u16::MAX);
594
595 Timestamp::from_unix(&context, seconds, subsec_nanos);
597 }
598 }
599 }
600
601 #[cfg(any(feature = "v1", feature = "v6"))]
602 pub use v1_support::*;
603
604 #[cfg(feature = "std")]
605 mod std_support {
606 use super::*;
607
608 use core::panic::{AssertUnwindSafe, RefUnwindSafe};
609 use std::{sync::Mutex, thread::LocalKey};
610
611 pub struct ThreadLocalContext<C: 'static>(&'static LocalKey<C>);
613
614 impl<C> std::fmt::Debug for ThreadLocalContext<C> {
615 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
616 f.debug_struct("ThreadLocalContext").finish_non_exhaustive()
617 }
618 }
619
620 impl<C: 'static> ThreadLocalContext<C> {
621 pub const fn new(local_key: &'static LocalKey<C>) -> Self {
623 ThreadLocalContext(local_key)
624 }
625 }
626
627 impl<C: ClockSequence + 'static> ClockSequence for ThreadLocalContext<C> {
628 type Output = C::Output;
629
630 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
631 self.0
632 .with(|ctxt| ctxt.generate_sequence(seconds, subsec_nanos))
633 }
634
635 fn generate_timestamp_sequence(
636 &self,
637 seconds: u64,
638 subsec_nanos: u32,
639 ) -> (Self::Output, u64, u32) {
640 self.0
641 .with(|ctxt| ctxt.generate_timestamp_sequence(seconds, subsec_nanos))
642 }
643
644 fn usable_bits(&self) -> usize {
645 self.0.with(|ctxt| ctxt.usable_bits())
646 }
647 }
648
649 impl<C: ClockSequence> ClockSequence for AssertUnwindSafe<C> {
650 type Output = C::Output;
651
652 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
653 self.0.generate_sequence(seconds, subsec_nanos)
654 }
655
656 fn generate_timestamp_sequence(
657 &self,
658 seconds: u64,
659 subsec_nanos: u32,
660 ) -> (Self::Output, u64, u32) {
661 self.0.generate_timestamp_sequence(seconds, subsec_nanos)
662 }
663
664 fn usable_bits(&self) -> usize
665 where
666 Self::Output: Sized,
667 {
668 self.0.usable_bits()
669 }
670 }
671
672 impl<C: ClockSequence + RefUnwindSafe> ClockSequence for Mutex<C> {
673 type Output = C::Output;
674
675 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
676 self.lock()
677 .unwrap_or_else(|err| err.into_inner())
678 .generate_sequence(seconds, subsec_nanos)
679 }
680
681 fn generate_timestamp_sequence(
682 &self,
683 seconds: u64,
684 subsec_nanos: u32,
685 ) -> (Self::Output, u64, u32) {
686 self.lock()
687 .unwrap_or_else(|err| err.into_inner())
688 .generate_timestamp_sequence(seconds, subsec_nanos)
689 }
690
691 fn usable_bits(&self) -> usize
692 where
693 Self::Output: Sized,
694 {
695 self.lock()
696 .unwrap_or_else(|err| err.into_inner())
697 .usable_bits()
698 }
699 }
700 }
701
702 #[cfg(feature = "std")]
703 pub use std_support::*;
704
705 #[cfg(feature = "v7")]
706 mod v7_support {
707 use super::*;
708
709 use core::{cell::Cell, cmp, panic::RefUnwindSafe};
710
711 #[cfg(feature = "std")]
712 static CONTEXT_V7: SharedContextV7 =
713 SharedContextV7(std::sync::Mutex::new(ContextV7::new()));
714
715 #[cfg(feature = "std")]
716 pub(crate) fn shared_context_v7() -> &'static SharedContextV7 {
717 &CONTEXT_V7
718 }
719
720 const USABLE_BITS: usize = 42;
721
722 const RESEED_MASK: u64 = u64::MAX >> 23;
727 const MAX_COUNTER: u64 = u64::MAX >> 22;
728
729 #[derive(Debug)]
755 pub struct ContextV7 {
756 timestamp: Cell<ReseedingTimestamp>,
757 counter: Cell<Counter>,
758 adjust: Adjust,
759 precision: Precision,
760 }
761
762 impl RefUnwindSafe for ContextV7 {}
763
764 impl ContextV7 {
765 pub const fn new() -> Self {
768 ContextV7 {
769 timestamp: Cell::new(ReseedingTimestamp {
770 last_seed: 0,
771 seconds: 0,
772 subsec_nanos: 0,
773 }),
774 counter: Cell::new(Counter { value: 0 }),
775 adjust: Adjust { by_ns: 0 },
776 precision: Precision {
777 bits: 0,
778 mask: 0,
779 factor: 0,
780 shift: 0,
781 },
782 }
783 }
784
785 pub fn with_adjust_by_millis(mut self, millis: u32) -> Self {
787 self.adjust = Adjust::by_millis(millis);
788 self
789 }
790
791 pub fn with_additional_precision(mut self) -> Self {
798 self.precision = Precision::new(12);
799 self
800 }
801 }
802
803 impl ClockSequence for ContextV7 {
804 type Output = u64;
805
806 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
807 self.generate_timestamp_sequence(seconds, subsec_nanos).0
808 }
809
810 fn generate_timestamp_sequence(
811 &self,
812 seconds: u64,
813 subsec_nanos: u32,
814 ) -> (Self::Output, u64, u32) {
815 let (seconds, subsec_nanos) = self.adjust.apply(seconds, subsec_nanos);
816
817 let mut counter;
818 let (mut timestamp, should_reseed) =
819 self.timestamp.get().advance(seconds, subsec_nanos);
820
821 if should_reseed {
822 counter = Counter::reseed(&self.precision, ×tamp);
824 } else {
825 counter = self.counter.get().increment(&self.precision, ×tamp);
832
833 if counter.has_overflowed() {
837 timestamp = timestamp.increment();
839 counter = Counter::reseed(&self.precision, ×tamp);
840 }
841 };
842
843 self.timestamp.set(timestamp);
844 self.counter.set(counter);
845
846 (counter.value, timestamp.seconds, timestamp.subsec_nanos)
847 }
848
849 fn usable_bits(&self) -> usize {
850 USABLE_BITS
851 }
852 }
853
854 #[derive(Debug, Default, Clone, Copy)]
856 struct ReseedingTimestamp {
857 last_seed: u64,
858 seconds: u64,
859 subsec_nanos: u32,
860 }
861
862 impl ReseedingTimestamp {
863 #[inline]
864 fn from_ts(seconds: u64, subsec_nanos: u32) -> Self {
865 let last_seed = seconds
867 .saturating_mul(1_000)
868 .saturating_add((subsec_nanos / 1_000_000) as u64);
869
870 ReseedingTimestamp {
871 last_seed,
872 seconds,
873 subsec_nanos,
874 }
875 }
876
877 #[inline]
879 fn advance(&self, seconds: u64, subsec_nanos: u32) -> (Self, bool) {
880 let incoming = ReseedingTimestamp::from_ts(seconds, subsec_nanos);
881
882 if incoming.last_seed > self.last_seed {
883 (incoming, true)
885 } else {
886 let mut value = *self;
889 value.subsec_nanos = cmp::max(self.subsec_nanos, subsec_nanos);
890
891 (value, false)
892 }
893 }
894
895 #[inline]
897 fn increment(&self) -> Self {
898 let (seconds, subsec_nanos) =
899 Adjust::by_millis(1).apply(self.seconds, self.subsec_nanos);
900
901 ReseedingTimestamp::from_ts(seconds, subsec_nanos)
902 }
903
904 #[inline]
905 fn submilli_nanos(&self) -> u32 {
906 self.subsec_nanos % 1_000_000
907 }
908 }
909
910 #[derive(Debug, Clone, Copy)]
912 struct Counter {
913 value: u64,
914 }
915
916 impl Counter {
917 #[inline]
918 fn reseed(precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
919 Counter {
920 value: precision.apply(crate::rng::u64() & RESEED_MASK, timestamp),
921 }
922 }
923
924 #[inline]
926 fn increment(&self, precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
927 let mut counter = Counter {
928 value: precision.apply(self.value, timestamp),
929 };
930
931 counter.value += 1;
938
939 counter
940 }
941
942 #[inline]
943 fn has_overflowed(&self) -> bool {
944 self.value > MAX_COUNTER
945 }
946 }
947
948 #[derive(Debug)]
950 struct Adjust {
951 by_ns: u128,
952 }
953
954 impl Adjust {
955 #[inline]
956 fn by_millis(millis: u32) -> Self {
957 Adjust {
958 by_ns: (millis as u128).saturating_mul(1_000_000),
959 }
960 }
961
962 #[inline]
964 fn apply(&self, seconds: u64, subsec_nanos: u32) -> (u64, u32) {
965 if self.by_ns == 0 {
966 return (seconds, subsec_nanos);
968 }
969
970 let ts = (seconds as u128)
971 .saturating_mul(1_000_000_000)
972 .saturating_add(subsec_nanos as u128)
973 .saturating_add(self.by_ns);
974
975 ((ts / 1_000_000_000) as u64, (ts % 1_000_000_000) as u32)
976 }
977 }
978
979 #[derive(Debug)]
981 struct Precision {
982 bits: usize,
983 factor: u64,
984 mask: u64,
985 shift: u64,
986 }
987
988 impl Precision {
989 fn new(bits: usize) -> Self {
990 let mask = u64::MAX >> (64 - USABLE_BITS + bits);
993 let shift = (USABLE_BITS - bits) as u64;
994
995 let factor = (999_999 / u64::pow(2, bits as u32)) + 1;
998
999 Precision {
1000 bits,
1001 factor,
1002 mask,
1003 shift,
1004 }
1005 }
1006
1007 #[inline]
1009 fn apply(&self, counter: u64, timestamp: &ReseedingTimestamp) -> u64 {
1010 if self.bits == 0 {
1011 return counter;
1013 }
1014
1015 let additional = timestamp.submilli_nanos() as u64 / self.factor;
1016
1017 (counter & self.mask) | (additional << self.shift)
1018 }
1019 }
1020
1021 #[cfg(feature = "std")]
1022 pub(crate) struct SharedContextV7(std::sync::Mutex<ContextV7>);
1023
1024 #[cfg(feature = "std")]
1025 impl ClockSequence for SharedContextV7 {
1026 type Output = u64;
1027
1028 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
1029 self.0.generate_sequence(seconds, subsec_nanos)
1030 }
1031
1032 fn generate_timestamp_sequence(
1033 &self,
1034 seconds: u64,
1035 subsec_nanos: u32,
1036 ) -> (Self::Output, u64, u32) {
1037 self.0.generate_timestamp_sequence(seconds, subsec_nanos)
1038 }
1039
1040 fn usable_bits(&self) -> usize
1041 where
1042 Self::Output: Sized,
1043 {
1044 USABLE_BITS
1045 }
1046 }
1047
1048 #[cfg(test)]
1049 mod tests {
1050 use core::time::Duration;
1051
1052 use super::*;
1053
1054 use crate::{Timestamp, Uuid};
1055
1056 #[test]
1057 fn context() {
1058 let seconds = 1_496_854_535;
1059 let subsec_nanos = 812_946_000;
1060
1061 let context = ContextV7::new();
1062
1063 let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1064 assert_eq!(42, ts1.usable_counter_bits);
1065
1066 let seconds = 1_496_854_534;
1068
1069 let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1070
1071 assert_eq!(ts1.seconds, ts2.seconds);
1074 assert_eq!(ts1.subsec_nanos, ts2.subsec_nanos);
1075 assert_eq!(ts1.counter + 1, ts2.counter);
1076
1077 let seconds = 1_496_854_536;
1079
1080 let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1081
1082 assert_ne!(ts2.counter + 1, ts3.counter);
1084 assert_ne!(0, ts3.counter);
1085 }
1086
1087 #[test]
1088 fn context_wrap() {
1089 let seconds = 1_496_854_535u64;
1090 let subsec_nanos = 812_946_000u32;
1091
1092 let context = ContextV7 {
1094 timestamp: Cell::new(ReseedingTimestamp::from_ts(seconds, subsec_nanos)),
1095 adjust: Adjust::by_millis(0),
1096 precision: Precision {
1097 bits: 0,
1098 mask: 0,
1099 factor: 0,
1100 shift: 0,
1101 },
1102 counter: Cell::new(Counter {
1103 value: u64::MAX >> 22,
1104 }),
1105 };
1106
1107 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1108
1109 let expected_ts = Duration::new(seconds, subsec_nanos) + Duration::from_millis(1);
1111 assert_eq!(expected_ts.as_secs(), ts.seconds);
1112 assert_eq!(expected_ts.subsec_nanos(), ts.subsec_nanos);
1113
1114 assert!(ts.counter < (u64::MAX >> 22) as u128);
1116 assert_ne!(0, ts.counter);
1117 }
1118
1119 #[test]
1120 fn context_shift() {
1121 let seconds = 1_496_854_535;
1122 let subsec_nanos = 812_946_000;
1123
1124 let context = ContextV7::new().with_adjust_by_millis(1);
1125
1126 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1127
1128 assert_eq!((1_496_854_535, 813_946_000), ts.to_unix());
1129 }
1130
1131 #[test]
1132 fn context_additional_precision() {
1133 let seconds = 1_496_854_535;
1134 let subsec_nanos = 812_946_000;
1135
1136 let context = ContextV7::new().with_additional_precision();
1137
1138 let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1139
1140 assert_eq!(3861, ts1.counter >> 30);
1142
1143 assert!(ts1.counter < (u64::MAX >> 22) as u128);
1144
1145 let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1147
1148 assert!(Uuid::new_v7(ts2) > Uuid::new_v7(ts1));
1149
1150 let subsec_nanos = subsec_nanos + 1;
1152
1153 let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1154
1155 assert!(Uuid::new_v7(ts3) > Uuid::new_v7(ts2));
1156 }
1157
1158 #[test]
1159 fn context_overflow() {
1160 let seconds = u64::MAX;
1161 let subsec_nanos = u32::MAX;
1162
1163 for context in [
1165 ContextV7::new(),
1166 ContextV7::new().with_additional_precision(),
1167 ContextV7::new().with_adjust_by_millis(u32::MAX),
1168 ] {
1169 Timestamp::from_unix(&context, seconds, subsec_nanos);
1170 }
1171 }
1172 }
1173 }
1174
1175 #[cfg(feature = "v7")]
1176 pub use v7_support::*;
1177
1178 #[derive(Debug, Clone, Copy, Default)]
1189 pub struct NoContext;
1190
1191 impl ClockSequence for NoContext {
1192 type Output = u16;
1193
1194 fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
1195 0
1196 }
1197
1198 fn usable_bits(&self) -> usize {
1199 0
1200 }
1201 }
1202}
1203
1204#[cfg(all(test, any(feature = "v1", feature = "v6")))]
1205mod tests {
1206 use super::*;
1207
1208 #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))]
1209 use wasm_bindgen_test::*;
1210
1211 #[test]
1212 #[cfg_attr(
1213 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1214 wasm_bindgen_test
1215 )]
1216 fn gregorian_unix_does_not_panic() {
1217 Timestamp::unix_to_gregorian_ticks(u64::MAX, 0);
1219 Timestamp::unix_to_gregorian_ticks(0, u32::MAX);
1220 Timestamp::unix_to_gregorian_ticks(u64::MAX, u32::MAX);
1221
1222 Timestamp::gregorian_to_unix(u64::MAX);
1223 }
1224
1225 #[test]
1226 #[cfg_attr(
1227 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1228 wasm_bindgen_test
1229 )]
1230 fn to_gregorian_truncates_to_usable_bits() {
1231 let ts = Timestamp::from_gregorian_time(123, u16::MAX);
1232
1233 assert_eq!((123, u16::MAX >> 2), ts.to_gregorian());
1234 }
1235
1236 #[test]
1237 #[cfg_attr(
1238 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1239 wasm_bindgen_test
1240 )]
1241 fn clock_sequence_usable_bits() {
1242 struct MyContext;
1243
1244 impl ClockSequence for MyContext {
1245 type Output = u16;
1246
1247 fn generate_sequence(&self, _: u64, _: u32) -> Self::Output {
1248 0
1249 }
1250 }
1251
1252 assert_eq!(16, MyContext.usable_bits());
1253 }
1254
1255 #[cfg(all(test, feature = "std", not(miri)))]
1256 mod std_support {
1257 use super::*;
1258
1259 use std::time::{Duration, SystemTime};
1260
1261 const KNOWN_SECONDS: u64 = 1_501_520_400;
1263 const KNOWN_NANOS: u32 = 1_000;
1264
1265 fn known_system_time() -> SystemTime {
1266 SystemTime::UNIX_EPOCH
1267 .checked_add(Duration::new(KNOWN_SECONDS, KNOWN_NANOS))
1268 .unwrap()
1269 }
1270
1271 fn known_timestamp() -> Timestamp {
1272 Timestamp::from_unix_time(KNOWN_SECONDS, KNOWN_NANOS, 0, 0)
1273 }
1274
1275 #[test]
1276 fn to_system_time() {
1277 let st: SystemTime = known_timestamp().into();
1278
1279 assert_eq!(known_system_time(), st);
1280 }
1281
1282 #[test]
1283 fn from_system_time() {
1284 let ts: Timestamp = known_system_time().try_into().unwrap();
1285
1286 assert_eq!(known_timestamp(), ts);
1287 }
1288
1289 #[test]
1290 fn from_system_time_before_epoch() {
1291 let before_epoch = match SystemTime::UNIX_EPOCH.checked_sub(Duration::from_nanos(1_000))
1292 {
1293 Some(st) => st,
1294 None => return,
1295 };
1296
1297 Timestamp::try_from(before_epoch)
1298 .expect_err("Timestamp should not be created from before epoch");
1299 }
1300 }
1301}