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(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(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
190pub(crate) const fn encode_gregorian_timestamp(
191 ticks: u64,
192 counter: u16,
193 node_id: &[u8; 6],
194) -> Uuid {
195 let time_low = (ticks & 0xFFFF_FFFF) as u32;
196 let time_mid = ((ticks >> 32) & 0xFFFF) as u16;
197 let time_high_and_version = (((ticks >> 48) & 0x0FFF) as u16) | (1 << 12);
198
199 let mut d4 = [0; 8];
200
201 d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
202 d4[1] = (counter & 0xFF) as u8;
203 d4[2] = node_id[0];
204 d4[3] = node_id[1];
205 d4[4] = node_id[2];
206 d4[5] = node_id[3];
207 d4[6] = node_id[4];
208 d4[7] = node_id[5];
209
210 Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
211}
212
213pub(crate) const fn decode_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
214 let bytes = uuid.as_bytes();
215
216 let ticks: u64 = ((bytes[6] & 0x0F) as u64) << 56
217 | (bytes[7] as u64) << 48
218 | (bytes[4] as u64) << 40
219 | (bytes[5] as u64) << 32
220 | (bytes[0] as u64) << 24
221 | (bytes[1] as u64) << 16
222 | (bytes[2] as u64) << 8
223 | (bytes[3] as u64);
224
225 let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
226
227 (ticks, counter)
228}
229
230pub(crate) const fn encode_sorted_gregorian_timestamp(
231 ticks: u64,
232 counter: u16,
233 node_id: &[u8; 6],
234) -> Uuid {
235 let time_high = ((ticks >> 28) & 0xFFFF_FFFF) as u32;
236 let time_mid = ((ticks >> 12) & 0xFFFF) as u16;
237 let time_low_and_version = ((ticks & 0x0FFF) as u16) | (0x6 << 12);
238
239 let mut d4 = [0; 8];
240
241 d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
242 d4[1] = (counter & 0xFF) as u8;
243 d4[2] = node_id[0];
244 d4[3] = node_id[1];
245 d4[4] = node_id[2];
246 d4[5] = node_id[3];
247 d4[6] = node_id[4];
248 d4[7] = node_id[5];
249
250 Uuid::from_fields(time_high, time_mid, time_low_and_version, &d4)
251}
252
253pub(crate) const fn decode_sorted_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
254 let bytes = uuid.as_bytes();
255
256 let ticks: u64 = ((bytes[0]) as u64) << 52
257 | (bytes[1] as u64) << 44
258 | (bytes[2] as u64) << 36
259 | (bytes[3] as u64) << 28
260 | (bytes[4] as u64) << 20
261 | (bytes[5] as u64) << 12
262 | ((bytes[6] & 0xF) as u64) << 8
263 | (bytes[7] as u64);
264
265 let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
266
267 (ticks, counter)
268}
269
270pub(crate) const fn encode_unix_timestamp_millis(
271 millis: u64,
272 counter_random_bytes: &[u8; 10],
273) -> Uuid {
274 let millis_high = ((millis >> 16) & 0xFFFF_FFFF) as u32;
275 let millis_low = (millis & 0xFFFF) as u16;
276
277 let counter_random_version = (counter_random_bytes[1] as u16
278 | ((counter_random_bytes[0] as u16) << 8) & 0x0FFF)
279 | (0x7 << 12);
280
281 let mut d4 = [0; 8];
282
283 d4[0] = (counter_random_bytes[2] & 0x3F) | 0x80;
284 d4[1] = counter_random_bytes[3];
285 d4[2] = counter_random_bytes[4];
286 d4[3] = counter_random_bytes[5];
287 d4[4] = counter_random_bytes[6];
288 d4[5] = counter_random_bytes[7];
289 d4[6] = counter_random_bytes[8];
290 d4[7] = counter_random_bytes[9];
291
292 Uuid::from_fields(millis_high, millis_low, counter_random_version, &d4)
293}
294
295pub(crate) const fn decode_unix_timestamp_millis(uuid: &Uuid) -> u64 {
296 let bytes = uuid.as_bytes();
297
298 let millis: u64 = (bytes[0] as u64) << 40
299 | (bytes[1] as u64) << 32
300 | (bytes[2] as u64) << 24
301 | (bytes[3] as u64) << 16
302 | (bytes[4] as u64) << 8
303 | (bytes[5] as u64);
304
305 millis
306}
307
308#[cfg(all(
309 feature = "std",
310 feature = "js",
311 all(
312 target_arch = "wasm32",
313 target_vendor = "unknown",
314 target_os = "unknown"
315 )
316))]
317fn now() -> (u64, u32) {
318 use wasm_bindgen::prelude::*;
319
320 #[wasm_bindgen]
321 extern "C" {
322 #[wasm_bindgen(js_namespace = Date, catch)]
324 fn now() -> Result<f64, JsValue>;
325 }
326
327 let now = now().unwrap_throw();
328
329 let secs = (now / 1_000.0) as u64;
330 let nanos = ((now % 1_000.0) * 1_000_000.0) as u32;
331
332 (secs, nanos)
333}
334
335#[cfg(all(
336 feature = "std",
337 not(miri),
338 any(
339 not(feature = "js"),
340 not(all(
341 target_arch = "wasm32",
342 target_vendor = "unknown",
343 target_os = "unknown"
344 ))
345 )
346))]
347fn now() -> (u64, u32) {
348 let dur = std::time::SystemTime::UNIX_EPOCH.elapsed().expect(
349 "Getting elapsed time since UNIX_EPOCH. If this fails, we've somehow violated causality",
350 );
351
352 (dur.as_secs(), dur.subsec_nanos())
353}
354
355#[cfg(all(feature = "std", miri))]
356fn now() -> (u64, u32) {
357 use std::{sync::Mutex, time::Duration};
358
359 static TS: Mutex<u64> = Mutex::new(0);
360
361 let ts = Duration::from_nanos({
362 let mut ts = TS.lock().unwrap();
363 *ts += 1;
364 *ts
365 });
366
367 (ts.as_secs(), ts.subsec_nanos())
368}
369
370pub trait ClockSequence {
379 type Output;
381
382 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output;
388
389 fn generate_timestamp_sequence(
395 &self,
396 seconds: u64,
397 subsec_nanos: u32,
398 ) -> (Self::Output, u64, u32) {
399 (
400 self.generate_sequence(seconds, subsec_nanos),
401 seconds,
402 subsec_nanos,
403 )
404 }
405
406 fn usable_bits(&self) -> usize
414 where
415 Self::Output: Sized,
416 {
417 cmp::min(128, core::mem::size_of::<Self::Output>())
418 }
419}
420
421impl<'a, T: ClockSequence + ?Sized> ClockSequence for &'a T {
422 type Output = T::Output;
423
424 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
425 (**self).generate_sequence(seconds, subsec_nanos)
426 }
427
428 fn generate_timestamp_sequence(
429 &self,
430 seconds: u64,
431 subsec_nanos: u32,
432 ) -> (Self::Output, u64, u32) {
433 (**self).generate_timestamp_sequence(seconds, subsec_nanos)
434 }
435
436 fn usable_bits(&self) -> usize
437 where
438 Self::Output: Sized,
439 {
440 (**self).usable_bits()
441 }
442}
443
444pub mod context {
446 use super::ClockSequence;
447
448 #[cfg(any(feature = "v1", feature = "v6"))]
449 mod v1_support {
450 use super::*;
451
452 use atomic::{Atomic, Ordering};
453
454 #[cfg(all(feature = "std", feature = "rng"))]
455 static CONTEXT: Context = Context {
456 count: Atomic::new(0),
457 };
458
459 #[cfg(all(feature = "std", feature = "rng"))]
460 static CONTEXT_INITIALIZED: Atomic<bool> = Atomic::new(false);
461
462 #[cfg(all(feature = "std", feature = "rng"))]
463 pub(crate) fn shared_context() -> &'static Context {
464 if CONTEXT_INITIALIZED
467 .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
468 .is_ok()
469 {
470 CONTEXT.count.store(crate::rng::u16(), Ordering::Release);
471 }
472
473 &CONTEXT
474 }
475
476 #[derive(Debug)]
491 pub struct Context {
492 count: Atomic<u16>,
493 }
494
495 impl Context {
496 pub const fn new(count: u16) -> Self {
502 Self {
503 count: Atomic::<u16>::new(count),
504 }
505 }
506
507 #[cfg(feature = "rng")]
509 pub fn new_random() -> Self {
510 Self {
511 count: Atomic::<u16>::new(crate::rng::u16()),
512 }
513 }
514 }
515
516 impl ClockSequence for Context {
517 type Output = u16;
518
519 fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
520 self.count.fetch_add(1, Ordering::AcqRel) & (u16::MAX >> 2)
526 }
527
528 fn usable_bits(&self) -> usize {
529 14
530 }
531 }
532
533 #[cfg(test)]
534 mod tests {
535 use crate::Timestamp;
536
537 use super::*;
538
539 #[test]
540 fn context() {
541 let seconds = 1_496_854_535;
542 let subsec_nanos = 812_946_000;
543
544 let context = Context::new(u16::MAX >> 2);
545
546 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
547 assert_eq!(16383, ts.counter);
548 assert_eq!(14, ts.usable_counter_bits);
549
550 let seconds = 1_496_854_536;
551
552 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
553 assert_eq!(0, ts.counter);
554
555 let seconds = 1_496_854_535;
556
557 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
558 assert_eq!(1, ts.counter);
559 }
560
561 #[test]
562 fn context_overflow() {
563 let seconds = u64::MAX;
564 let subsec_nanos = u32::MAX;
565
566 let context = Context::new(u16::MAX);
567
568 Timestamp::from_unix(&context, seconds, subsec_nanos);
570 }
571 }
572 }
573
574 #[cfg(any(feature = "v1", feature = "v6"))]
575 pub use v1_support::*;
576
577 #[cfg(feature = "std")]
578 mod std_support {
579 use super::*;
580
581 use core::panic::{AssertUnwindSafe, RefUnwindSafe};
582 use std::{sync::Mutex, thread::LocalKey};
583
584 pub struct ThreadLocalContext<C: 'static>(&'static LocalKey<C>);
586
587 impl<C> std::fmt::Debug for ThreadLocalContext<C> {
588 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
589 f.debug_struct("ThreadLocalContext").finish_non_exhaustive()
590 }
591 }
592
593 impl<C: 'static> ThreadLocalContext<C> {
594 pub const fn new(local_key: &'static LocalKey<C>) -> Self {
596 ThreadLocalContext(local_key)
597 }
598 }
599
600 impl<C: ClockSequence + 'static> ClockSequence for ThreadLocalContext<C> {
601 type Output = C::Output;
602
603 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
604 self.0
605 .with(|ctxt| ctxt.generate_sequence(seconds, subsec_nanos))
606 }
607
608 fn generate_timestamp_sequence(
609 &self,
610 seconds: u64,
611 subsec_nanos: u32,
612 ) -> (Self::Output, u64, u32) {
613 self.0
614 .with(|ctxt| ctxt.generate_timestamp_sequence(seconds, subsec_nanos))
615 }
616
617 fn usable_bits(&self) -> usize {
618 self.0.with(|ctxt| ctxt.usable_bits())
619 }
620 }
621
622 impl<C: ClockSequence> ClockSequence for AssertUnwindSafe<C> {
623 type Output = C::Output;
624
625 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
626 self.0.generate_sequence(seconds, subsec_nanos)
627 }
628
629 fn generate_timestamp_sequence(
630 &self,
631 seconds: u64,
632 subsec_nanos: u32,
633 ) -> (Self::Output, u64, u32) {
634 self.0.generate_timestamp_sequence(seconds, subsec_nanos)
635 }
636
637 fn usable_bits(&self) -> usize
638 where
639 Self::Output: Sized,
640 {
641 self.0.usable_bits()
642 }
643 }
644
645 impl<C: ClockSequence + RefUnwindSafe> ClockSequence for Mutex<C> {
646 type Output = C::Output;
647
648 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
649 self.lock()
650 .unwrap_or_else(|err| err.into_inner())
651 .generate_sequence(seconds, subsec_nanos)
652 }
653
654 fn generate_timestamp_sequence(
655 &self,
656 seconds: u64,
657 subsec_nanos: u32,
658 ) -> (Self::Output, u64, u32) {
659 self.lock()
660 .unwrap_or_else(|err| err.into_inner())
661 .generate_timestamp_sequence(seconds, subsec_nanos)
662 }
663
664 fn usable_bits(&self) -> usize
665 where
666 Self::Output: Sized,
667 {
668 self.lock()
669 .unwrap_or_else(|err| err.into_inner())
670 .usable_bits()
671 }
672 }
673 }
674
675 #[cfg(feature = "std")]
676 pub use std_support::*;
677
678 #[cfg(feature = "v7")]
679 mod v7_support {
680 use super::*;
681
682 use core::{cell::Cell, cmp, panic::RefUnwindSafe};
683
684 #[cfg(feature = "std")]
685 static CONTEXT_V7: SharedContextV7 =
686 SharedContextV7(std::sync::Mutex::new(ContextV7::new()));
687
688 #[cfg(feature = "std")]
689 pub(crate) fn shared_context_v7() -> &'static SharedContextV7 {
690 &CONTEXT_V7
691 }
692
693 const USABLE_BITS: usize = 42;
694
695 const RESEED_MASK: u64 = u64::MAX >> 23;
700 const MAX_COUNTER: u64 = u64::MAX >> 22;
701
702 #[derive(Debug)]
725 pub struct ContextV7 {
726 timestamp: Cell<ReseedingTimestamp>,
727 counter: Cell<Counter>,
728 adjust: Adjust,
729 precision: Precision,
730 }
731
732 impl RefUnwindSafe for ContextV7 {}
733
734 impl ContextV7 {
735 pub const fn new() -> Self {
738 ContextV7 {
739 timestamp: Cell::new(ReseedingTimestamp {
740 last_seed: 0,
741 seconds: 0,
742 subsec_nanos: 0,
743 }),
744 counter: Cell::new(Counter { value: 0 }),
745 adjust: Adjust { by_ns: 0 },
746 precision: Precision {
747 bits: 0,
748 mask: 0,
749 factor: 0,
750 shift: 0,
751 },
752 }
753 }
754
755 pub fn with_adjust_by_millis(mut self, millis: u32) -> Self {
757 self.adjust = Adjust::by_millis(millis);
758 self
759 }
760
761 pub fn with_additional_precision(mut self) -> Self {
768 self.precision = Precision::new(12);
769 self
770 }
771 }
772
773 impl ClockSequence for ContextV7 {
774 type Output = u64;
775
776 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
777 self.generate_timestamp_sequence(seconds, subsec_nanos).0
778 }
779
780 fn generate_timestamp_sequence(
781 &self,
782 seconds: u64,
783 subsec_nanos: u32,
784 ) -> (Self::Output, u64, u32) {
785 let (seconds, subsec_nanos) = self.adjust.apply(seconds, subsec_nanos);
786
787 let mut counter;
788 let (mut timestamp, should_reseed) =
789 self.timestamp.get().advance(seconds, subsec_nanos);
790
791 if should_reseed {
792 counter = Counter::reseed(&self.precision, ×tamp);
794 } else {
795 counter = self.counter.get().increment(&self.precision, ×tamp);
802
803 if counter.has_overflowed() {
807 timestamp = timestamp.increment();
809 counter = Counter::reseed(&self.precision, ×tamp);
810 }
811 };
812
813 self.timestamp.set(timestamp);
814 self.counter.set(counter);
815
816 (counter.value, timestamp.seconds, timestamp.subsec_nanos)
817 }
818
819 fn usable_bits(&self) -> usize {
820 USABLE_BITS
821 }
822 }
823
824 #[derive(Debug)]
825 struct Adjust {
826 by_ns: u128,
827 }
828
829 impl Adjust {
830 #[inline]
831 fn by_millis(millis: u32) -> Self {
832 Adjust {
833 by_ns: (millis as u128).saturating_mul(1_000_000),
834 }
835 }
836
837 #[inline]
838 fn apply(&self, seconds: u64, subsec_nanos: u32) -> (u64, u32) {
839 if self.by_ns == 0 {
840 return (seconds, subsec_nanos);
842 }
843
844 let ts = (seconds as u128)
845 .saturating_mul(1_000_000_000)
846 .saturating_add(subsec_nanos as u128)
847 .saturating_add(self.by_ns as u128);
848
849 ((ts / 1_000_000_000) as u64, (ts % 1_000_000_000) as u32)
850 }
851 }
852
853 #[derive(Debug, Default, Clone, Copy)]
854 struct ReseedingTimestamp {
855 last_seed: u64,
856 seconds: u64,
857 subsec_nanos: u32,
858 }
859
860 impl ReseedingTimestamp {
861 #[inline]
862 fn advance(&self, seconds: u64, subsec_nanos: u32) -> (Self, bool) {
863 let incoming = ReseedingTimestamp::from_ts(seconds, subsec_nanos);
864
865 if incoming.last_seed > self.last_seed {
866 (incoming, true)
868 } else {
869 let mut value = *self;
872 value.subsec_nanos = cmp::max(self.subsec_nanos, subsec_nanos);
873
874 (value, false)
875 }
876 }
877
878 #[inline]
879 fn from_ts(seconds: u64, subsec_nanos: u32) -> Self {
880 let last_seed = seconds
882 .saturating_mul(1_000)
883 .saturating_add((subsec_nanos / 1_000_000) as u64);
884
885 ReseedingTimestamp {
886 last_seed,
887 seconds,
888 subsec_nanos,
889 }
890 }
891
892 #[inline]
893 fn increment(&self) -> Self {
894 let (seconds, subsec_nanos) =
895 Adjust::by_millis(1).apply(self.seconds, self.subsec_nanos);
896
897 ReseedingTimestamp::from_ts(seconds, subsec_nanos)
898 }
899
900 #[inline]
901 fn submilli_nanos(&self) -> u32 {
902 self.subsec_nanos % 1_000_000
903 }
904 }
905
906 #[derive(Debug)]
907 struct Precision {
908 bits: usize,
909 factor: u64,
910 mask: u64,
911 shift: u64,
912 }
913
914 impl Precision {
915 fn new(bits: usize) -> Self {
916 let mask = u64::MAX >> (64 - USABLE_BITS + bits);
919 let shift = (USABLE_BITS - bits) as u64;
920
921 let factor = (999_999 / u64::pow(2, bits as u32)) + 1;
924
925 Precision {
926 bits,
927 factor,
928 mask,
929 shift,
930 }
931 }
932
933 #[inline]
934 fn apply(&self, value: u64, timestamp: &ReseedingTimestamp) -> u64 {
935 if self.bits == 0 {
936 return value;
938 }
939
940 let additional = timestamp.submilli_nanos() as u64 / self.factor;
941
942 (value & self.mask) | (additional << self.shift)
943 }
944 }
945
946 #[derive(Debug, Clone, Copy)]
947 struct Counter {
948 value: u64,
949 }
950
951 impl Counter {
952 #[inline]
953 fn reseed(precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
954 Counter {
955 value: precision.apply(crate::rng::u64() & RESEED_MASK, timestamp),
956 }
957 }
958
959 #[inline]
960 fn increment(&self, precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
961 let mut counter = Counter {
962 value: precision.apply(self.value, timestamp),
963 };
964
965 counter.value += 1;
972
973 counter
974 }
975
976 #[inline]
977 fn has_overflowed(&self) -> bool {
978 self.value > MAX_COUNTER
979 }
980 }
981
982 #[cfg(feature = "std")]
983 pub(crate) struct SharedContextV7(std::sync::Mutex<ContextV7>);
984
985 #[cfg(feature = "std")]
986 impl ClockSequence for SharedContextV7 {
987 type Output = u64;
988
989 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
990 self.0.generate_sequence(seconds, subsec_nanos)
991 }
992
993 fn generate_timestamp_sequence(
994 &self,
995 seconds: u64,
996 subsec_nanos: u32,
997 ) -> (Self::Output, u64, u32) {
998 self.0.generate_timestamp_sequence(seconds, subsec_nanos)
999 }
1000
1001 fn usable_bits(&self) -> usize
1002 where
1003 Self::Output: Sized,
1004 {
1005 USABLE_BITS
1006 }
1007 }
1008
1009 #[cfg(test)]
1010 mod tests {
1011 use core::time::Duration;
1012
1013 use super::*;
1014
1015 use crate::{Timestamp, Uuid};
1016
1017 #[test]
1018 fn context() {
1019 let seconds = 1_496_854_535;
1020 let subsec_nanos = 812_946_000;
1021
1022 let context = ContextV7::new();
1023
1024 let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1025 assert_eq!(42, ts1.usable_counter_bits);
1026
1027 let seconds = 1_496_854_534;
1029
1030 let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1031
1032 assert_eq!(ts1.seconds, ts2.seconds);
1035 assert_eq!(ts1.subsec_nanos, ts2.subsec_nanos);
1036 assert_eq!(ts1.counter + 1, ts2.counter);
1037
1038 let seconds = 1_496_854_536;
1040
1041 let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1042
1043 assert_ne!(ts2.counter + 1, ts3.counter);
1045 assert_ne!(0, ts3.counter);
1046 }
1047
1048 #[test]
1049 fn context_wrap() {
1050 let seconds = 1_496_854_535u64;
1051 let subsec_nanos = 812_946_000u32;
1052
1053 let context = ContextV7 {
1055 timestamp: Cell::new(ReseedingTimestamp::from_ts(seconds, subsec_nanos)),
1056 adjust: Adjust::by_millis(0),
1057 precision: Precision {
1058 bits: 0,
1059 mask: 0,
1060 factor: 0,
1061 shift: 0,
1062 },
1063 counter: Cell::new(Counter {
1064 value: u64::MAX >> 22,
1065 }),
1066 };
1067
1068 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1069
1070 let expected_ts = Duration::new(seconds, subsec_nanos) + Duration::from_millis(1);
1072 assert_eq!(expected_ts.as_secs(), ts.seconds);
1073 assert_eq!(expected_ts.subsec_nanos(), ts.subsec_nanos);
1074
1075 assert!(ts.counter < (u64::MAX >> 22) as u128);
1077 assert_ne!(0, ts.counter);
1078 }
1079
1080 #[test]
1081 fn context_shift() {
1082 let seconds = 1_496_854_535;
1083 let subsec_nanos = 812_946_000;
1084
1085 let context = ContextV7::new().with_adjust_by_millis(1);
1086
1087 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1088
1089 assert_eq!((1_496_854_535, 813_946_000), ts.to_unix());
1090 }
1091
1092 #[test]
1093 fn context_additional_precision() {
1094 let seconds = 1_496_854_535;
1095 let subsec_nanos = 812_946_000;
1096
1097 let context = ContextV7::new().with_additional_precision();
1098
1099 let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1100
1101 assert_eq!(3861, ts1.counter >> 30);
1103
1104 assert!(ts1.counter < (u64::MAX >> 22) as u128);
1105
1106 let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1108
1109 assert!(Uuid::new_v7(ts2) > Uuid::new_v7(ts1));
1110
1111 let subsec_nanos = subsec_nanos + 1;
1113
1114 let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1115
1116 assert!(Uuid::new_v7(ts3) > Uuid::new_v7(ts2));
1117 }
1118
1119 #[test]
1120 fn context_overflow() {
1121 let seconds = u64::MAX;
1122 let subsec_nanos = u32::MAX;
1123
1124 for context in [
1126 ContextV7::new(),
1127 ContextV7::new().with_additional_precision(),
1128 ContextV7::new().with_adjust_by_millis(u32::MAX),
1129 ] {
1130 Timestamp::from_unix(&context, seconds, subsec_nanos);
1131 }
1132 }
1133 }
1134 }
1135
1136 #[cfg(feature = "v7")]
1137 pub use v7_support::*;
1138
1139 #[derive(Debug, Clone, Copy, Default)]
1150 pub struct NoContext;
1151
1152 impl ClockSequence for NoContext {
1153 type Output = u16;
1154
1155 fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
1156 0
1157 }
1158
1159 fn usable_bits(&self) -> usize {
1160 0
1161 }
1162 }
1163}
1164
1165#[cfg(all(test, any(feature = "v1", feature = "v6")))]
1166mod tests {
1167 use super::*;
1168
1169 #[cfg(all(
1170 target_arch = "wasm32",
1171 target_vendor = "unknown",
1172 target_os = "unknown"
1173 ))]
1174 use wasm_bindgen_test::*;
1175
1176 #[test]
1177 #[cfg_attr(
1178 all(
1179 target_arch = "wasm32",
1180 target_vendor = "unknown",
1181 target_os = "unknown"
1182 ),
1183 wasm_bindgen_test
1184 )]
1185 fn gregorian_unix_does_not_panic() {
1186 Timestamp::unix_to_gregorian_ticks(u64::MAX, 0);
1188 Timestamp::unix_to_gregorian_ticks(0, u32::MAX);
1189 Timestamp::unix_to_gregorian_ticks(u64::MAX, u32::MAX);
1190
1191 Timestamp::gregorian_to_unix(u64::MAX);
1192 }
1193
1194 #[test]
1195 #[cfg_attr(
1196 all(
1197 target_arch = "wasm32",
1198 target_vendor = "unknown",
1199 target_os = "unknown"
1200 ),
1201 wasm_bindgen_test
1202 )]
1203 fn to_gregorian_truncates_to_usable_bits() {
1204 let ts = Timestamp::from_gregorian(123, u16::MAX);
1205
1206 assert_eq!((123, u16::MAX >> 2), ts.to_gregorian());
1207 }
1208}