diff options
Diffstat (limited to 'vendor/uuid/src/v7.rs')
-rw-r--r-- | vendor/uuid/src/v7.rs | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/vendor/uuid/src/v7.rs b/vendor/uuid/src/v7.rs new file mode 100644 index 000000000..4497ea3f5 --- /dev/null +++ b/vendor/uuid/src/v7.rs @@ -0,0 +1,124 @@ +//! The implementation for Version 7 UUIDs. +//! +//! Note that you need to enable the `v7` Cargo feature +//! in order to use this module. + +use crate::{std::convert::TryInto, rng, timestamp::Timestamp, Builder, Uuid}; + +impl Uuid { + /// Create a new version 7 UUID using the current time value and random bytes. + /// + /// This method is a convenient alternative to [`Uuid::new_v7`] that uses the current system time + /// as the source timestamp. + #[cfg(feature = "std")] + pub fn now_v7() -> Self { + Self::new_v7(Timestamp::now(crate::NoContext)) + } + + /// Create a new version 7 UUID using a time value and random bytes. + /// + /// When the `std` feature is enabled, you can also use [`Uuid::now_v7`]. + /// + /// Note that usage of this method requires the `v7` feature of this crate + /// to be enabled. + /// + /// Also see [`Uuid::now_v7`] for a convenient way to generate version 7 + /// UUIDs using the current system time. + /// + /// # Examples + /// + /// A v7 UUID can be created from a unix [`Timestamp`] plus a 128 bit + /// random number. When supplied as such, the data will be + /// + /// ```rust + /// # use uuid::{Uuid, Timestamp, NoContext}; + /// let ts = Timestamp::from_unix(NoContext, 1497624119, 1234); + /// + /// let uuid = Uuid::new_v7(ts); + /// + /// assert!( + /// uuid.hyphenated().to_string().starts_with("015cb15a-86d8-7") + /// ); + /// ``` + /// + /// # References + /// + /// * [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) + pub fn new_v7(ts: Timestamp) -> Self { + let (secs, nanos) = ts.to_unix(); + let millis = (secs * 1000).saturating_add(nanos as u64 / 1_000_000); + + Builder::from_unix_timestamp_millis(millis, &rng::bytes()[..10].try_into().unwrap()) + .into_uuid() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{std::string::ToString, NoContext, Variant, Version}; + #[cfg(target_arch = "wasm32")] + use wasm_bindgen_test::*; + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn test_new() { + let ts: u64 = 1645557742000; + + let seconds = ts / 1000; + let nanos = ((ts % 1000) * 1_000_000) as u32; + + let uuid = Uuid::new_v7(Timestamp::from_unix(NoContext, seconds, nanos)); + let uustr = uuid.hyphenated().to_string(); + + assert_eq!(uuid.get_version(), Some(Version::SortRand)); + assert_eq!(uuid.get_variant(), Variant::RFC4122); + assert!(uuid.hyphenated().to_string().starts_with("017f22e2-79b0-7")); + + // Ensure parsing the same UUID produces the same timestamp + let parsed = Uuid::parse_str(uustr.as_str()).unwrap(); + + assert_eq!(uuid, parsed); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + #[cfg(feature = "std")] + fn test_now() { + let uuid = Uuid::now_v7(); + + assert_eq!(uuid.get_version(), Some(Version::SortRand)); + assert_eq!(uuid.get_variant(), Variant::RFC4122); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn test_sorting() { + let time1: u64 = 1_496_854_535; + let time_fraction1: u32 = 812_000_000; + + let time2 = time1 + 4000; + let time_fraction2 = time_fraction1; + + let uuid1 = Uuid::new_v7(Timestamp::from_unix(NoContext, time1, time_fraction1)); + let uuid2 = Uuid::new_v7(Timestamp::from_unix(NoContext, time2, time_fraction2)); + + assert!(uuid1.as_bytes() < uuid2.as_bytes()); + assert!(uuid1.to_string() < uuid2.to_string()); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn test_new_timestamp_roundtrip() { + let time: u64 = 1_496_854_535; + let time_fraction: u32 = 812_000_000; + + let ts = Timestamp::from_unix(NoContext, time, time_fraction); + + let uuid = Uuid::new_v7(ts); + + let decoded_ts = uuid.get_timestamp().unwrap(); + + assert_eq!(ts.to_unix(), decoded_ts.to_unix()); + } +} |