Skip to content

Commit

Permalink
Merge pull request #748 from uuid-rs/feat/get_node_id
Browse files Browse the repository at this point in the history
Add a get_node_id method for v1 and v6 UUIDs
  • Loading branch information
KodrAus committed Mar 20, 2024
2 parents 0f2aaae + 632d770 commit 1d123ec
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 16 deletions.
2 changes: 1 addition & 1 deletion macros/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl<'a> InvalidUuid<'a> {
group_bounds[hyphen_count] = index;
}
hyphen_count += 1;
} else if !matches!(byte, b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F') {
} else if !byte.is_ascii_hexdigit() {
// Non-hex char
return Error(ErrorKind::Char {
character: byte as char,
Expand Down
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl<'a> InvalidUuid<'a> {
group_bounds[hyphen_count] = index;
}
hyphen_count += 1;
} else if !matches!(byte, b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F') {
} else if !byte.is_ascii_hexdigit() {
// Non-hex char
return Error(ErrorKind::Char {
character: byte as char,
Expand Down
2 changes: 1 addition & 1 deletion src/external/serde_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion src/external/slog_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
72 changes: 60 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@

#![no_std]
#![deny(missing_debug_implementations, missing_docs)]
#![allow(clippy::mixed_attributes_style)]
#![doc(
html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
Expand Down Expand Up @@ -877,24 +878,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) => {
Expand Down Expand Up @@ -923,6 +914,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 {
Expand Down Expand Up @@ -1251,6 +1262,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(
Expand Down
2 changes: 2 additions & 0 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions src/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,17 @@ 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();

assert_eq!(
uuid.get_timestamp().unwrap(),
parsed.get_timestamp().unwrap()
);

assert_eq!(uuid.get_node_id().unwrap(), parsed.get_node_id().unwrap(),);
}

#[test]
Expand Down
4 changes: 4 additions & 0 deletions src/v6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,17 @@ 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();

assert_eq!(
uuid.get_timestamp().unwrap(),
parsed.get_timestamp().unwrap()
);

assert_eq!(uuid.get_node_id().unwrap(), parsed.get_node_id().unwrap(),);
}

#[test]
Expand Down
2 changes: 2 additions & 0 deletions tests/ui/compile_pass/hygiene.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![allow(non_snake_case)]

use uuid::{uuid, Uuid};

fn Ok() {}
Expand Down

0 comments on commit 1d123ec

Please sign in to comment.