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