add a get_node_id method for v1 and v6 UUIDs

This commit is contained in:
KodrAus 2024-03-20 08:55:04 +10:00
parent 0f2aaaeab9
commit 17d592afb7
7 changed files with 73 additions and 14 deletions

View File

@ -184,7 +184,7 @@ pub mod compact {
#[cfg(test)]
mod tests {
use serde_derive::*;
use serde_test::{self, Configure};
use serde_test::Configure;
#[test]
fn test_serialize_compact() {

View File

@ -26,7 +26,7 @@ impl slog::Value for Uuid {
mod tests {
use crate::tests::new;
use slog::{self, crit, Drain};
use slog::{crit, Drain};
#[test]
fn test_slog_kv() {

View File

@ -877,24 +877,14 @@ impl Uuid {
}
/// If the UUID is the correct version (v1, v6, or v7) this will return
/// the timestamp and counter portion parsed from a V1 UUID.
///
/// Returns `None` if the supplied UUID is not V1.
///
/// The V1 timestamp format defined in RFC4122 specifies a 60-bit
/// integer representing the number of 100-nanosecond intervals
/// since 00:00:00.00, 15 Oct 1582.
///
/// [`Timestamp`] offers several options for converting the raw RFC4122
/// value into more commonly-used formats, such as a unix timestamp.
/// the timestamp in a version-agnostic [`Timestamp`]. For other versions
/// this will return `None`.
///
/// # Roundtripping
///
/// This method is unlikely to roundtrip a timestamp in a UUID due to the way
/// UUIDs encode timestamps. The timestamp returned from this method will be truncated to
/// 100ns precision for version 1 and 6 UUIDs, and to millisecond precision for version 7 UUIDs.
///
/// [`Timestamp`]: v1/struct.Timestamp.html
pub const fn get_timestamp(&self) -> Option<Timestamp> {
match self.get_version() {
Some(Version::Mac) => {
@ -923,6 +913,26 @@ impl Uuid {
_ => None,
}
}
/// If the UUID is the correct version (v1, or v6) this will return the
/// node value as a 6-byte array. For other versions this will return `None`.
pub const fn get_node_id(&self) -> Option<[u8; 6]> {
match self.get_version() {
Some(Version::Mac) | Some(Version::SortMac) => {
let mut node_id = [0; 6];
node_id[0] = self.0[10];
node_id[1] = self.0[11];
node_id[2] = self.0[12];
node_id[3] = self.0[13];
node_id[4] = self.0[14];
node_id[5] = self.0[15];
Some(node_id)
}
_ => None,
}
}
}
impl Default for Uuid {
@ -1251,6 +1261,43 @@ mod tests {
assert_eq!(uuid.get_version_num(), 3);
}
#[test]
#[cfg_attr(
all(
target_arch = "wasm32",
target_vendor = "unknown",
target_os = "unknown"
),
wasm_bindgen_test
)]
fn test_get_timestamp_unsupported_version() {
let uuid = new();
assert_ne!(Version::Mac, uuid.get_version().unwrap());
assert_ne!(Version::SortMac, uuid.get_version().unwrap());
assert_ne!(Version::SortRand, uuid.get_version().unwrap());
assert!(uuid.get_timestamp().is_none());
}
#[test]
#[cfg_attr(
all(
target_arch = "wasm32",
target_vendor = "unknown",
target_os = "unknown"
),
wasm_bindgen_test
)]
fn test_get_node_id_unsupported_version() {
let uuid = new();
assert_ne!(Version::Mac, uuid.get_version().unwrap());
assert_ne!(Version::SortMac, uuid.get_version().unwrap());
assert!(uuid.get_node_id().is_none());
}
#[test]
#[cfg_attr(
all(

View File

@ -151,6 +151,7 @@ const fn try_parse(input: &[u8]) -> Result<[u8; 16], InvalidUuid> {
}
#[inline]
#[allow(dead_code)]
pub(crate) const fn parse_braced(input: &[u8]) -> Result<[u8; 16], InvalidUuid> {
if let (38, [b'{', s @ .., b'}']) = (input.len(), input) {
parse_hyphenated(s)
@ -160,6 +161,7 @@ pub(crate) const fn parse_braced(input: &[u8]) -> Result<[u8; 16], InvalidUuid>
}
#[inline]
#[allow(dead_code)]
pub(crate) const fn parse_urn(input: &[u8]) -> Result<[u8; 16], InvalidUuid> {
if let (45, [b'u', b'r', b'n', b':', b'u', b'u', b'i', b'd', b':', s @ ..]) =
(input.len(), input)

View File

@ -135,6 +135,8 @@ mod tests {
assert_eq!(ts.0 - 0x01B2_1DD2_1381_4000, 14_968_545_358_129_460);
assert_eq!(Some(node), uuid.get_node_id(),);
// Ensure parsing the same UUID produces the same timestamp
let parsed = Uuid::parse_str("20616934-4ba2-11e7-8000-010203040506").unwrap();
@ -142,6 +144,8 @@ mod tests {
uuid.get_timestamp().unwrap(),
parsed.get_timestamp().unwrap()
);
assert_eq!(uuid.get_node_id().unwrap(), parsed.get_node_id().unwrap(),);
}
#[test]

View File

@ -137,6 +137,8 @@ mod tests {
assert_eq!(ts.0 - 0x01B2_1DD2_1381_4000, 14_968_545_358_129_460);
assert_eq!(Some(node), uuid.get_node_id(),);
// Ensure parsing the same UUID produces the same timestamp
let parsed = Uuid::parse_str("1e74ba22-0616-6934-8000-010203040506").unwrap();
@ -144,6 +146,8 @@ mod tests {
uuid.get_timestamp().unwrap(),
parsed.get_timestamp().unwrap()
);
assert_eq!(uuid.get_node_id().unwrap(), parsed.get_node_id().unwrap(),);
}
#[test]

View File

@ -1,3 +1,5 @@
#![allow(non_snake_case)]
use uuid::{uuid, Uuid};
fn Ok() {}