1use core::cmp;
25
26use crate::Uuid;
27
28pub const UUID_TICKS_BETWEEN_EPOCHS: u64 = 0x01B2_1DD2_1381_4000;
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
43pub struct Timestamp {
44 seconds: u64,
45 subsec_nanos: u32,
46 counter: u128,
47 usable_counter_bits: u8,
48}
49
50impl Timestamp {
51 #[cfg(feature = "std")]
55 pub fn now(context: impl ClockSequence<Output = impl Into<u128>>) -> Self {
56 let (seconds, subsec_nanos) = now();
57
58 let (counter, seconds, subsec_nanos) =
59 context.generate_timestamp_sequence(seconds, subsec_nanos);
60 let counter = counter.into();
61 let usable_counter_bits = context.usable_bits() as u8;
62
63 Timestamp {
64 seconds,
65 subsec_nanos,
66 counter,
67 usable_counter_bits,
68 }
69 }
70
71 pub const fn from_gregorian_time(ticks: u64, counter: u16) -> Self {
80 let (seconds, subsec_nanos) = Self::gregorian_to_unix(ticks);
81
82 Timestamp {
83 seconds,
84 subsec_nanos,
85 counter: counter as u128,
86 usable_counter_bits: 14,
87 }
88 }
89
90 pub const fn from_unix_time(
92 seconds: u64,
93 subsec_nanos: u32,
94 counter: u128,
95 usable_counter_bits: u8,
96 ) -> Self {
97 Timestamp {
98 seconds,
99 subsec_nanos,
100 counter,
101 usable_counter_bits,
102 }
103 }
104
105 pub fn from_unix(
107 context: impl ClockSequence<Output = impl Into<u128>>,
108 seconds: u64,
109 subsec_nanos: u32,
110 ) -> Self {
111 let (counter, seconds, subsec_nanos) =
112 context.generate_timestamp_sequence(seconds, subsec_nanos);
113 let counter = counter.into();
114 let usable_counter_bits = context.usable_bits() as u8;
115
116 Timestamp {
117 seconds,
118 subsec_nanos,
119 counter,
120 usable_counter_bits,
121 }
122 }
123
124 pub const fn to_gregorian(&self) -> (u64, u16) {
134 (
135 Self::unix_to_gregorian_ticks(self.seconds, self.subsec_nanos),
136 (self.counter as u16) & 0x3FFF,
137 )
138 }
139
140 #[cfg(feature = "v7")]
143 pub(crate) const fn counter(&self) -> (u128, u8) {
144 (self.counter, self.usable_counter_bits)
145 }
146
147 pub const fn to_unix(&self) -> (u64, u32) {
149 (self.seconds, self.subsec_nanos)
150 }
151
152 const fn unix_to_gregorian_ticks(seconds: u64, nanos: u32) -> u64 {
153 UUID_TICKS_BETWEEN_EPOCHS
154 .wrapping_add(seconds.wrapping_mul(10_000_000))
155 .wrapping_add(nanos as u64 / 100)
156 }
157
158 const fn gregorian_to_unix(ticks: u64) -> (u64, u32) {
159 (
160 ticks.wrapping_sub(UUID_TICKS_BETWEEN_EPOCHS) / 10_000_000,
161 (ticks.wrapping_sub(UUID_TICKS_BETWEEN_EPOCHS) % 10_000_000) as u32 * 100,
162 )
163 }
164}
165
166#[doc(hidden)]
167impl Timestamp {
168 #[deprecated(
169 since = "1.10.0",
170 note = "use `Timestamp::from_gregorian_time(ticks, counter)`"
171 )]
172 pub const fn from_rfc4122(ticks: u64, counter: u16) -> Self {
173 Timestamp::from_gregorian_time(ticks, counter)
174 }
175
176 #[deprecated(since = "1.10.0", note = "use `Timestamp::to_gregorian()`")]
177 pub const fn to_rfc4122(&self) -> (u64, u16) {
178 self.to_gregorian()
179 }
180
181 #[deprecated(
182 since = "1.2.0",
183 note = "`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`"
184 )]
185 pub const fn to_unix_nanos(&self) -> u32 {
186 panic!("`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`")
187 }
188
189 #[deprecated(
190 since = "1.23.0",
191 note = "use `Timestamp::from_gregorian_time(ticks, counter)`"
192 )]
193 pub const fn from_gregorian(ticks: u64, counter: u16) -> Self {
194 Timestamp::from_gregorian_time(ticks, counter)
195 }
196}
197
198#[cfg(feature = "std")]
199impl TryFrom<std::time::SystemTime> for Timestamp {
200 type Error = crate::Error;
201
202 fn try_from(st: std::time::SystemTime) -> Result<Self, Self::Error> {
207 let dur = st.duration_since(std::time::UNIX_EPOCH).map_err(|_| {
208 crate::Error(crate::error::ErrorKind::InvalidSystemTime(
209 "unable to convert the system tie into a Unix timestamp",
210 ))
211 })?;
212
213 Ok(Self::from_unix_time(
214 dur.as_secs(),
215 dur.subsec_nanos(),
216 0,
217 0,
218 ))
219 }
220}
221
222#[cfg(feature = "std")]
223impl From<Timestamp> for std::time::SystemTime {
224 fn from(ts: Timestamp) -> Self {
230 let (seconds, subsec_nanos) = ts.to_unix();
231
232 Self::UNIX_EPOCH
235 .checked_add(std::time::Duration::new(seconds, subsec_nanos))
236 .unwrap_or(std::time::SystemTime::UNIX_EPOCH)
237 }
238}
239
240pub(crate) const fn encode_gregorian_timestamp(
241 ticks: u64,
242 counter: u16,
243 node_id: &[u8; 6],
244) -> Uuid {
245 let time_low = (ticks & 0xFFFF_FFFF) as u32;
246 let time_mid = ((ticks >> 32) & 0xFFFF) as u16;
247 let time_high_and_version = (((ticks >> 48) & 0x0FFF) as u16) | (1 << 12);
248
249 let mut d4 = [0; 8];
250
251 d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
252 d4[1] = (counter & 0xFF) as u8;
253 d4[2] = node_id[0];
254 d4[3] = node_id[1];
255 d4[4] = node_id[2];
256 d4[5] = node_id[3];
257 d4[6] = node_id[4];
258 d4[7] = node_id[5];
259
260 Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
261}
262
263pub(crate) const fn decode_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
264 let bytes = uuid.as_bytes();
265
266 let ticks: u64 = ((bytes[6] & 0x0F) as u64) << 56
267 | (bytes[7] as u64) << 48
268 | (bytes[4] as u64) << 40
269 | (bytes[5] as u64) << 32
270 | (bytes[0] as u64) << 24
271 | (bytes[1] as u64) << 16
272 | (bytes[2] as u64) << 8
273 | (bytes[3] as u64);
274
275 let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
276
277 (ticks, counter)
278}
279
280pub(crate) const fn encode_sorted_gregorian_timestamp(
281 ticks: u64,
282 counter: u16,
283 node_id: &[u8; 6],
284) -> Uuid {
285 let time_high = ((ticks >> 28) & 0xFFFF_FFFF) as u32;
286 let time_mid = ((ticks >> 12) & 0xFFFF) as u16;
287 let time_low_and_version = ((ticks & 0x0FFF) as u16) | (0x6 << 12);
288
289 let mut d4 = [0; 8];
290
291 d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
292 d4[1] = (counter & 0xFF) as u8;
293 d4[2] = node_id[0];
294 d4[3] = node_id[1];
295 d4[4] = node_id[2];
296 d4[5] = node_id[3];
297 d4[6] = node_id[4];
298 d4[7] = node_id[5];
299
300 Uuid::from_fields(time_high, time_mid, time_low_and_version, &d4)
301}
302
303pub(crate) const fn decode_sorted_gregorian_timestamp(uuid: &Uuid) -> (u64, u16) {
304 let bytes = uuid.as_bytes();
305
306 let ticks: u64 = ((bytes[0]) as u64) << 52
307 | (bytes[1] as u64) << 44
308 | (bytes[2] as u64) << 36
309 | (bytes[3] as u64) << 28
310 | (bytes[4] as u64) << 20
311 | (bytes[5] as u64) << 12
312 | ((bytes[6] & 0xF) as u64) << 8
313 | (bytes[7] as u64);
314
315 let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
316
317 (ticks, counter)
318}
319
320pub(crate) const fn encode_unix_timestamp_millis(
321 millis: u64,
322 counter_random_bytes: &[u8; 10],
323) -> Uuid {
324 let millis_high = ((millis >> 16) & 0xFFFF_FFFF) as u32;
325 let millis_low = (millis & 0xFFFF) as u16;
326
327 let counter_random_version = (counter_random_bytes[1] as u16
328 | ((counter_random_bytes[0] as u16) << 8) & 0x0FFF)
329 | (0x7 << 12);
330
331 let mut d4 = [0; 8];
332
333 d4[0] = (counter_random_bytes[2] & 0x3F) | 0x80;
334 d4[1] = counter_random_bytes[3];
335 d4[2] = counter_random_bytes[4];
336 d4[3] = counter_random_bytes[5];
337 d4[4] = counter_random_bytes[6];
338 d4[5] = counter_random_bytes[7];
339 d4[6] = counter_random_bytes[8];
340 d4[7] = counter_random_bytes[9];
341
342 Uuid::from_fields(millis_high, millis_low, counter_random_version, &d4)
343}
344
345pub(crate) const fn decode_unix_timestamp_millis(uuid: &Uuid) -> u64 {
346 let bytes = uuid.as_bytes();
347
348 let millis: u64 = (bytes[0] as u64) << 40
349 | (bytes[1] as u64) << 32
350 | (bytes[2] as u64) << 24
351 | (bytes[3] as u64) << 16
352 | (bytes[4] as u64) << 8
353 | (bytes[5] as u64);
354
355 millis
356}
357
358#[cfg(all(
359 feature = "std",
360 feature = "js",
361 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))
362))]
363fn now() -> (u64, u32) {
364 use wasm_bindgen::prelude::*;
365
366 #[wasm_bindgen]
367 extern "C" {
368 #[wasm_bindgen(js_namespace = Date, catch)]
370 fn now() -> Result<f64, JsValue>;
371 }
372
373 let now = now().unwrap_throw();
374
375 let secs = (now / 1_000.0) as u64;
376 let nanos = ((now % 1_000.0) * 1_000_000.0) as u32;
377
378 (secs, nanos)
379}
380
381#[cfg(all(
382 feature = "std",
383 not(miri),
384 any(
385 not(feature = "js"),
386 not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))
387 )
388))]
389fn now() -> (u64, u32) {
390 let dur = std::time::SystemTime::UNIX_EPOCH.elapsed().expect(
391 "Getting elapsed time since UNIX_EPOCH. If this fails, we've somehow violated causality",
392 );
393
394 (dur.as_secs(), dur.subsec_nanos())
395}
396
397#[cfg(all(feature = "std", miri))]
398fn now() -> (u64, u32) {
399 use std::{sync::Mutex, time::Duration};
400
401 static TS: Mutex<u64> = Mutex::new(0);
402
403 let ts = Duration::from_nanos({
404 let mut ts = TS.lock().unwrap();
405 *ts += 1;
406 *ts
407 });
408
409 (ts.as_secs(), ts.subsec_nanos())
410}
411
412pub trait ClockSequence {
421 type Output;
423
424 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output;
430
431 fn generate_timestamp_sequence(
437 &self,
438 seconds: u64,
439 subsec_nanos: u32,
440 ) -> (Self::Output, u64, u32) {
441 (
442 self.generate_sequence(seconds, subsec_nanos),
443 seconds,
444 subsec_nanos,
445 )
446 }
447
448 fn usable_bits(&self) -> usize
456 where
457 Self::Output: Sized,
458 {
459 cmp::min(128, core::mem::size_of::<Self::Output>() * 8)
460 }
461}
462
463impl<T: ClockSequence + ?Sized> ClockSequence for &T {
464 type Output = T::Output;
465
466 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
467 (**self).generate_sequence(seconds, subsec_nanos)
468 }
469
470 fn generate_timestamp_sequence(
471 &self,
472 seconds: u64,
473 subsec_nanos: u32,
474 ) -> (Self::Output, u64, u32) {
475 (**self).generate_timestamp_sequence(seconds, subsec_nanos)
476 }
477
478 fn usable_bits(&self) -> usize
479 where
480 Self::Output: Sized,
481 {
482 (**self).usable_bits()
483 }
484}
485
486pub mod context {
488 use super::ClockSequence;
489
490 #[cfg(any(feature = "v1", feature = "v6"))]
491 mod v1_support {
492 use super::*;
493
494 #[cfg(all(feature = "std", feature = "rng"))]
495 use crate::std::sync::LazyLock;
496
497 use atomic::{Atomic, Ordering};
498
499 #[cfg(all(feature = "std", feature = "rng"))]
500 static CONTEXT: LazyLock<ContextV1> = LazyLock::new(ContextV1::new_random);
501
502 #[cfg(all(feature = "std", feature = "rng"))]
503 pub(crate) fn shared_context_v1() -> &'static ContextV1 {
504 &*CONTEXT
505 }
506
507 #[derive(Debug)]
523 pub struct ContextV1 {
524 count: Atomic<u16>,
525 }
526
527 impl ContextV1 {
528 pub const fn new(count: u16) -> Self {
534 Self {
535 count: Atomic::<u16>::new(count),
536 }
537 }
538
539 #[cfg(feature = "rng")]
541 pub fn new_random() -> Self {
542 Self {
543 count: Atomic::<u16>::new(crate::rng::u16()),
544 }
545 }
546 }
547
548 impl ClockSequence for ContextV1 {
549 type Output = u16;
550
551 fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
552 self.count.fetch_add(1, Ordering::AcqRel) & (u16::MAX >> 2)
558 }
559
560 fn usable_bits(&self) -> usize {
561 14
562 }
563 }
564
565 #[deprecated(since = "1.23.0", note = "renamed to `ContextV1`")]
566 #[doc(hidden)]
567 pub type Context = ContextV1;
568
569 #[cfg(test)]
570 mod tests {
571 use crate::Timestamp;
572
573 use super::*;
574
575 #[test]
576 fn context() {
577 let seconds = 1_496_854_535;
578 let subsec_nanos = 812_946_000;
579
580 let context = ContextV1::new(u16::MAX >> 2);
581
582 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
583 assert_eq!(16383, ts.counter);
584 assert_eq!(14, ts.usable_counter_bits);
585
586 let seconds = 1_496_854_536;
587
588 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
589 assert_eq!(0, ts.counter);
590
591 let seconds = 1_496_854_535;
592
593 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
594 assert_eq!(1, ts.counter);
595 }
596
597 #[test]
598 fn context_overflow() {
599 let seconds = u64::MAX;
600 let subsec_nanos = u32::MAX;
601
602 let context = ContextV1::new(u16::MAX);
603
604 Timestamp::from_unix(&context, seconds, subsec_nanos);
606 }
607 }
608 }
609
610 #[cfg(any(feature = "v1", feature = "v6"))]
611 pub use v1_support::*;
612
613 #[cfg(feature = "std")]
614 mod std_support {
615 use super::*;
616
617 use core::panic::{AssertUnwindSafe, RefUnwindSafe};
618 use std::{sync::Mutex, thread::LocalKey};
619
620 pub struct ThreadLocalContext<C: 'static>(&'static LocalKey<C>);
622
623 impl<C> std::fmt::Debug for ThreadLocalContext<C> {
624 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
625 f.debug_struct("ThreadLocalContext").finish_non_exhaustive()
626 }
627 }
628
629 impl<C: 'static> ThreadLocalContext<C> {
630 pub const fn new(local_key: &'static LocalKey<C>) -> Self {
632 ThreadLocalContext(local_key)
633 }
634 }
635
636 impl<C: ClockSequence + 'static> ClockSequence for ThreadLocalContext<C> {
637 type Output = C::Output;
638
639 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
640 self.0
641 .with(|ctxt| ctxt.generate_sequence(seconds, subsec_nanos))
642 }
643
644 fn generate_timestamp_sequence(
645 &self,
646 seconds: u64,
647 subsec_nanos: u32,
648 ) -> (Self::Output, u64, u32) {
649 self.0
650 .with(|ctxt| ctxt.generate_timestamp_sequence(seconds, subsec_nanos))
651 }
652
653 fn usable_bits(&self) -> usize {
654 self.0.with(|ctxt| ctxt.usable_bits())
655 }
656 }
657
658 impl<C: ClockSequence> ClockSequence for AssertUnwindSafe<C> {
659 type Output = C::Output;
660
661 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
662 self.0.generate_sequence(seconds, subsec_nanos)
663 }
664
665 fn generate_timestamp_sequence(
666 &self,
667 seconds: u64,
668 subsec_nanos: u32,
669 ) -> (Self::Output, u64, u32) {
670 self.0.generate_timestamp_sequence(seconds, subsec_nanos)
671 }
672
673 fn usable_bits(&self) -> usize
674 where
675 Self::Output: Sized,
676 {
677 self.0.usable_bits()
678 }
679 }
680
681 impl<C: ClockSequence + RefUnwindSafe> ClockSequence for Mutex<C> {
682 type Output = C::Output;
683
684 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
685 self.lock()
686 .unwrap_or_else(|err| err.into_inner())
687 .generate_sequence(seconds, subsec_nanos)
688 }
689
690 fn generate_timestamp_sequence(
691 &self,
692 seconds: u64,
693 subsec_nanos: u32,
694 ) -> (Self::Output, u64, u32) {
695 self.lock()
696 .unwrap_or_else(|err| err.into_inner())
697 .generate_timestamp_sequence(seconds, subsec_nanos)
698 }
699
700 fn usable_bits(&self) -> usize
701 where
702 Self::Output: Sized,
703 {
704 self.lock()
705 .unwrap_or_else(|err| err.into_inner())
706 .usable_bits()
707 }
708 }
709 }
710
711 #[cfg(feature = "std")]
712 pub use std_support::*;
713
714 #[cfg(feature = "v7")]
715 mod v7_support {
716 use super::*;
717
718 use core::{cell::Cell, cmp, panic::RefUnwindSafe};
719
720 #[cfg(feature = "std")]
721 static CONTEXT_V7: SharedContextV7 =
722 SharedContextV7(std::sync::Mutex::new(ContextV7::new()));
723
724 #[cfg(feature = "std")]
725 pub(crate) fn shared_context_v7() -> &'static SharedContextV7 {
726 &CONTEXT_V7
727 }
728
729 const USABLE_BITS: usize = 42;
730
731 const RESEED_MASK: u64 = u64::MAX >> 23;
736 const MAX_COUNTER: u64 = u64::MAX >> 22;
737
738 #[derive(Debug)]
764 pub struct ContextV7 {
765 timestamp: Cell<ReseedingTimestamp>,
766 counter: Cell<Counter>,
767 adjust: Adjust,
768 precision: Precision,
769 }
770
771 impl RefUnwindSafe for ContextV7 {}
772
773 impl ContextV7 {
774 pub const fn new() -> Self {
777 ContextV7 {
778 timestamp: Cell::new(ReseedingTimestamp {
779 last_seed: 0,
780 seconds: 0,
781 subsec_nanos: 0,
782 }),
783 counter: Cell::new(Counter { value: 0 }),
784 adjust: Adjust { by_ns: 0 },
785 precision: Precision {
786 bits: 0,
787 mask: 0,
788 factor: 0,
789 shift: 0,
790 },
791 }
792 }
793
794 pub fn with_adjust_by_millis(mut self, millis: u32) -> Self {
796 self.adjust = Adjust::by_millis(millis);
797 self
798 }
799
800 pub fn with_additional_precision(self) -> Self {
807 self.with_additional_precision_bits(12)
808 }
809
810 pub fn with_additional_precision_bits(mut self, bits: usize) -> Self {
820 self.precision = Precision::new(cmp::min(bits, 12));
821 self
822 }
823 }
824
825 impl ClockSequence for ContextV7 {
826 type Output = u64;
827
828 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
829 self.generate_timestamp_sequence(seconds, subsec_nanos).0
830 }
831
832 fn generate_timestamp_sequence(
833 &self,
834 seconds: u64,
835 subsec_nanos: u32,
836 ) -> (Self::Output, u64, u32) {
837 let (seconds, subsec_nanos) = self.adjust.apply(seconds, subsec_nanos);
838
839 let mut counter;
840 let (mut timestamp, should_reseed) =
841 self.timestamp.get().advance(seconds, subsec_nanos);
842
843 if should_reseed {
844 counter = Counter::reseed(&self.precision, ×tamp);
846 } else {
847 counter = self.counter.get().increment(&self.precision, ×tamp);
854
855 if counter.has_overflowed() {
859 timestamp = timestamp.increment();
861 counter = Counter::reseed(&self.precision, ×tamp);
862 }
863 };
864
865 self.timestamp.set(timestamp);
866 self.counter.set(counter);
867
868 (counter.value, timestamp.seconds, timestamp.subsec_nanos)
869 }
870
871 fn usable_bits(&self) -> usize {
872 USABLE_BITS
873 }
874 }
875
876 #[derive(Debug, Default, Clone, Copy)]
878 struct ReseedingTimestamp {
879 last_seed: u64,
880 seconds: u64,
881 subsec_nanos: u32,
882 }
883
884 impl ReseedingTimestamp {
885 #[inline]
886 fn from_ts(seconds: u64, subsec_nanos: u32) -> Self {
887 let last_seed = seconds
889 .saturating_mul(1_000)
890 .saturating_add((subsec_nanos / 1_000_000) as u64);
891
892 ReseedingTimestamp {
893 last_seed,
894 seconds,
895 subsec_nanos,
896 }
897 }
898
899 #[inline]
901 fn advance(&self, seconds: u64, subsec_nanos: u32) -> (Self, bool) {
902 let incoming = ReseedingTimestamp::from_ts(seconds, subsec_nanos);
903
904 if incoming.last_seed > self.last_seed {
905 (incoming, true)
907 } else {
908 let mut value = *self;
911 value.subsec_nanos = cmp::max(self.subsec_nanos, subsec_nanos);
912
913 (value, false)
914 }
915 }
916
917 #[inline]
919 fn increment(&self) -> Self {
920 let (seconds, subsec_nanos) =
921 Adjust::by_millis(1).apply(self.seconds, self.subsec_nanos);
922
923 ReseedingTimestamp::from_ts(seconds, subsec_nanos)
924 }
925
926 #[inline]
927 fn submilli_nanos(&self) -> u32 {
928 self.subsec_nanos % 1_000_000
929 }
930 }
931
932 #[derive(Debug, Clone, Copy)]
934 struct Counter {
935 value: u64,
936 }
937
938 impl Counter {
939 #[inline]
940 fn reseed(precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
941 Counter {
942 value: precision.apply(crate::rng::u64() & RESEED_MASK, timestamp),
943 }
944 }
945
946 #[inline]
948 fn increment(&self, precision: &Precision, timestamp: &ReseedingTimestamp) -> Self {
949 let mut counter = Counter {
950 value: precision.apply(self.value, timestamp),
951 };
952
953 counter.value += 1;
960
961 counter
962 }
963
964 #[inline]
965 fn has_overflowed(&self) -> bool {
966 self.value > MAX_COUNTER
967 }
968 }
969
970 #[derive(Debug)]
972 struct Adjust {
973 by_ns: u128,
974 }
975
976 impl Adjust {
977 #[inline]
978 fn by_millis(millis: u32) -> Self {
979 Adjust {
980 by_ns: (millis as u128).saturating_mul(1_000_000),
981 }
982 }
983
984 #[inline]
986 fn apply(&self, seconds: u64, subsec_nanos: u32) -> (u64, u32) {
987 if self.by_ns == 0 {
988 return (seconds, subsec_nanos);
990 }
991
992 let ts = (seconds as u128)
993 .saturating_mul(1_000_000_000)
994 .saturating_add(subsec_nanos as u128)
995 .saturating_add(self.by_ns);
996
997 ((ts / 1_000_000_000) as u64, (ts % 1_000_000_000) as u32)
998 }
999 }
1000
1001 #[derive(Debug)]
1003 struct Precision {
1004 bits: usize,
1005 factor: u64,
1006 mask: u64,
1007 shift: u64,
1008 }
1009
1010 impl Precision {
1011 fn new(bits: usize) -> Self {
1012 let mask = u64::MAX >> (64 - USABLE_BITS + bits);
1015 let shift = (USABLE_BITS - bits) as u64;
1016
1017 let factor = (999_999 / u64::pow(2, bits as u32)) + 1;
1020
1021 Precision {
1022 bits,
1023 factor,
1024 mask,
1025 shift,
1026 }
1027 }
1028
1029 #[inline]
1031 fn apply(&self, counter: u64, timestamp: &ReseedingTimestamp) -> u64 {
1032 if self.bits == 0 {
1033 return counter;
1035 }
1036
1037 let additional = timestamp.submilli_nanos() as u64 / self.factor;
1038
1039 (counter & self.mask) | (additional << self.shift)
1040 }
1041 }
1042
1043 #[cfg(feature = "std")]
1044 pub(crate) struct SharedContextV7(std::sync::Mutex<ContextV7>);
1045
1046 #[cfg(feature = "std")]
1047 impl ClockSequence for SharedContextV7 {
1048 type Output = u64;
1049
1050 fn generate_sequence(&self, seconds: u64, subsec_nanos: u32) -> Self::Output {
1051 self.0.generate_sequence(seconds, subsec_nanos)
1052 }
1053
1054 fn generate_timestamp_sequence(
1055 &self,
1056 seconds: u64,
1057 subsec_nanos: u32,
1058 ) -> (Self::Output, u64, u32) {
1059 self.0.generate_timestamp_sequence(seconds, subsec_nanos)
1060 }
1061
1062 fn usable_bits(&self) -> usize
1063 where
1064 Self::Output: Sized,
1065 {
1066 USABLE_BITS
1067 }
1068 }
1069
1070 #[cfg(test)]
1071 mod tests {
1072 use core::time::Duration;
1073
1074 use super::*;
1075
1076 use crate::{Timestamp, Uuid};
1077
1078 #[test]
1079 fn context() {
1080 let seconds = 1_496_854_535;
1081 let subsec_nanos = 812_946_000;
1082
1083 let context = ContextV7::new();
1084
1085 let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1086 assert_eq!(42, ts1.usable_counter_bits);
1087
1088 let seconds = 1_496_854_534;
1090
1091 let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1092
1093 assert_eq!(ts1.seconds, ts2.seconds);
1096 assert_eq!(ts1.subsec_nanos, ts2.subsec_nanos);
1097 assert_eq!(ts1.counter + 1, ts2.counter);
1098
1099 let seconds = 1_496_854_536;
1101
1102 let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1103
1104 assert_ne!(ts2.counter + 1, ts3.counter);
1106 assert_ne!(0, ts3.counter);
1107 }
1108
1109 #[test]
1110 fn context_wrap() {
1111 let seconds = 1_496_854_535u64;
1112 let subsec_nanos = 812_946_000u32;
1113
1114 let context = ContextV7 {
1116 timestamp: Cell::new(ReseedingTimestamp::from_ts(seconds, subsec_nanos)),
1117 adjust: Adjust::by_millis(0),
1118 precision: Precision {
1119 bits: 0,
1120 mask: 0,
1121 factor: 0,
1122 shift: 0,
1123 },
1124 counter: Cell::new(Counter {
1125 value: u64::MAX >> 22,
1126 }),
1127 };
1128
1129 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1130
1131 let expected_ts = Duration::new(seconds, subsec_nanos) + Duration::from_millis(1);
1133 assert_eq!(expected_ts.as_secs(), ts.seconds);
1134 assert_eq!(expected_ts.subsec_nanos(), ts.subsec_nanos);
1135
1136 assert!(ts.counter < (u64::MAX >> 22) as u128);
1138 assert_ne!(0, ts.counter);
1139 }
1140
1141 #[test]
1142 fn context_shift() {
1143 let seconds = 1_496_854_535;
1144 let subsec_nanos = 812_946_000;
1145
1146 let context = ContextV7::new().with_adjust_by_millis(1);
1147
1148 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1149
1150 assert_eq!((1_496_854_535, 813_946_000), ts.to_unix());
1151 }
1152
1153 #[test]
1154 fn context_additional_precision() {
1155 let seconds = 1_496_854_535;
1156 let subsec_nanos = 812_946_000;
1157
1158 let context = ContextV7::new().with_additional_precision();
1159
1160 let ts1 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1161
1162 assert_eq!(3861, ts1.counter >> 30);
1164
1165 assert!(ts1.counter < (u64::MAX >> 22) as u128);
1166
1167 let ts2 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1169
1170 assert!(Uuid::new_v7(ts2) > Uuid::new_v7(ts1));
1171
1172 let subsec_nanos = subsec_nanos + 1;
1174
1175 let ts3 = Timestamp::from_unix(&context, seconds, subsec_nanos);
1176
1177 assert!(Uuid::new_v7(ts3) > Uuid::new_v7(ts2));
1178 }
1179
1180 #[test]
1181 fn context_additional_precision_bits() {
1182 let seconds = 1_496_854_535;
1183 let subsec_nanos = 812_946_000;
1184
1185 let context = ContextV7::new().with_additional_precision_bits(10);
1188
1189 let ts = Timestamp::from_unix(&context, seconds, subsec_nanos);
1190
1191 assert_eq!(968, ts.counter >> 32);
1194
1195 assert!(ts.counter < (u64::MAX >> 22) as u128);
1196
1197 let full = Timestamp::from_unix(
1199 &ContextV7::new().with_additional_precision(),
1200 seconds,
1201 subsec_nanos,
1202 );
1203 let bits12 = Timestamp::from_unix(
1204 &ContextV7::new().with_additional_precision_bits(12),
1205 seconds,
1206 subsec_nanos,
1207 );
1208 assert_eq!(full.counter >> 30, bits12.counter >> 30);
1209
1210 let capped = Timestamp::from_unix(
1212 &ContextV7::new().with_additional_precision_bits(64),
1213 seconds,
1214 subsec_nanos,
1215 );
1216 assert_eq!(bits12.counter >> 30, capped.counter >> 30);
1217
1218 let none = ContextV7::new().with_additional_precision_bits(0);
1220 assert_eq!(0, none.precision.bits);
1221 }
1222
1223 #[test]
1224 fn context_overflow() {
1225 let seconds = u64::MAX;
1226 let subsec_nanos = u32::MAX;
1227
1228 for context in [
1230 ContextV7::new(),
1231 ContextV7::new().with_additional_precision(),
1232 ContextV7::new().with_adjust_by_millis(u32::MAX),
1233 ] {
1234 Timestamp::from_unix(&context, seconds, subsec_nanos);
1235 }
1236 }
1237 }
1238 }
1239
1240 #[cfg(feature = "v7")]
1241 pub use v7_support::*;
1242
1243 #[derive(Debug, Clone, Copy, Default)]
1254 pub struct NoContext;
1255
1256 impl ClockSequence for NoContext {
1257 type Output = u16;
1258
1259 fn generate_sequence(&self, _seconds: u64, _nanos: u32) -> Self::Output {
1260 0
1261 }
1262
1263 fn usable_bits(&self) -> usize {
1264 0
1265 }
1266 }
1267}
1268
1269#[cfg(all(test, any(feature = "v1", feature = "v6")))]
1270mod tests {
1271 use super::*;
1272
1273 #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))]
1274 use wasm_bindgen_test::*;
1275
1276 #[test]
1277 #[cfg_attr(
1278 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1279 wasm_bindgen_test
1280 )]
1281 fn gregorian_unix_does_not_panic() {
1282 Timestamp::unix_to_gregorian_ticks(u64::MAX, 0);
1284 Timestamp::unix_to_gregorian_ticks(0, u32::MAX);
1285 Timestamp::unix_to_gregorian_ticks(u64::MAX, u32::MAX);
1286
1287 Timestamp::gregorian_to_unix(u64::MAX);
1288 }
1289
1290 #[test]
1291 #[cfg_attr(
1292 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1293 wasm_bindgen_test
1294 )]
1295 fn to_gregorian_truncates_to_usable_bits() {
1296 let ts = Timestamp::from_gregorian_time(123, u16::MAX);
1297
1298 assert_eq!((123, u16::MAX >> 2), ts.to_gregorian());
1299 }
1300
1301 #[test]
1302 #[cfg_attr(
1303 all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")),
1304 wasm_bindgen_test
1305 )]
1306 fn clock_sequence_usable_bits() {
1307 struct MyContext;
1308
1309 impl ClockSequence for MyContext {
1310 type Output = u16;
1311
1312 fn generate_sequence(&self, _: u64, _: u32) -> Self::Output {
1313 0
1314 }
1315 }
1316
1317 assert_eq!(16, MyContext.usable_bits());
1318 }
1319
1320 #[cfg(all(test, feature = "std", not(miri)))]
1321 mod std_support {
1322 use super::*;
1323
1324 use std::time::{Duration, SystemTime};
1325
1326 const KNOWN_SECONDS: u64 = 1_501_520_400;
1328 const KNOWN_NANOS: u32 = 1_000;
1329
1330 fn known_system_time() -> SystemTime {
1331 SystemTime::UNIX_EPOCH
1332 .checked_add(Duration::new(KNOWN_SECONDS, KNOWN_NANOS))
1333 .unwrap()
1334 }
1335
1336 fn known_timestamp() -> Timestamp {
1337 Timestamp::from_unix_time(KNOWN_SECONDS, KNOWN_NANOS, 0, 0)
1338 }
1339
1340 #[test]
1341 fn to_system_time() {
1342 let st: SystemTime = known_timestamp().into();
1343
1344 assert_eq!(known_system_time(), st);
1345 }
1346
1347 #[test]
1348 fn from_system_time() {
1349 let ts: Timestamp = known_system_time().try_into().unwrap();
1350
1351 assert_eq!(known_timestamp(), ts);
1352 }
1353
1354 #[test]
1355 fn from_system_time_before_epoch() {
1356 let before_epoch = match SystemTime::UNIX_EPOCH.checked_sub(Duration::from_nanos(1_000))
1357 {
1358 Some(st) => st,
1359 None => return,
1360 };
1361
1362 Timestamp::try_from(before_epoch)
1363 .expect_err("Timestamp should not be created from before epoch");
1364 }
1365
1366 #[test]
1367 fn from_system_time_max() {
1368 let ts = Timestamp::from_unix_time(u64::MAX, 999_999_999, 0, 0);
1369
1370 let _: SystemTime = ts.into();
1372 }
1373 }
1374}