Skip to main content

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}