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
190#[cfg(feature = "std")]
191impl std::convert::TryFrom<std::time::SystemTime> for Timestamp {
192 type Error = crate::Error;
193
194 fn try_from(st: std::time::SystemTime) -> Result<Self, Self::Error> {
199 let dur = st.duration_since(std::time::UNIX_EPOCH).map_err(|_| crate::Error(crate::error::ErrorKind::InvalidSystemTime("unable to convert the system tie into a Unix timestamp")))?;
200
201 Ok(Self::from_unix_time(
202 dur.as_secs(),
203 dur.subsec_nanos(),
204 0,
205 0,
206 ))
207 }
208}
209
210#[cfg(feature = "std")]
211impl From<Timestamp> for std::time::SystemTime {
212 fn from(ts: Timestamp) -> Self {
213 let (seconds, subsec_nanos) = ts.to_unix();
214
215 Self::UNIX_EPOCH + std::time::Duration::new(seconds, subsec_nanos)
216 }
217}
218
219pub(crate) const fn encode_gregorian_timestamp(
220 ticks: u64,
221 counter: u16,
222 node_id: &[u8; 6],
223) -> Uuid {
224 let time_low = (ticks & 0xFFFF_FFFF) as u32;
225 let time_mid = ((ticks >> 32) & 0xFFFF) as u16;
226 let time_high_and_version = (((ticks >> 48) & 0x0FFF) as u16) | (1 << 12);
227
228 let mut d4 = [0; 8];
229
230 d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
231 d4[1] = (counter & 0xFF) as u8;
232 d4[2] = node_id[0];
233 d4[3] = node_id[1];
234 d4[4] = node_id[2];
235 d4[5] = node_id[3];
236 d4[6] = node_id[4];
237 d4[7] = node_id[5];
238
239 Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
240}
241
242pub(crate) const fn decode_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
243 let bytes = uuid.as_bytes();
244
245 let ticks: u64 = ((bytes[6] & 0x0F) as u64) << 56
246 | (bytes[7] as u64) << 48
247 | (bytes[4] as u64) << 40
248 | (bytes[5] as u64) << 32
249 | (bytes[0] as u64) << 24
250 | (bytes[1] as u64) << 16
251 | (bytes[2] as u64) << 8
252 | (bytes[3] as u64);
253
254 let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
255
256 (ticks, counter)
257}
258
259pub(crate) const fn encode_sorted_gregorian_timestamp(
260 ticks: u64,
261 counter: u16,
262 node_id: &[u8; 6],
263) -> Uuid {
264 let time_high = ((ticks >> 28) & 0xFFFF_FFFF) as u32;
265 let time_mid = ((ticks >> 12) & 0xFFFF) as u16;
266 let time_low_and_version = ((ticks & 0x0FFF) as u16) | (0x6 << 12);
267
268 let mut d4 = [0; 8];
269
270 d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
271 d4[1] = (counter & 0xFF) as u8;
272 d4[2] = node_id[0];
273 d4[3] = node_id[1];
274 d4[4] = node_id[2];
275 d4[5] = node_id[3];
276 d4[6] = node_id[4];
277 d4[7] = node_id[5];
278
279 Uuid::from_fields(time_high, time_mid, time_low_and_version, &d4)
280}
281
282pub(crate) const fn decode_sorted_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
283 let bytes = uuid.as_bytes();
284
285 let ticks: u64 = ((bytes[0]) as u64) << 52
286 | (bytes[1] as u64) << 44
287 | (bytes[2] as u64) << 36
288 | (bytes[3] as u64) << 28
289 | (bytes[4] as u64) << 20
290 | (bytes[5] as u64) << 12
291 | ((bytes[6] & 0xF) as u64) << 8
292 | (bytes[7] as u64);
293
294 let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
295
296 (ticks, counter)
297}
298
299pub(crate) const fn encode_unix_timestamp_millis(
300 millis: u64,
301 counter_random_bytes: &[u8; 10],
302) -> Uuid {
303 let millis_high = ((millis >> 16) & 0xFFFF_FFFF) as u32;
304 let millis_low = (millis & 0xFFFF) as u16;
305
306 let counter_random_version = (counter_random_bytes[1] as u16
307 | ((counter_random_bytes[0] as u16) << 8) & 0x0FFF)
308 | (0x7 << 12);
309
310 let mut d4 = [0; 8];
311
312 d4[0] = (counter_random_bytes[2] & 0x3F) | 0x80;
313 d4[1] = counter_random_bytes[3];
314 d4[2] = counter_random_bytes[4];
315 d4[3] = counter_random_bytes[5];
316 d4[4] = counter_random_bytes[6];
317 d4[5] = counter_random_bytes[7];
318 d4[6] = counter_random_bytes[8];
319 d4[7] = counter_random_bytes[9];
320
321 Uuid::from_fields(millis_high, millis_low, counter_random_version, &d4)
322}
323
324pub(crate) const fn decode_unix_timestamp_millis(uuid: &Uuid) -> u64 {
325 let bytes = uuid.as_bytes();
326
327 let millis: u64 = (bytes[0] as u64) << 40
328 | (bytes[1] as u64) << 32
329 | (bytes[2] as u64) << 24
330 | (bytes[3] as u64) << 16
331 | (bytes[4] as u64) << 8
332 | (bytes[5] as u64);
333
334 millis
335}
336
337#[cfg(all(
338 feature = "std",
339 feature = "js",
340 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))
341))]
342fn now() -> (u64, u32) {
343 use wasm_bindgen::prelude::*;
344
345 #[wasm_bindgen]
346 extern "C" {
347 #[wasm_bindgen(js_namespace = Date, catch)]
349 fn now() -> Result<f64, JsValue>;
350 }
351
352 let now = now().unwrap_throw();
353
354 let secs = (now / 1_000.0) as u64;
355 let nanos = ((now % 1_000.0) * 1_000_000.0) as u32;
356
357 (secs, nanos)
358}
359
360#[cfg(all(
361 feature = "std",
362 not(miri),
363 any(
364 not(feature = "js"),
365 not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))
366 )
367))]
368fn now() -> (u64, u32) {
369 let dur = std::time::SystemTime::UNIX_EPOCH.elapsed().expect(
370 "Getting elapsed time since UNIX_EPOCH. If this fails, we've somehow violated causality",
371 );
372
373 (dur.as_secs(), dur.subsec_nanos())
374}
375
376#[cfg(all(feature = "std", miri))]
377fn now() -> (u64, u32) {
378 use std::{sync::Mutex, time::Duration};
379
380 static TS: Mutex<u64> = Mutex::new(0);
381
382 let ts = Duration::from_nanos({
383 let mut ts = TS.lock().unwrap();
384 *ts += 1;
385 *ts
386 });
387
388 (ts.as_secs(), ts.subsec_nanos())
389}
390
391pub trait ClockSequence {
400 type Output;
402
403 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output;
409
410 fn generate_timestamp_sequence(
416 &self,
417 seconds: u64,
418 subsec_nanos: u32,
419 ) -> (Self::Output, u64, u32) {
420 (
421 self.generate_sequence(seconds, subsec_nanos),
422 seconds,
423 subsec_nanos,
424 )
425 }
426
427 fn usable_bits(&self) -> usize
435 where
436 Self::Output: Sized,
437 {
438 cmp::min(128, core::mem::size_of::<Self::Output>())
439 }
440}
441
442impl<'a, T: ClockSequence + ?Sized> ClockSequence for &'a T {
443 type Output = T::Output;
444
445 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
446 (**self).generate_sequence(seconds, subsec_nanos)
447 }
448
449 fn generate_timestamp_sequence(
450 &self,
451 seconds: u64,
452 subsec_nanos: u32,
453 ) -> (Self::Output, u64, u32) {
454 (**self).generate_timestamp_sequence(seconds, subsec_nanos)
455 }
456
457 fn usable_bits(&self) -> usize
458 where
459 Self::Output: Sized,
460 {
461 (**self).usable_bits()
462 }
463}
464
465pub mod context {
467 use super::ClockSequence;
468
469 #[cfg(any(feature = "v1", feature = "v6"))]
470 mod v1_support {
471 use super::*;
472
473 use atomic::{Atomic, Ordering};
474
475 #[cfg(all(feature = "std", feature = "rng"))]
476 static CONTEXT: Context = Context {
477 count: Atomic::new(0),
478 };
479
480 #[cfg(all(feature = "std", feature = "rng"))]
481 static CONTEXT_INITIALIZED: Atomic<bool> = Atomic::new(false);
482
483 #[cfg(all(feature = "std", feature = "rng"))]
484 pub(crate) fn shared_context() -> &'static Context {
485 if CONTEXT_INITIALIZED
488 .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
489 .is_ok()
490 {
491 CONTEXT.count.store(crate::rng::u16(), Ordering::Release);
492 }
493
494 &CONTEXT
495 }
496
497 #[derive(Debug)]
512 pub struct Context {
513 count: Atomic<u16>,
514 }
515
516 impl Context {
517 pub const fn new(count: u16) -> Self {
523 Self {
524 count: Atomic::<u16>::new(count),
525 }
526 }
527
528 #[cfg(feature = "rng")]
530 pub fn new_random() -> Self {
531 Self {
532 count: Atomic::<u16>::new(crate::rng::u16()),
533 }
534 }
535 }
536
537 impl ClockSequence for Context {
538 type Output = u16;
539
540 fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
541 self.count.fetch_add(1, Ordering::AcqRel) & (u16::MAX >> 2)
547 }
548
549 fn usable_bits(&self) -> usize {
550 14
551 }
552 }
553
554 #[cfg(test)]
555 mod tests {
556 use crate::Timestamp;
557
558 use super::*;
559
560 #[test]
561 fn context() {
562 let seconds = 1_496_854_535;
563 let subsec_nanos = 812_946_000;
564
565 let context = Context::new(u16::MAX >> 2);
566
567 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
568 assert_eq!(16383, ts.counter);
569 assert_eq!(14, ts.usable_counter_bits);
570
571 let seconds = 1_496_854_536;
572
573 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
574 assert_eq!(0, ts.counter);
575
576 let seconds = 1_496_854_535;
577
578 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
579 assert_eq!(1, ts.counter);
580 }
581
582 #[test]
583 fn context_overflow() {
584 let seconds = u64::MAX;
585 let subsec_nanos = u32::MAX;
586
587 let context = Context::new(u16::MAX);
588
589 Timestamp::from_unix(&context, seconds, subsec_nanos);
591 }
592 }
593 }
594
595 #[cfg(any(feature = "v1", feature = "v6"))]
596 pub use v1_support::*;
597
598 #[cfg(feature = "std")]
599 mod std_support {
600 use super::*;
601
602 use core::panic::{AssertUnwindSafe, RefUnwindSafe};
603 use std::{sync::Mutex, thread::LocalKey};
604
605 pub struct ThreadLocalContext<C: 'static>(&'static LocalKey<C>);
607
608 impl<C> std::fmt::Debug for ThreadLocalContext<C> {
609 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
610 f.debug_struct("ThreadLocalContext").finish_non_exhaustive()
611 }
612 }
613
614 impl<C: 'static> ThreadLocalContext<C> {
615 pub const fn new(local_key: &'static LocalKey<C>) -> Self {
617 ThreadLocalContext(local_key)
618 }
619 }
620
621 impl<C: ClockSequence + 'static> ClockSequence for ThreadLocalContext<C> {
622 type Output = C::Output;
623
624 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
625 self.0
626 .with(|ctxt| ctxt.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
635 .with(|ctxt| ctxt.generate_timestamp_sequence(seconds, subsec_nanos))
636 }
637
638 fn usable_bits(&self) -> usize {
639 self.0.with(|ctxt| ctxt.usable_bits())
640 }
641 }
642
643 impl<C: ClockSequence> ClockSequence for AssertUnwindSafe<C> {
644 type Output = C::Output;
645
646 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
647 self.0.generate_sequence(seconds, subsec_nanos)
648 }
649
650 fn generate_timestamp_sequence(
651 &self,
652 seconds: u64,
653 subsec_nanos: u32,
654 ) -> (Self::Output, u64, u32) {
655 self.0.generate_timestamp_sequence(seconds, subsec_nanos)
656 }
657
658 fn usable_bits(&self) -> usize
659 where
660 Self::Output: Sized,
661 {
662 self.0.usable_bits()
663 }
664 }
665
666 impl<C: ClockSequence + RefUnwindSafe> ClockSequence for Mutex<C> {
667 type Output = C::Output;
668
669 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
670 self.lock()
671 .unwrap_or_else(|err| err.into_inner())
672 .generate_sequence(seconds, subsec_nanos)
673 }
674
675 fn generate_timestamp_sequence(
676 &self,
677 seconds: u64,
678 subsec_nanos: u32,
679 ) -> (Self::Output, u64, u32) {
680 self.lock()
681 .unwrap_or_else(|err| err.into_inner())
682 .generate_timestamp_sequence(seconds, subsec_nanos)
683 }
684
685 fn usable_bits(&self) -> usize
686 where
687 Self::Output: Sized,
688 {
689 self.lock()
690 .unwrap_or_else(|err| err.into_inner())
691 .usable_bits()
692 }
693 }
694 }
695
696 #[cfg(feature = "std")]
697 pub use std_support::*;
698
699 #[cfg(feature = "v7")]
700 mod v7_support {
701 use super::*;
702
703 use core::{cell::Cell, cmp, panic::RefUnwindSafe};
704
705 #[cfg(feature = "std")]
706 static CONTEXT_V7: SharedContextV7 =
707 SharedContextV7(std::sync::Mutex::new(ContextV7::new()));
708
709 #[cfg(feature = "std")]
710 pub(crate) fn shared_context_v7() -> &'static SharedContextV7 {
711 &CONTEXT_V7
712 }
713
714 const USABLE_BITS: usize = 42;
715
716 const RESEED_MASK: u64 = u64::MAX >> 23;
721 const MAX_COUNTER: u64 = u64::MAX >> 22;
722
723 #[derive(Debug)]
746 pub struct ContextV7 {
747 timestamp: Cell<ReseedingTimestamp>,
748 counter: Cell<Counter>,
749 adjust: Adjust,
750 precision: Precision,
751 }
752
753 impl RefUnwindSafe for ContextV7 {}
754
755 impl ContextV7 {
756 pub const fn new() -> Self {
759 ContextV7 {
760 timestamp: Cell::new(ReseedingTimestamp {
761 last_seed: 0,
762 seconds: 0,
763 subsec_nanos: 0,
764 }),
765 counter: Cell::new(Counter { value: 0 }),
766 adjust: Adjust { by_ns: 0 },
767 precision: Precision {
768 bits: 0,
769 mask: 0,
770 factor: 0,
771 shift: 0,
772 },
773 }
774 }
775
776 pub fn with_adjust_by_millis(mut self, millis: u32) -> Self {
778 self.adjust = Adjust::by_millis(millis);
779 self
780 }
781
782 pub fn with_additional_precision(mut self) -> Self {
789 self.precision = Precision::new(12);
790 self
791 }
792 }
793
794 impl ClockSequence for ContextV7 {
795 type Output = u64;
796
797 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
798 self.generate_timestamp_sequence(seconds, subsec_nanos).0
799 }
800
801 fn generate_timestamp_sequence(
802 &self,
803 seconds: u64,
804 subsec_nanos: u32,
805 ) -> (Self::Output, u64, u32) {
806 let (seconds, subsec_nanos) = self.adjust.apply(seconds, subsec_nanos);
807
808 let mut counter;
809 let (mut timestamp, should_reseed) =
810 self.timestamp.get().advance(seconds, subsec_nanos);
811
812 if should_reseed {
813 counter = Counter::reseed(&self.precision, ×tamp);
815 } else {
816 counter = self.counter.get().increment(&self.precision, ×tamp);
823
824 if counter.has_overflowed() {
828 timestamp = timestamp.increment();
830 counter = Counter::reseed(&self.precision, ×tamp);
831 }
832 };
833
834 self.timestamp.set(timestamp);
835 self.counter.set(counter);
836
837 (counter.value, timestamp.seconds, timestamp.subsec_nanos)
838 }
839
840 fn usable_bits(&self) -> usize {
841 USABLE_BITS
842 }
843 }
844
845 #[derive(Debug)]
846 struct Adjust {
847 by_ns: u128,
848 }
849
850 impl Adjust {
851 #[inline]
852 fn by_millis(millis: u32) -> Self {
853 Adjust {
854 by_ns: (millis as u128).saturating_mul(1_000_000),
855 }
856 }
857
858 #[inline]
859 fn apply(&self, seconds: u64, subsec_nanos: u32) -> (u64, u32) {
860 if self.by_ns == 0 {
861 return (seconds, subsec_nanos);
863 }
864
865 let ts = (seconds as u128)
866 .saturating_mul(1_000_000_000)
867 .saturating_add(subsec_nanos as u128)
868 .saturating_add(self.by_ns as u128);
869
870 ((ts / 1_000_000_000) as u64, (ts % 1_000_000_000) as u32)
871 }
872 }
873
874 #[derive(Debug, Default, Clone, Copy)]
875 struct ReseedingTimestamp {
876 last_seed: u64,
877 seconds: u64,
878 subsec_nanos: u32,
879 }
880
881 impl ReseedingTimestamp {
882 #[inline]
883 fn advance(&self, seconds: u64, subsec_nanos: u32) -> (Self, bool) {
884 let incoming = ReseedingTimestamp::from_ts(seconds, subsec_nanos);
885
886 if incoming.last_seed > self.last_seed {
887 (incoming, true)
889 } else {
890 let mut value = *self;
893 value.subsec_nanos = cmp::max(self.subsec_nanos, subsec_nanos);
894
895 (value, false)
896 }
897 }
898
899 #[inline]
900 fn from_ts(seconds: u64, subsec_nanos: u32) -> Self {
901 let last_seed = seconds
903 .saturating_mul(1_000)
904 .saturating_add((subsec_nanos / 1_000_000) as u64);
905
906 ReseedingTimestamp {
907 last_seed,
908 seconds,
909 subsec_nanos,
910 }
911 }
912
913 #[inline]
914 fn increment(&self) -> Self {
915 let (seconds, subsec_nanos) =
916 Adjust::by_millis(1).apply(self.seconds, self.subsec_nanos);
917
918 ReseedingTimestamp::from_ts(seconds, subsec_nanos)
919 }
920
921 #[inline]
922 fn submilli_nanos(&self) -> u32 {
923 self.subsec_nanos % 1_000_000
924 }
925 }
926
927 #[derive(Debug)]
928 struct Precision {
929 bits: usize,
930 factor: u64,
931 mask: u64,
932 shift: u64,
933 }
934
935 impl Precision {
936 fn new(bits: usize) -> Self {
937 let mask = u64::MAX >> (64 - USABLE_BITS + bits);
940 let shift = (USABLE_BITS - bits) as u64;
941
942 let factor = (999_999 / u64::pow(2, bits as u32)) + 1;
945
946 Precision {
947 bits,
948 factor,
949 mask,
950 shift,
951 }
952 }
953
954 #[inline]
955 fn apply(&self, value: u64, timestamp: &ReseedingTimestamp) -> u64 {
956 if self.bits == 0 {
957 return value;
959 }
960
961 let additional = timestamp.submilli_nanos() as u64 / self.factor;
962
963 (value & self.mask) | (additional << self.shift)
964 }
965 }
966
967 #[derive(Debug, Clone, Copy)]
968 struct Counter {
969 value: u64,
970 }
971
972 impl Counter {
973 #[inline]
974 fn reseed(precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
975 Counter {
976 value: precision.apply(crate::rng::u64() & RESEED_MASK, timestamp),
977 }
978 }
979
980 #[inline]
981 fn increment(&self, precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
982 let mut counter = Counter {
983 value: precision.apply(self.value, timestamp),
984 };
985
986 counter.value += 1;
993
994 counter
995 }
996
997 #[inline]
998 fn has_overflowed(&self) -> bool {
999 self.value > MAX_COUNTER
1000 }
1001 }
1002
1003 #[cfg(feature = "std")]
1004 pub(crate) struct SharedContextV7(std::sync::Mutex<ContextV7>);
1005
1006 #[cfg(feature = "std")]
1007 impl ClockSequence for SharedContextV7 {
1008 type Output = u64;
1009
1010 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
1011 self.0.generate_sequence(seconds, subsec_nanos)
1012 }
1013
1014 fn generate_timestamp_sequence(
1015 &self,
1016 seconds: u64,
1017 subsec_nanos: u32,
1018 ) -> (Self::Output, u64, u32) {
1019 self.0.generate_timestamp_sequence(seconds, subsec_nanos)
1020 }
1021
1022 fn usable_bits(&self) -> usize
1023 where
1024 Self::Output: Sized,
1025 {
1026 USABLE_BITS
1027 }
1028 }
1029
1030 #[cfg(test)]
1031 mod tests {
1032 use core::time::Duration;
1033
1034 use super::*;
1035
1036 use crate::{Timestamp, Uuid};
1037
1038 #[test]
1039 fn context() {
1040 let seconds = 1_496_854_535;
1041 let subsec_nanos = 812_946_000;
1042
1043 let context = ContextV7::new();
1044
1045 let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1046 assert_eq!(42, ts1.usable_counter_bits);
1047
1048 let seconds = 1_496_854_534;
1050
1051 let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1052
1053 assert_eq!(ts1.seconds, ts2.seconds);
1056 assert_eq!(ts1.subsec_nanos, ts2.subsec_nanos);
1057 assert_eq!(ts1.counter + 1, ts2.counter);
1058
1059 let seconds = 1_496_854_536;
1061
1062 let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1063
1064 assert_ne!(ts2.counter + 1, ts3.counter);
1066 assert_ne!(0, ts3.counter);
1067 }
1068
1069 #[test]
1070 fn context_wrap() {
1071 let seconds = 1_496_854_535u64;
1072 let subsec_nanos = 812_946_000u32;
1073
1074 let context = ContextV7 {
1076 timestamp: Cell::new(ReseedingTimestamp::from_ts(seconds, subsec_nanos)),
1077 adjust: Adjust::by_millis(0),
1078 precision: Precision {
1079 bits: 0,
1080 mask: 0,
1081 factor: 0,
1082 shift: 0,
1083 },
1084 counter: Cell::new(Counter {
1085 value: u64::MAX >> 22,
1086 }),
1087 };
1088
1089 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1090
1091 let expected_ts = Duration::new(seconds, subsec_nanos) + Duration::from_millis(1);
1093 assert_eq!(expected_ts.as_secs(), ts.seconds);
1094 assert_eq!(expected_ts.subsec_nanos(), ts.subsec_nanos);
1095
1096 assert!(ts.counter < (u64::MAX >> 22) as u128);
1098 assert_ne!(0, ts.counter);
1099 }
1100
1101 #[test]
1102 fn context_shift() {
1103 let seconds = 1_496_854_535;
1104 let subsec_nanos = 812_946_000;
1105
1106 let context = ContextV7::new().with_adjust_by_millis(1);
1107
1108 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1109
1110 assert_eq!((1_496_854_535, 813_946_000), ts.to_unix());
1111 }
1112
1113 #[test]
1114 fn context_additional_precision() {
1115 let seconds = 1_496_854_535;
1116 let subsec_nanos = 812_946_000;
1117
1118 let context = ContextV7::new().with_additional_precision();
1119
1120 let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1121
1122 assert_eq!(3861, ts1.counter >> 30);
1124
1125 assert!(ts1.counter < (u64::MAX >> 22) as u128);
1126
1127 let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1129
1130 assert!(Uuid::new_v7(ts2) > Uuid::new_v7(ts1));
1131
1132 let subsec_nanos = subsec_nanos + 1;
1134
1135 let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1136
1137 assert!(Uuid::new_v7(ts3) > Uuid::new_v7(ts2));
1138 }
1139
1140 #[test]
1141 fn context_overflow() {
1142 let seconds = u64::MAX;
1143 let subsec_nanos = u32::MAX;
1144
1145 for context in [
1147 ContextV7::new(),
1148 ContextV7::new().with_additional_precision(),
1149 ContextV7::new().with_adjust_by_millis(u32::MAX),
1150 ] {
1151 Timestamp::from_unix(&context, seconds, subsec_nanos);
1152 }
1153 }
1154 }
1155 }
1156
1157 #[cfg(feature = "v7")]
1158 pub use v7_support::*;
1159
1160 #[derive(Debug, Clone, Copy, Default)]
1171 pub struct NoContext;
1172
1173 impl ClockSequence for NoContext {
1174 type Output = u16;
1175
1176 fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
1177 0
1178 }
1179
1180 fn usable_bits(&self) -> usize {
1181 0
1182 }
1183 }
1184}
1185
1186#[cfg(all(test, any(feature = "v1", feature = "v6")))]
1187mod tests {
1188 use super::*;
1189
1190 #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))]
1191 use wasm_bindgen_test::*;
1192
1193 #[test]
1194 #[cfg_attr(
1195 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1196 wasm_bindgen_test
1197 )]
1198 fn gregorian_unix_does_not_panic() {
1199 Timestamp::unix_to_gregorian_ticks(u64::MAX, 0);
1201 Timestamp::unix_to_gregorian_ticks(0, u32::MAX);
1202 Timestamp::unix_to_gregorian_ticks(u64::MAX, u32::MAX);
1203
1204 Timestamp::gregorian_to_unix(u64::MAX);
1205 }
1206
1207 #[test]
1208 #[cfg_attr(
1209 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1210 wasm_bindgen_test
1211 )]
1212 fn to_gregorian_truncates_to_usable_bits() {
1213 let ts = Timestamp::from_gregorian(123, u16::MAX);
1214
1215 assert_eq!((123, u16::MAX >> 2), ts.to_gregorian());
1216 }
1217}
1218
1219#[cfg(all(test, feature = "std", not(miri)))]
1221mod test_conversion {
1222 use std::{
1223 convert::{TryFrom, TryInto},
1224 time::{Duration, SystemTime},
1225 };
1226
1227 use super::Timestamp;
1228
1229 const KNOWN_SECONDS: u64 = 1_501_520_400;
1231 const KNOWN_NANOS: u32 = 1_000;
1232
1233 fn known_system_time() -> SystemTime {
1234 SystemTime::UNIX_EPOCH
1235 .checked_add(Duration::new(KNOWN_SECONDS, KNOWN_NANOS))
1236 .unwrap()
1237 }
1238
1239 fn known_timestamp() -> Timestamp {
1240 Timestamp::from_unix_time(KNOWN_SECONDS, KNOWN_NANOS, 0, 0)
1241 }
1242
1243 #[test]
1244 fn to_system_time() {
1245 let st: SystemTime = known_timestamp().into();
1246
1247 assert_eq!(known_system_time(), st);
1248 }
1249
1250 #[test]
1251 fn from_system_time() {
1252 let ts: Timestamp = known_system_time().try_into().unwrap();
1253
1254 assert_eq!(known_timestamp(), ts);
1255 }
1256
1257 #[test]
1258 fn from_system_time_before_epoch() {
1259 let before_epoch = match SystemTime::UNIX_EPOCH.checked_sub(Duration::from_nanos(1_000)) {
1260 Some(st) => st,
1261 None => return,
1262 };
1263
1264 Timestamp::try_from(before_epoch)
1265 .expect_err("Timestamp should not be created from before epoch");
1266 }
1267}