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(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))
312))]
313fn now() -> (u64, u32) {
314 use wasm_bindgen::prelude::*;
315
316 #[wasm_bindgen]
317 extern "C" {
318 #[wasm_bindgen(js_namespace = Date, catch)]
320 fn now() -> Result<f64, JsValue>;
321 }
322
323 let now = now().unwrap_throw();
324
325 let secs = (now / 1_000.0) as u64;
326 let nanos = ((now % 1_000.0) * 1_000_000.0) as u32;
327
328 (secs, nanos)
329}
330
331#[cfg(all(
332 feature = "std",
333 not(miri),
334 any(
335 not(feature = "js"),
336 not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))
337 )
338))]
339fn now() -> (u64, u32) {
340 let dur = std::time::SystemTime::UNIX_EPOCH.elapsed().expect(
341 "Getting elapsed time since UNIX_EPOCH. If this fails, we've somehow violated causality",
342 );
343
344 (dur.as_secs(), dur.subsec_nanos())
345}
346
347#[cfg(all(feature = "std", miri))]
348fn now() -> (u64, u32) {
349 use std::{sync::Mutex, time::Duration};
350
351 static TS: Mutex<u64> = Mutex::new(0);
352
353 let ts = Duration::from_nanos({
354 let mut ts = TS.lock().unwrap();
355 *ts += 1;
356 *ts
357 });
358
359 (ts.as_secs(), ts.subsec_nanos())
360}
361
362pub trait ClockSequence {
371 type Output;
373
374 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output;
380
381 fn generate_timestamp_sequence(
387 &self,
388 seconds: u64,
389 subsec_nanos: u32,
390 ) -> (Self::Output, u64, u32) {
391 (
392 self.generate_sequence(seconds, subsec_nanos),
393 seconds,
394 subsec_nanos,
395 )
396 }
397
398 fn usable_bits(&self) -> usize
406 where
407 Self::Output: Sized,
408 {
409 cmp::min(128, core::mem::size_of::<Self::Output>())
410 }
411}
412
413impl<'a, T: ClockSequence + ?Sized> ClockSequence for &'a T {
414 type Output = T::Output;
415
416 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
417 (**self).generate_sequence(seconds, subsec_nanos)
418 }
419
420 fn generate_timestamp_sequence(
421 &self,
422 seconds: u64,
423 subsec_nanos: u32,
424 ) -> (Self::Output, u64, u32) {
425 (**self).generate_timestamp_sequence(seconds, subsec_nanos)
426 }
427
428 fn usable_bits(&self) -> usize
429 where
430 Self::Output: Sized,
431 {
432 (**self).usable_bits()
433 }
434}
435
436pub mod context {
438 use super::ClockSequence;
439
440 #[cfg(any(feature = "v1", feature = "v6"))]
441 mod v1_support {
442 use super::*;
443
444 use atomic::{Atomic, Ordering};
445
446 #[cfg(all(feature = "std", feature = "rng"))]
447 static CONTEXT: Context = Context {
448 count: Atomic::new(0),
449 };
450
451 #[cfg(all(feature = "std", feature = "rng"))]
452 static CONTEXT_INITIALIZED: Atomic<bool> = Atomic::new(false);
453
454 #[cfg(all(feature = "std", feature = "rng"))]
455 pub(crate) fn shared_context() -> &'static Context {
456 if CONTEXT_INITIALIZED
459 .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
460 .is_ok()
461 {
462 CONTEXT.count.store(crate::rng::u16(), Ordering::Release);
463 }
464
465 &CONTEXT
466 }
467
468 #[derive(Debug)]
483 pub struct Context {
484 count: Atomic<u16>,
485 }
486
487 impl Context {
488 pub const fn new(count: u16) -> Self {
494 Self {
495 count: Atomic::<u16>::new(count),
496 }
497 }
498
499 #[cfg(feature = "rng")]
501 pub fn new_random() -> Self {
502 Self {
503 count: Atomic::<u16>::new(crate::rng::u16()),
504 }
505 }
506 }
507
508 impl ClockSequence for Context {
509 type Output = u16;
510
511 fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
512 self.count.fetch_add(1, Ordering::AcqRel) & (u16::MAX >> 2)
518 }
519
520 fn usable_bits(&self) -> usize {
521 14
522 }
523 }
524
525 #[cfg(test)]
526 mod tests {
527 use crate::Timestamp;
528
529 use super::*;
530
531 #[test]
532 fn context() {
533 let seconds = 1_496_854_535;
534 let subsec_nanos = 812_946_000;
535
536 let context = Context::new(u16::MAX >> 2);
537
538 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
539 assert_eq!(16383, ts.counter);
540 assert_eq!(14, ts.usable_counter_bits);
541
542 let seconds = 1_496_854_536;
543
544 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
545 assert_eq!(0, ts.counter);
546
547 let seconds = 1_496_854_535;
548
549 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
550 assert_eq!(1, ts.counter);
551 }
552
553 #[test]
554 fn context_overflow() {
555 let seconds = u64::MAX;
556 let subsec_nanos = u32::MAX;
557
558 let context = Context::new(u16::MAX);
559
560 Timestamp::from_unix(&context, seconds, subsec_nanos);
562 }
563 }
564 }
565
566 #[cfg(any(feature = "v1", feature = "v6"))]
567 pub use v1_support::*;
568
569 #[cfg(feature = "std")]
570 mod std_support {
571 use super::*;
572
573 use core::panic::{AssertUnwindSafe, RefUnwindSafe};
574 use std::{sync::Mutex, thread::LocalKey};
575
576 pub struct ThreadLocalContext<C: 'static>(&'static LocalKey<C>);
578
579 impl<C> std::fmt::Debug for ThreadLocalContext<C> {
580 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
581 f.debug_struct("ThreadLocalContext").finish_non_exhaustive()
582 }
583 }
584
585 impl<C: 'static> ThreadLocalContext<C> {
586 pub const fn new(local_key: &'static LocalKey<C>) -> Self {
588 ThreadLocalContext(local_key)
589 }
590 }
591
592 impl<C: ClockSequence + 'static> ClockSequence for ThreadLocalContext<C> {
593 type Output = C::Output;
594
595 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
596 self.0
597 .with(|ctxt| ctxt.generate_sequence(seconds, subsec_nanos))
598 }
599
600 fn generate_timestamp_sequence(
601 &self,
602 seconds: u64,
603 subsec_nanos: u32,
604 ) -> (Self::Output, u64, u32) {
605 self.0
606 .with(|ctxt| ctxt.generate_timestamp_sequence(seconds, subsec_nanos))
607 }
608
609 fn usable_bits(&self) -> usize {
610 self.0.with(|ctxt| ctxt.usable_bits())
611 }
612 }
613
614 impl<C: ClockSequence> ClockSequence for AssertUnwindSafe<C> {
615 type Output = C::Output;
616
617 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
618 self.0.generate_sequence(seconds, subsec_nanos)
619 }
620
621 fn generate_timestamp_sequence(
622 &self,
623 seconds: u64,
624 subsec_nanos: u32,
625 ) -> (Self::Output, u64, u32) {
626 self.0.generate_timestamp_sequence(seconds, subsec_nanos)
627 }
628
629 fn usable_bits(&self) -> usize
630 where
631 Self::Output: Sized,
632 {
633 self.0.usable_bits()
634 }
635 }
636
637 impl<C: ClockSequence + RefUnwindSafe> ClockSequence for Mutex<C> {
638 type Output = C::Output;
639
640 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
641 self.lock()
642 .unwrap_or_else(|err| err.into_inner())
643 .generate_sequence(seconds, subsec_nanos)
644 }
645
646 fn generate_timestamp_sequence(
647 &self,
648 seconds: u64,
649 subsec_nanos: u32,
650 ) -> (Self::Output, u64, u32) {
651 self.lock()
652 .unwrap_or_else(|err| err.into_inner())
653 .generate_timestamp_sequence(seconds, subsec_nanos)
654 }
655
656 fn usable_bits(&self) -> usize
657 where
658 Self::Output: Sized,
659 {
660 self.lock()
661 .unwrap_or_else(|err| err.into_inner())
662 .usable_bits()
663 }
664 }
665 }
666
667 #[cfg(feature = "std")]
668 pub use std_support::*;
669
670 #[cfg(feature = "v7")]
671 mod v7_support {
672 use super::*;
673
674 use core::{cell::Cell, cmp, panic::RefUnwindSafe};
675
676 #[cfg(feature = "std")]
677 static CONTEXT_V7: SharedContextV7 =
678 SharedContextV7(std::sync::Mutex::new(ContextV7::new()));
679
680 #[cfg(feature = "std")]
681 pub(crate) fn shared_context_v7() -> &'static SharedContextV7 {
682 &CONTEXT_V7
683 }
684
685 const USABLE_BITS: usize = 42;
686
687 const RESEED_MASK: u64 = u64::MAX >> 23;
692 const MAX_COUNTER: u64 = u64::MAX >> 22;
693
694 #[derive(Debug)]
717 pub struct ContextV7 {
718 timestamp: Cell<ReseedingTimestamp>,
719 counter: Cell<Counter>,
720 adjust: Adjust,
721 precision: Precision,
722 }
723
724 impl RefUnwindSafe for ContextV7 {}
725
726 impl ContextV7 {
727 pub const fn new() -> Self {
730 ContextV7 {
731 timestamp: Cell::new(ReseedingTimestamp {
732 last_seed: 0,
733 seconds: 0,
734 subsec_nanos: 0,
735 }),
736 counter: Cell::new(Counter { value: 0 }),
737 adjust: Adjust { by_ns: 0 },
738 precision: Precision {
739 bits: 0,
740 mask: 0,
741 factor: 0,
742 shift: 0,
743 },
744 }
745 }
746
747 pub fn with_adjust_by_millis(mut self, millis: u32) -> Self {
749 self.adjust = Adjust::by_millis(millis);
750 self
751 }
752
753 pub fn with_additional_precision(mut self) -> Self {
760 self.precision = Precision::new(12);
761 self
762 }
763 }
764
765 impl ClockSequence for ContextV7 {
766 type Output = u64;
767
768 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
769 self.generate_timestamp_sequence(seconds, subsec_nanos).0
770 }
771
772 fn generate_timestamp_sequence(
773 &self,
774 seconds: u64,
775 subsec_nanos: u32,
776 ) -> (Self::Output, u64, u32) {
777 let (seconds, subsec_nanos) = self.adjust.apply(seconds, subsec_nanos);
778
779 let mut counter;
780 let (mut timestamp, should_reseed) =
781 self.timestamp.get().advance(seconds, subsec_nanos);
782
783 if should_reseed {
784 counter = Counter::reseed(&self.precision, ×tamp);
786 } else {
787 counter = self.counter.get().increment(&self.precision, ×tamp);
794
795 if counter.has_overflowed() {
799 timestamp = timestamp.increment();
801 counter = Counter::reseed(&self.precision, ×tamp);
802 }
803 };
804
805 self.timestamp.set(timestamp);
806 self.counter.set(counter);
807
808 (counter.value, timestamp.seconds, timestamp.subsec_nanos)
809 }
810
811 fn usable_bits(&self) -> usize {
812 USABLE_BITS
813 }
814 }
815
816 #[derive(Debug)]
817 struct Adjust {
818 by_ns: u128,
819 }
820
821 impl Adjust {
822 #[inline]
823 fn by_millis(millis: u32) -> Self {
824 Adjust {
825 by_ns: (millis as u128).saturating_mul(1_000_000),
826 }
827 }
828
829 #[inline]
830 fn apply(&self, seconds: u64, subsec_nanos: u32) -> (u64, u32) {
831 if self.by_ns == 0 {
832 return (seconds, subsec_nanos);
834 }
835
836 let ts = (seconds as u128)
837 .saturating_mul(1_000_000_000)
838 .saturating_add(subsec_nanos as u128)
839 .saturating_add(self.by_ns as u128);
840
841 ((ts / 1_000_000_000) as u64, (ts % 1_000_000_000) as u32)
842 }
843 }
844
845 #[derive(Debug, Default, Clone, Copy)]
846 struct ReseedingTimestamp {
847 last_seed: u64,
848 seconds: u64,
849 subsec_nanos: u32,
850 }
851
852 impl ReseedingTimestamp {
853 #[inline]
854 fn advance(&self, seconds: u64, subsec_nanos: u32) -> (Self, bool) {
855 let incoming = ReseedingTimestamp::from_ts(seconds, subsec_nanos);
856
857 if incoming.last_seed > self.last_seed {
858 (incoming, true)
860 } else {
861 let mut value = *self;
864 value.subsec_nanos = cmp::max(self.subsec_nanos, subsec_nanos);
865
866 (value, false)
867 }
868 }
869
870 #[inline]
871 fn from_ts(seconds: u64, subsec_nanos: u32) -> Self {
872 let last_seed = seconds
874 .saturating_mul(1_000)
875 .saturating_add((subsec_nanos / 1_000_000) as u64);
876
877 ReseedingTimestamp {
878 last_seed,
879 seconds,
880 subsec_nanos,
881 }
882 }
883
884 #[inline]
885 fn increment(&self) -> Self {
886 let (seconds, subsec_nanos) =
887 Adjust::by_millis(1).apply(self.seconds, self.subsec_nanos);
888
889 ReseedingTimestamp::from_ts(seconds, subsec_nanos)
890 }
891
892 #[inline]
893 fn submilli_nanos(&self) -> u32 {
894 self.subsec_nanos % 1_000_000
895 }
896 }
897
898 #[derive(Debug)]
899 struct Precision {
900 bits: usize,
901 factor: u64,
902 mask: u64,
903 shift: u64,
904 }
905
906 impl Precision {
907 fn new(bits: usize) -> Self {
908 let mask = u64::MAX >> (64 - USABLE_BITS + bits);
911 let shift = (USABLE_BITS - bits) as u64;
912
913 let factor = (999_999 / u64::pow(2, bits as u32)) + 1;
916
917 Precision {
918 bits,
919 factor,
920 mask,
921 shift,
922 }
923 }
924
925 #[inline]
926 fn apply(&self, value: u64, timestamp: &ReseedingTimestamp) -> u64 {
927 if self.bits == 0 {
928 return value;
930 }
931
932 let additional = timestamp.submilli_nanos() as u64 / self.factor;
933
934 (value & self.mask) | (additional << self.shift)
935 }
936 }
937
938 #[derive(Debug, Clone, Copy)]
939 struct Counter {
940 value: u64,
941 }
942
943 impl Counter {
944 #[inline]
945 fn reseed(precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
946 Counter {
947 value: precision.apply(crate::rng::u64() & RESEED_MASK, timestamp),
948 }
949 }
950
951 #[inline]
952 fn increment(&self, precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
953 let mut counter = Counter {
954 value: precision.apply(self.value, timestamp),
955 };
956
957 counter.value += 1;
964
965 counter
966 }
967
968 #[inline]
969 fn has_overflowed(&self) -> bool {
970 self.value > MAX_COUNTER
971 }
972 }
973
974 #[cfg(feature = "std")]
975 pub(crate) struct SharedContextV7(std::sync::Mutex<ContextV7>);
976
977 #[cfg(feature = "std")]
978 impl ClockSequence for SharedContextV7 {
979 type Output = u64;
980
981 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
982 self.0.generate_sequence(seconds, subsec_nanos)
983 }
984
985 fn generate_timestamp_sequence(
986 &self,
987 seconds: u64,
988 subsec_nanos: u32,
989 ) -> (Self::Output, u64, u32) {
990 self.0.generate_timestamp_sequence(seconds, subsec_nanos)
991 }
992
993 fn usable_bits(&self) -> usize
994 where
995 Self::Output: Sized,
996 {
997 USABLE_BITS
998 }
999 }
1000
1001 #[cfg(test)]
1002 mod tests {
1003 use core::time::Duration;
1004
1005 use super::*;
1006
1007 use crate::{Timestamp, Uuid};
1008
1009 #[test]
1010 fn context() {
1011 let seconds = 1_496_854_535;
1012 let subsec_nanos = 812_946_000;
1013
1014 let context = ContextV7::new();
1015
1016 let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1017 assert_eq!(42, ts1.usable_counter_bits);
1018
1019 let seconds = 1_496_854_534;
1021
1022 let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1023
1024 assert_eq!(ts1.seconds, ts2.seconds);
1027 assert_eq!(ts1.subsec_nanos, ts2.subsec_nanos);
1028 assert_eq!(ts1.counter + 1, ts2.counter);
1029
1030 let seconds = 1_496_854_536;
1032
1033 let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1034
1035 assert_ne!(ts2.counter + 1, ts3.counter);
1037 assert_ne!(0, ts3.counter);
1038 }
1039
1040 #[test]
1041 fn context_wrap() {
1042 let seconds = 1_496_854_535u64;
1043 let subsec_nanos = 812_946_000u32;
1044
1045 let context = ContextV7 {
1047 timestamp: Cell::new(ReseedingTimestamp::from_ts(seconds, subsec_nanos)),
1048 adjust: Adjust::by_millis(0),
1049 precision: Precision {
1050 bits: 0,
1051 mask: 0,
1052 factor: 0,
1053 shift: 0,
1054 },
1055 counter: Cell::new(Counter {
1056 value: u64::MAX >> 22,
1057 }),
1058 };
1059
1060 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1061
1062 let expected_ts = Duration::new(seconds, subsec_nanos) + Duration::from_millis(1);
1064 assert_eq!(expected_ts.as_secs(), ts.seconds);
1065 assert_eq!(expected_ts.subsec_nanos(), ts.subsec_nanos);
1066
1067 assert!(ts.counter < (u64::MAX >> 22) as u128);
1069 assert_ne!(0, ts.counter);
1070 }
1071
1072 #[test]
1073 fn context_shift() {
1074 let seconds = 1_496_854_535;
1075 let subsec_nanos = 812_946_000;
1076
1077 let context = ContextV7::new().with_adjust_by_millis(1);
1078
1079 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1080
1081 assert_eq!((1_496_854_535, 813_946_000), ts.to_unix());
1082 }
1083
1084 #[test]
1085 fn context_additional_precision() {
1086 let seconds = 1_496_854_535;
1087 let subsec_nanos = 812_946_000;
1088
1089 let context = ContextV7::new().with_additional_precision();
1090
1091 let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1092
1093 assert_eq!(3861, ts1.counter >> 30);
1095
1096 assert!(ts1.counter < (u64::MAX >> 22) as u128);
1097
1098 let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1100
1101 assert!(Uuid::new_v7(ts2) > Uuid::new_v7(ts1));
1102
1103 let subsec_nanos = subsec_nanos + 1;
1105
1106 let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1107
1108 assert!(Uuid::new_v7(ts3) > Uuid::new_v7(ts2));
1109 }
1110
1111 #[test]
1112 fn context_overflow() {
1113 let seconds = u64::MAX;
1114 let subsec_nanos = u32::MAX;
1115
1116 for context in [
1118 ContextV7::new(),
1119 ContextV7::new().with_additional_precision(),
1120 ContextV7::new().with_adjust_by_millis(u32::MAX),
1121 ] {
1122 Timestamp::from_unix(&context, seconds, subsec_nanos);
1123 }
1124 }
1125 }
1126 }
1127
1128 #[cfg(feature = "v7")]
1129 pub use v7_support::*;
1130
1131 #[derive(Debug, Clone, Copy, Default)]
1142 pub struct NoContext;
1143
1144 impl ClockSequence for NoContext {
1145 type Output = u16;
1146
1147 fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
1148 0
1149 }
1150
1151 fn usable_bits(&self) -> usize {
1152 0
1153 }
1154 }
1155}
1156
1157#[cfg(all(test, any(feature = "v1", feature = "v6")))]
1158mod tests {
1159 use super::*;
1160
1161 #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))]
1162 use wasm_bindgen_test::*;
1163
1164 #[test]
1165 #[cfg_attr(
1166 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1167 wasm_bindgen_test
1168 )]
1169 fn gregorian_unix_does_not_panic() {
1170 Timestamp::unix_to_gregorian_ticks(u64::MAX, 0);
1172 Timestamp::unix_to_gregorian_ticks(0, u32::MAX);
1173 Timestamp::unix_to_gregorian_ticks(u64::MAX, u32::MAX);
1174
1175 Timestamp::gregorian_to_unix(u64::MAX);
1176 }
1177
1178 #[test]
1179 #[cfg_attr(
1180 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1181 wasm_bindgen_test
1182 )]
1183 fn to_gregorian_truncates_to_usable_bits() {
1184 let ts = Timestamp::from_gregorian(123, u16::MAX);
1185
1186 assert_eq!((123, u16::MAX >> 2), ts.to_gregorian());
1187 }
1188}