uuid/v7.rs
1use crate::{Uuid, Version};
2
3impl Uuid {
4 /// Create a new version 7 UUID using a time value and random bytes.
5 ///
6 /// When the `std` feature is enabled, you can also use [`Uuid::new_v7`].
7 ///
8 /// Note that usage of this method requires the `v7` feature of this crate
9 /// to be enabled.
10 ///
11 /// # References
12 ///
13 /// * [Version 7 UUIDs in Draft RFC: New UUID Formats, Version 4](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-5.2)
14 pub fn new_v7() -> Uuid {
15 let now = std::time::SystemTime::UNIX_EPOCH
16 .elapsed()
17 .expect("Getting elapsed time since UNIX_EPOCH. If this fails, we've somehow violated causality");
18
19 // let now = (now.as_secs(), now.subsec_nanos());
20 return Self::new_v7_with_timestamp(now.as_millis() as u64);
21 }
22
23 pub fn new_v7_with_timestamp(unix_millis: u64) -> Self {
24 /*
25 0 1 2 3
26 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
27 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28 | unix_ts_ms |
29 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30 | unix_ts_ms | ver | rand_a (12 bit seq) |
31 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32 |var| rand_b |
33 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 | rand_b |
35 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 unix_ts_ms:
37 48 bit big-endian unsigned number of Unix epoch timestamp as per Section 6.1.
38 ver:
39 4 bit UUIDv7 version set as per Section 4
40 rand_a:
41 12 bits pseudo-random data to provide uniqueness as per Section 6.2 and Section 6.6.
42 var:
43 The 2 bit variant defined by Section 4.
44 rand_b:
45 The final 62 bits of pseudo-random data to provide uniqueness as per Section 6.2 and Section 6.6.
46 */
47
48 // // unix_high
49 // let unix_high = ((millis >> 16) & 0xFFFF_FFFF) as u32;
50 // // unix_low
51 // let unix_low = (millis & 0xFFFF) as u16;
52
53 // let unix_millis =
54 // (unix_seconds * 1000).saturating_add(nanoseconds.unwrap_or_default() as u64 / 1_000_000);
55 let mut uuid = Uuid(rand::random());
56
57 // let random_bytes: [u8; 10] = rand::random();
58 // random_and_version
59 // let d3: u16 =
60 // (uuid.0[7] as u16 | ((uuid.0[6] as u16) << 8) & 0x0FFF) | (0x7 << 12);
61
62 uuid.0[0] = (unix_millis >> 40) as u8;
63 uuid.0[1] = (unix_millis >> 32) as u8;
64 uuid.0[2] = (unix_millis >> 24) as u8;
65 uuid.0[3] = (unix_millis >> 16) as u8;
66 uuid.0[4] = (unix_millis >> 8) as u8;
67 uuid.0[5] = unix_millis as u8;
68
69 // Version: 7. 7 << 4 = 0x70
70 uuid.0[6] = (uuid.0[6] & 0x0f) | ((Version::V7 as u8) << 4);
71 // Variant: RFC4122
72 uuid.0[8] = (uuid.0[8] & 0x3F) | 0x80;
73
74 // uuid[6] = 0x70 | (0x0F & byte(s>>8))
75 // uuid[7] = byte(s)
76 // uuid.0[6] = (d3 >> 8) as u8;
77 // uuid.0[7] = d3 as u8;
78
79 return uuid;
80 }
81}