mirror of
https://github.com/uuid-rs/uuid.git
synced 2025-10-02 15:24:57 +00:00
shift some more code around
This commit is contained in:
parent
c31ddafb29
commit
c60dd9404a
@ -7,7 +7,7 @@
|
|||||||
fn generate_sortable_uuid() {
|
fn generate_sortable_uuid() {
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
let uuid = Uuid::new_v7(uuid::Timestamp::now(uuid::NoContext));
|
let uuid = Uuid::now_v7();
|
||||||
|
|
||||||
assert_eq!(Some(uuid::Version::SortRand), uuid.get_version());
|
assert_eq!(Some(uuid::Version::SortRand), uuid.get_version());
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
//!
|
//!
|
||||||
//! [`Uuid`]: ../struct.Uuid.html
|
//! [`Uuid`]: ../struct.Uuid.html
|
||||||
|
|
||||||
use crate::{error::*, Bytes, Uuid, Variant, Version};
|
use crate::{error::*, timestamp, Bytes, Uuid, Variant, Version};
|
||||||
|
|
||||||
/// A builder struct for creating a UUID.
|
/// A builder struct for creating a UUID.
|
||||||
///
|
///
|
||||||
@ -43,12 +43,14 @@ use crate::{error::*, Bytes, Uuid, Variant, Version};
|
|||||||
pub struct Builder(Uuid);
|
pub struct Builder(Uuid);
|
||||||
|
|
||||||
impl Uuid {
|
impl Uuid {
|
||||||
/// The 'nil UUID'.
|
/// The 'nil UUID' (all zeros).
|
||||||
///
|
///
|
||||||
/// The nil UUID is a special form of UUID that is specified to have all
|
/// The nil UUID is a special form of UUID that is specified to have all
|
||||||
/// 128 bits set to zero, as defined in [IETF RFC 4122 Section 4.1.7][RFC].
|
/// 128 bits set to zero.
|
||||||
///
|
///
|
||||||
/// [RFC]: https://tools.ietf.org/html/rfc4122.html#section-4.1.7
|
/// # References
|
||||||
|
///
|
||||||
|
/// * [Nil UUID in RFC4122]: https://tools.ietf.org/html/rfc4122.html#section-4.1.7
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@ -67,12 +69,14 @@ impl Uuid {
|
|||||||
Uuid::from_bytes([0; 16])
|
Uuid::from_bytes([0; 16])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The 'max UUID'.
|
/// The 'max UUID' (all ones).
|
||||||
///
|
///
|
||||||
/// The max UUID is a special form of UUID that is specified to have all
|
/// The max UUID is a special form of UUID that is specified to have all
|
||||||
/// 128 bits set to one, as defined in [IETF RFC 4122 Update Section 5.4][Draft RFC].
|
/// 128 bits set to one.
|
||||||
///
|
///
|
||||||
/// [Draft RFC]: https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#page-12
|
/// # References
|
||||||
|
///
|
||||||
|
/// * [Max UUID in Draft RFC: New UUID Formats, Version 4]: https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-5.4
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@ -141,6 +145,8 @@ impl Uuid {
|
|||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use uuid::Uuid;
|
/// # use uuid::Uuid;
|
||||||
/// let d1 = 0xa1a2a3a4;
|
/// let d1 = 0xa1a2a3a4;
|
||||||
@ -539,7 +545,7 @@ impl Builder {
|
|||||||
|
|
||||||
/// Creates a `Builder` for a version 1 UUID using the supplied timestamp and node id.
|
/// Creates a `Builder` for a version 1 UUID using the supplied timestamp and node id.
|
||||||
pub const fn from_rfc4122_timestamp(ticks: u64, counter: u16, node_id: &[u8; 6]) -> Self {
|
pub const fn from_rfc4122_timestamp(ticks: u64, counter: u16, node_id: &[u8; 6]) -> Self {
|
||||||
Builder(crate::v1::encode_rfc4122_timestamp(ticks, counter, node_id))
|
Builder(timestamp::encode_rfc4122_timestamp(ticks, counter, node_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `Builder` for a version 3 UUID using the supplied MD5 hashed bytes.
|
/// Creates a `Builder` for a version 3 UUID using the supplied MD5 hashed bytes.
|
||||||
@ -574,9 +580,9 @@ impl Builder {
|
|||||||
.with_version(Version::Random)
|
.with_version(Version::Random)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `Builder` for a version 5 UUID using the supplied SHA1 hashed bytes.
|
/// Creates a `Builder` for a version 5 UUID using the supplied SHA-1 hashed bytes.
|
||||||
///
|
///
|
||||||
/// This method assumes the bytes are already a SHA1 hash, it will only set the appropriate
|
/// This method assumes the bytes are already a SHA-1 hash, it will only set the appropriate
|
||||||
/// bits for the UUID version and variant.
|
/// bits for the UUID version and variant.
|
||||||
pub const fn from_sha1_bytes(sha1_bytes: Bytes) -> Self {
|
pub const fn from_sha1_bytes(sha1_bytes: Bytes) -> Self {
|
||||||
Builder(Uuid::from_bytes(sha1_bytes))
|
Builder(Uuid::from_bytes(sha1_bytes))
|
||||||
@ -592,22 +598,21 @@ impl Builder {
|
|||||||
counter: u16,
|
counter: u16,
|
||||||
node_id: &[u8; 6],
|
node_id: &[u8; 6],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Builder(crate::v6::encode_sorted_rfc4122_timestamp(
|
Builder(timestamp::encode_sorted_rfc4122_timestamp(
|
||||||
ticks, counter, node_id,
|
ticks, counter, node_id,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `Builder` for a version 7 UUID using the supplied Unix timestamp.
|
/// Creates a `Builder` for a version 7 UUID using the supplied Unix timestamp and random bytes.
|
||||||
///
|
///
|
||||||
/// This method will encode the duration since the Unix epoch at millisecond precision, filling
|
/// This method assumes the bytes are already sufficiently random.
|
||||||
/// the rest with data from the given random bytes. This method assumes the bytes are already
|
|
||||||
/// sufficiently random.
|
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Creating a UUID using the current system timestamp:
|
/// Creating a UUID using the current system timestamp:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
/// # use std::convert::TryInto;
|
||||||
/// use std::time::{Duration, SystemTime};
|
/// use std::time::{Duration, SystemTime};
|
||||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
/// # use uuid::{Builder, Uuid, Variant, Version, Timestamp, NoContext};
|
/// # use uuid::{Builder, Uuid, Variant, Version, Timestamp, NoContext};
|
||||||
@ -618,7 +623,7 @@ impl Builder {
|
|||||||
///
|
///
|
||||||
/// let random_bytes = rng();
|
/// let random_bytes = rng();
|
||||||
///
|
///
|
||||||
/// let uuid = Builder::from_unix_timestamp(ts.as_secs(), ts.subsec_millis(), &random_bytes).into_uuid();
|
/// let uuid = Builder::from_unix_timestamp(ts.as_millis().try_into()?, &random_bytes).into_uuid();
|
||||||
///
|
///
|
||||||
/// assert_eq!(Some(Version::SortRand), uuid.get_version());
|
/// assert_eq!(Some(Version::SortRand), uuid.get_version());
|
||||||
/// assert_eq!(Variant::RFC4122, uuid.get_variant());
|
/// assert_eq!(Variant::RFC4122, uuid.get_variant());
|
||||||
@ -626,7 +631,7 @@ impl Builder {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn from_unix_timestamp_millis(millis: u64, random_bytes: &[u8; 10]) -> Self {
|
pub const fn from_unix_timestamp_millis(millis: u64, random_bytes: &[u8; 10]) -> Self {
|
||||||
Builder(crate::v7::encode_unix_timestamp_millis(
|
Builder(timestamp::encode_unix_timestamp_millis(
|
||||||
millis,
|
millis,
|
||||||
random_bytes,
|
random_bytes,
|
||||||
))
|
))
|
||||||
|
11
src/lib.rs
11
src/lib.rs
@ -31,7 +31,7 @@
|
|||||||
//! be extremely unlikely.
|
//! be extremely unlikely.
|
||||||
//!
|
//!
|
||||||
//! UUIDs have a number of standardized encodings that are specified in [RFC4122](http://tools.ietf.org/html/rfc4122),
|
//! UUIDs have a number of standardized encodings that are specified in [RFC4122](http://tools.ietf.org/html/rfc4122),
|
||||||
//! with recent additions [in draft](https://github.com/uuid6/uuid6-ietf-draft).
|
//! with recent additions [in draft](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04).
|
||||||
//!
|
//!
|
||||||
//! # Getting started
|
//! # Getting started
|
||||||
//!
|
//!
|
||||||
@ -193,7 +193,7 @@
|
|||||||
//!
|
//!
|
||||||
//! * [Wikipedia: Universally Unique Identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier)
|
//! * [Wikipedia: Universally Unique Identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier)
|
||||||
//! * [RFC4122: A Universally Unique Identifier (UUID) URN Namespace](http://tools.ietf.org/html/rfc4122)
|
//! * [RFC4122: A Universally Unique Identifier (UUID) URN Namespace](http://tools.ietf.org/html/rfc4122)
|
||||||
//! * [Draft RFC: New UUID Formats](https://github.com/uuid6/uuid6-ietf-draft)
|
//! * [Draft RFC: New UUID Formats, Version 4](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04)
|
||||||
//!
|
//!
|
||||||
//! [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
|
//! [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
|
||||||
//! [`cargo-web`]: https://crates.io/crates/cargo-web
|
//! [`cargo-web`]: https://crates.io/crates/cargo-web
|
||||||
@ -264,6 +264,7 @@ mod external;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[cfg(feature = "macro-diagnostics")]
|
#[cfg(feature = "macro-diagnostics")]
|
||||||
pub extern crate private_uuid_macro_internal;
|
pub extern crate private_uuid_macro_internal;
|
||||||
@ -894,17 +895,17 @@ impl Uuid {
|
|||||||
pub const fn get_timestamp(&self) -> Option<Timestamp> {
|
pub const fn get_timestamp(&self) -> Option<Timestamp> {
|
||||||
match self.get_version() {
|
match self.get_version() {
|
||||||
Some(Version::Mac) => {
|
Some(Version::Mac) => {
|
||||||
let (ticks, counter) = v1::decode_rfc4122_timestamp(self);
|
let (ticks, counter) = timestamp::decode_rfc4122_timestamp(self);
|
||||||
|
|
||||||
Some(Timestamp::from_rfc4122(ticks, counter))
|
Some(Timestamp::from_rfc4122(ticks, counter))
|
||||||
}
|
}
|
||||||
Some(Version::SortMac) => {
|
Some(Version::SortMac) => {
|
||||||
let (ticks, counter) = v6::decode_sorted_rfc4122_timestamp(self);
|
let (ticks, counter) = timestamp::decode_sorted_rfc4122_timestamp(self);
|
||||||
|
|
||||||
Some(Timestamp::from_rfc4122(ticks, counter))
|
Some(Timestamp::from_rfc4122(ticks, counter))
|
||||||
}
|
}
|
||||||
Some(Version::SortRand) => {
|
Some(Version::SortRand) => {
|
||||||
let millis = v7::decode_unix_timestamp_millis(self);
|
let millis = timestamp::decode_unix_timestamp_millis(self);
|
||||||
|
|
||||||
let seconds = millis / 1000;
|
let seconds = millis / 1000;
|
||||||
let nanos = ((millis % 1000) * 1_000_000) as u32;
|
let nanos = ((millis % 1000) * 1_000_000) as u32;
|
||||||
|
@ -18,7 +18,7 @@ pub(crate) fn bytes() -> [u8; 16] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "v1", feature = "v6", feature = "v7"))]
|
#[cfg(any(feature = "v1", feature = "v6"))]
|
||||||
pub(crate) fn u16() -> u16 {
|
pub(crate) fn u16() -> u16 {
|
||||||
#[cfg(not(feature = "fast-rng"))]
|
#[cfg(not(feature = "fast-rng"))]
|
||||||
{
|
{
|
||||||
|
114
src/timestamp.rs
114
src/timestamp.rs
@ -18,6 +18,9 @@
|
|||||||
//! # References
|
//! # References
|
||||||
//!
|
//!
|
||||||
//! * [Timestamp in RFC4122](https://www.rfc-editor.org/rfc/rfc4122#section-4.1.4)
|
//! * [Timestamp in RFC4122](https://www.rfc-editor.org/rfc/rfc4122#section-4.1.4)
|
||||||
|
//! * [Timestamp in Draft RFC: New UUID Formats, Version 4](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-6.1)
|
||||||
|
|
||||||
|
use crate::Uuid;
|
||||||
|
|
||||||
/// The number of 100 nanosecond ticks between the RFC4122 epoch
|
/// The number of 100 nanosecond ticks between the RFC4122 epoch
|
||||||
/// (`1582-10-15 00:00:00`) and the Unix epoch (`1970-01-01 00:00:00`).
|
/// (`1582-10-15 00:00:00`) and the Unix epoch (`1970-01-01 00:00:00`).
|
||||||
@ -32,6 +35,7 @@ pub const UUID_TICKS_BETWEEN_EPOCHS: u64 = 0x01B2_1DD2_1381_4000;
|
|||||||
/// # References
|
/// # References
|
||||||
///
|
///
|
||||||
/// * [Timestamp in RFC4122](https://www.rfc-editor.org/rfc/rfc4122#section-4.1.4)
|
/// * [Timestamp in RFC4122](https://www.rfc-editor.org/rfc/rfc4122#section-4.1.4)
|
||||||
|
/// * [Timestamp in Draft RFC: New UUID Formats, Version 4](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-6.1)
|
||||||
/// * [Clock Sequence in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.5)
|
/// * [Clock Sequence in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.5)
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct Timestamp {
|
pub struct Timestamp {
|
||||||
@ -152,6 +156,116 @@ impl Timestamp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) const fn encode_rfc4122_timestamp(ticks: u64, counter: u16, node_id: &[u8; 6]) -> Uuid {
|
||||||
|
let time_low = (ticks & 0xFFFF_FFFF) as u32;
|
||||||
|
let time_mid = ((ticks >> 32) & 0xFFFF) as u16;
|
||||||
|
let time_high_and_version = (((ticks >> 48) & 0x0FFF) as u16) | (1 << 12);
|
||||||
|
|
||||||
|
let mut d4 = [0; 8];
|
||||||
|
|
||||||
|
d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
|
||||||
|
d4[1] = (counter & 0xFF) as u8;
|
||||||
|
d4[2] = node_id[0];
|
||||||
|
d4[3] = node_id[1];
|
||||||
|
d4[4] = node_id[2];
|
||||||
|
d4[5] = node_id[3];
|
||||||
|
d4[6] = node_id[4];
|
||||||
|
d4[7] = node_id[5];
|
||||||
|
|
||||||
|
Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) const fn decode_rfc4122_timestamp(uuid: &Uuid) -> (u64, u16) {
|
||||||
|
let bytes = uuid.as_bytes();
|
||||||
|
|
||||||
|
let ticks: u64 = ((bytes[6] & 0x0F) as u64) << 56
|
||||||
|
| (bytes[7] as u64) << 48
|
||||||
|
| (bytes[4] as u64) << 40
|
||||||
|
| (bytes[5] as u64) << 32
|
||||||
|
| (bytes[0] as u64) << 24
|
||||||
|
| (bytes[1] as u64) << 16
|
||||||
|
| (bytes[2] as u64) << 8
|
||||||
|
| (bytes[3] as u64);
|
||||||
|
|
||||||
|
let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
|
||||||
|
|
||||||
|
(ticks, counter)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) const fn encode_sorted_rfc4122_timestamp(
|
||||||
|
ticks: u64,
|
||||||
|
counter: u16,
|
||||||
|
node_id: &[u8; 6],
|
||||||
|
) -> Uuid {
|
||||||
|
let time_high = ((ticks >> 28) & 0xFFFF_FFFF) as u32;
|
||||||
|
let time_mid = ((ticks >> 12) & 0xFFFF) as u16;
|
||||||
|
let time_low_and_version = ((ticks & 0x0FFF) as u16) | (0x6 << 12);
|
||||||
|
|
||||||
|
let mut d4 = [0; 8];
|
||||||
|
|
||||||
|
d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
|
||||||
|
d4[1] = (counter & 0xFF) as u8;
|
||||||
|
d4[2] = node_id[0];
|
||||||
|
d4[3] = node_id[1];
|
||||||
|
d4[4] = node_id[2];
|
||||||
|
d4[5] = node_id[3];
|
||||||
|
d4[6] = node_id[4];
|
||||||
|
d4[7] = node_id[5];
|
||||||
|
|
||||||
|
Uuid::from_fields(time_high, time_mid, time_low_and_version, &d4)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) const fn decode_sorted_rfc4122_timestamp(uuid: &Uuid) -> (u64, u16) {
|
||||||
|
let bytes = uuid.as_bytes();
|
||||||
|
|
||||||
|
let ticks: u64 = ((bytes[0]) as u64) << 52
|
||||||
|
| (bytes[1] as u64) << 44
|
||||||
|
| (bytes[2] as u64) << 36
|
||||||
|
| (bytes[3] as u64) << 28
|
||||||
|
| (bytes[4] as u64) << 20
|
||||||
|
| (bytes[5] as u64) << 12
|
||||||
|
| ((bytes[6] & 0xF) as u64) << 8
|
||||||
|
| (bytes[7] as u64);
|
||||||
|
|
||||||
|
let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
|
||||||
|
|
||||||
|
(ticks, counter)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) const fn encode_unix_timestamp_millis(millis: u64, random_bytes: &[u8; 10]) -> Uuid {
|
||||||
|
let millis_high = ((millis >> 16) & 0xFFFF_FFFF) as u32;
|
||||||
|
let millis_low = (millis & 0xFFFF) as u16;
|
||||||
|
|
||||||
|
let random_and_version =
|
||||||
|
(random_bytes[0] as u16 | ((random_bytes[1] as u16) << 8) & 0x0FFF) | (0x7 << 12);
|
||||||
|
|
||||||
|
let mut d4 = [0; 8];
|
||||||
|
|
||||||
|
d4[0] = (random_bytes[2] & 0x3F) | 0x80;
|
||||||
|
d4[1] = random_bytes[3];
|
||||||
|
d4[2] = random_bytes[4];
|
||||||
|
d4[3] = random_bytes[5];
|
||||||
|
d4[4] = random_bytes[6];
|
||||||
|
d4[5] = random_bytes[7];
|
||||||
|
d4[6] = random_bytes[8];
|
||||||
|
d4[7] = random_bytes[9];
|
||||||
|
|
||||||
|
Uuid::from_fields(millis_high, millis_low, random_and_version, &d4)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) const fn decode_unix_timestamp_millis(uuid: &Uuid) -> u64 {
|
||||||
|
let bytes = uuid.as_bytes();
|
||||||
|
|
||||||
|
let millis: u64 = (bytes[0] as u64) << 40
|
||||||
|
| (bytes[1] as u64) << 32
|
||||||
|
| (bytes[2] as u64) << 24
|
||||||
|
| (bytes[3] as u64) << 16
|
||||||
|
| (bytes[4] as u64) << 8
|
||||||
|
| (bytes[5] as u64);
|
||||||
|
|
||||||
|
millis
|
||||||
|
}
|
||||||
|
|
||||||
/// A counter that can be used by version 1 and version 6 UUIDs to support
|
/// A counter that can be used by version 1 and version 6 UUIDs to support
|
||||||
/// the uniqueness of timestamps.
|
/// the uniqueness of timestamps.
|
||||||
///
|
///
|
||||||
|
54
src/v1.rs
54
src/v1.rs
@ -8,9 +8,12 @@ use crate::{timestamp::context::shared_context, Builder, Timestamp, Uuid};
|
|||||||
pub use crate::timestamp::context::Context;
|
pub use crate::timestamp::context::Context;
|
||||||
|
|
||||||
impl Uuid {
|
impl Uuid {
|
||||||
/// Create a new UUID (version 1) using the current system time and a node id.
|
/// Create a new version 1 UUID using the current system time and a node id.
|
||||||
///
|
///
|
||||||
/// This method is only available if both the `std` and `rng` features are enabled.
|
/// This method is only available if both the `std` and `rng` features are enabled.
|
||||||
|
///
|
||||||
|
/// This method is a convenient alternative to [`Uuid::new_v1`] that uses the current system time
|
||||||
|
/// as the source timestamp.
|
||||||
#[cfg(all(feature = "std", feature = "rng"))]
|
#[cfg(all(feature = "std", feature = "rng"))]
|
||||||
pub fn now_v1(node_id: &[u8; 6]) -> Self {
|
pub fn now_v1(node_id: &[u8; 6]) -> Self {
|
||||||
let ts = Timestamp::now(shared_context());
|
let ts = Timestamp::now(shared_context());
|
||||||
@ -18,7 +21,7 @@ impl Uuid {
|
|||||||
Self::new_v1(ts, node_id)
|
Self::new_v1(ts, node_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new UUID (version 1) using the given timestamp and node id.
|
/// Create a new version 1 UUID using the given timestamp and node id.
|
||||||
///
|
///
|
||||||
/// When generating [`Timestamp`]s using a [`ClockSequence`], this function
|
/// When generating [`Timestamp`]s using a [`ClockSequence`], this function
|
||||||
/// is only guaranteed to produce unique values if the following conditions
|
/// is only guaranteed to produce unique values if the following conditions
|
||||||
@ -71,17 +74,6 @@ impl Uuid {
|
|||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// The timestamp can also just use the current SystemTime
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use uuid::{Timestamp, Context};
|
|
||||||
/// # use uuid::Uuid;
|
|
||||||
/// let context = Context::new(42);
|
|
||||||
/// let ts = Timestamp::now(&context);
|
|
||||||
///
|
|
||||||
/// let _uuid = Uuid::new_v1(ts, &[1, 2, 3, 4, 5, 6]);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// # References
|
/// # References
|
||||||
///
|
///
|
||||||
/// * [Version 1 UUIDs in RFC4122](https://www.rfc-editor.org/rfc/rfc4122#section-4.2)
|
/// * [Version 1 UUIDs in RFC4122](https://www.rfc-editor.org/rfc/rfc4122#section-4.2)
|
||||||
@ -96,42 +88,6 @@ impl Uuid {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const fn encode_rfc4122_timestamp(ticks: u64, counter: u16, node_id: &[u8; 6]) -> Uuid {
|
|
||||||
let time_low = (ticks & 0xFFFF_FFFF) as u32;
|
|
||||||
let time_mid = ((ticks >> 32) & 0xFFFF) as u16;
|
|
||||||
let time_high_and_version = (((ticks >> 48) & 0x0FFF) as u16) | (1 << 12);
|
|
||||||
|
|
||||||
let mut d4 = [0; 8];
|
|
||||||
|
|
||||||
d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
|
|
||||||
d4[1] = (counter & 0xFF) as u8;
|
|
||||||
d4[2] = node_id[0];
|
|
||||||
d4[3] = node_id[1];
|
|
||||||
d4[4] = node_id[2];
|
|
||||||
d4[5] = node_id[3];
|
|
||||||
d4[6] = node_id[4];
|
|
||||||
d4[7] = node_id[5];
|
|
||||||
|
|
||||||
Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) const fn decode_rfc4122_timestamp(uuid: &Uuid) -> (u64, u16) {
|
|
||||||
let bytes = uuid.as_bytes();
|
|
||||||
|
|
||||||
let ticks: u64 = ((bytes[6] & 0x0F) as u64) << 56
|
|
||||||
| (bytes[7] as u64) << 48
|
|
||||||
| (bytes[4] as u64) << 40
|
|
||||||
| (bytes[5] as u64) << 32
|
|
||||||
| (bytes[0] as u64) << 24
|
|
||||||
| (bytes[1] as u64) << 16
|
|
||||||
| (bytes[2] as u64) << 8
|
|
||||||
| (bytes[3] as u64);
|
|
||||||
|
|
||||||
let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
|
|
||||||
|
|
||||||
(ticks, counter)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
49
src/v6.rs
49
src/v6.rs
@ -6,9 +6,12 @@
|
|||||||
use crate::{timestamp::context::shared_context, Builder, Timestamp, Uuid};
|
use crate::{timestamp::context::shared_context, Builder, Timestamp, Uuid};
|
||||||
|
|
||||||
impl Uuid {
|
impl Uuid {
|
||||||
/// Create a new UUID (version 6) using the current time value and a node id.
|
/// Create a new version 6 UUID using the current time value and a node id.
|
||||||
///
|
///
|
||||||
/// This method is only available if the `std` feature is enabled.
|
/// This method is only available if the `std` feature is enabled.
|
||||||
|
///
|
||||||
|
/// This method is a convenient alternative to [`Uuid::new_v6`] that uses the current system time
|
||||||
|
/// as the source timestamp.
|
||||||
#[cfg(all(feature = "std", feature = "rng"))]
|
#[cfg(all(feature = "std", feature = "rng"))]
|
||||||
pub fn now_v6(node_id: &[u8; 6]) -> Self {
|
pub fn now_v6(node_id: &[u8; 6]) -> Self {
|
||||||
let ts = Timestamp::now(shared_context());
|
let ts = Timestamp::now(shared_context());
|
||||||
@ -16,9 +19,9 @@ impl Uuid {
|
|||||||
Self::new_v6(ts, node_id)
|
Self::new_v6(ts, node_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new UUID (version 6) using a time value + sequence +
|
/// Create a new version 6 UUID using a time value + sequence +
|
||||||
/// *NodeId*.
|
/// *NodeId*.
|
||||||
/// This is similar to UUIDv1, except that it is lexographically sortable by timestamp.
|
/// This is similar to UUIDv1, except that it is lexicographically sortable by timestamp.
|
||||||
///
|
///
|
||||||
/// When generating [`Timestamp`]s using a [`ClockSequence`], this function
|
/// When generating [`Timestamp`]s using a [`ClockSequence`], this function
|
||||||
/// is only guaranteed to produce unique values if the following conditions
|
/// is only guaranteed to produce unique values if the following conditions
|
||||||
@ -87,46 +90,6 @@ impl Uuid {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const fn encode_sorted_rfc4122_timestamp(
|
|
||||||
ticks: u64,
|
|
||||||
counter: u16,
|
|
||||||
node_id: &[u8; 6],
|
|
||||||
) -> Uuid {
|
|
||||||
let time_high = ((ticks >> 28) & 0xFFFF_FFFF) as u32;
|
|
||||||
let time_mid = ((ticks >> 12) & 0xFFFF) as u16;
|
|
||||||
let time_low_and_version = ((ticks & 0x0FFF) as u16) | (0x6 << 12);
|
|
||||||
|
|
||||||
let mut d4 = [0; 8];
|
|
||||||
|
|
||||||
d4[0] = (((counter & 0x3F00) >> 8) as u8) | 0x80;
|
|
||||||
d4[1] = (counter & 0xFF) as u8;
|
|
||||||
d4[2] = node_id[0];
|
|
||||||
d4[3] = node_id[1];
|
|
||||||
d4[4] = node_id[2];
|
|
||||||
d4[5] = node_id[3];
|
|
||||||
d4[6] = node_id[4];
|
|
||||||
d4[7] = node_id[5];
|
|
||||||
|
|
||||||
Uuid::from_fields(time_high, time_mid, time_low_and_version, &d4)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) const fn decode_sorted_rfc4122_timestamp(uuid: &Uuid) -> (u64, u16) {
|
|
||||||
let bytes = uuid.as_bytes();
|
|
||||||
|
|
||||||
let ticks: u64 = ((bytes[0]) as u64) << 52
|
|
||||||
| (bytes[1] as u64) << 44
|
|
||||||
| (bytes[2] as u64) << 36
|
|
||||||
| (bytes[3] as u64) << 28
|
|
||||||
| (bytes[4] as u64) << 20
|
|
||||||
| (bytes[5] as u64) << 12
|
|
||||||
| ((bytes[6] & 0xF) as u64) << 8
|
|
||||||
| (bytes[7] as u64);
|
|
||||||
|
|
||||||
let counter: u16 = ((bytes[8] & 0x3F) as u16) << 8 | (bytes[9] as u16);
|
|
||||||
|
|
||||||
(ticks, counter)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
58
src/v7.rs
58
src/v7.rs
@ -7,7 +7,7 @@ use crate::{rng, timestamp::Timestamp, Builder, NoContext, Uuid};
|
|||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
|
|
||||||
impl Uuid {
|
impl Uuid {
|
||||||
/// Create a new UUID (version 7) using the current time value and random bytes.
|
/// 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
|
/// This method is a convenient alternative to [`Uuid::new_v7`] that uses the current system time
|
||||||
/// as the source timestamp.
|
/// as the source timestamp.
|
||||||
@ -16,13 +16,16 @@ impl Uuid {
|
|||||||
Self::new_v7(Timestamp::now(NoContext))
|
Self::new_v7(Timestamp::now(NoContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new UUID (version 7) using a time value and random bytes.
|
/// 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`].
|
/// 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
|
/// Note that usage of this method requires the `v7` feature of this crate
|
||||||
/// to be enabled.
|
/// to be enabled.
|
||||||
///
|
///
|
||||||
|
/// Also see [`Uuid::now_v7`] for a convenient way to generate version 7
|
||||||
|
/// UUIDs using the current system time.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// A v7 UUID can be created from a unix [`Timestamp`] plus a 128 bit
|
/// A v7 UUID can be created from a unix [`Timestamp`] plus a 128 bit
|
||||||
@ -44,67 +47,34 @@ impl Uuid {
|
|||||||
/// * [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)
|
/// * [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 {
|
pub fn new_v7(ts: Timestamp) -> Self {
|
||||||
let (secs, nanos) = ts.to_unix();
|
let (secs, nanos) = ts.to_unix();
|
||||||
let millis = secs.saturating_add(nanos as u64 / 1_000_000);
|
let millis = (secs * 1000).saturating_add(nanos as u64 / 1_000_000);
|
||||||
|
|
||||||
Builder::from_unix_timestamp_millis(millis, &rng::bytes()[..10].try_into().unwrap())
|
Builder::from_unix_timestamp_millis(millis, &rng::bytes()[..10].try_into().unwrap())
|
||||||
.into_uuid()
|
.into_uuid()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const fn encode_unix_timestamp_millis(millis: u64, random_bytes: &[u8; 10]) -> Uuid {
|
|
||||||
let millis_high = ((millis >> 16) & 0xFFFF_FFFF) as u32;
|
|
||||||
let millis_low = (millis & 0xFFFF) as u16;
|
|
||||||
|
|
||||||
let random_and_version =
|
|
||||||
(random_bytes[0] as u16 | ((random_bytes[1] as u16) << 8) & 0x0FFF) | (0x7 << 12);
|
|
||||||
|
|
||||||
let mut d4 = [0; 8];
|
|
||||||
|
|
||||||
d4[0] = (random_bytes[2] & 0x3F) | 0x80;
|
|
||||||
d4[1] = random_bytes[3];
|
|
||||||
d4[2] = random_bytes[4];
|
|
||||||
d4[3] = random_bytes[5];
|
|
||||||
d4[4] = random_bytes[6];
|
|
||||||
d4[5] = random_bytes[7];
|
|
||||||
d4[6] = random_bytes[8];
|
|
||||||
d4[7] = random_bytes[9];
|
|
||||||
|
|
||||||
Uuid::from_fields(millis_high, millis_low, random_and_version, &d4)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) const fn decode_unix_timestamp_millis(uuid: &Uuid) -> u64 {
|
|
||||||
let bytes = uuid.as_bytes();
|
|
||||||
|
|
||||||
let millis: u64 = (bytes[0] as u64) << 40
|
|
||||||
| (bytes[1] as u64) << 32
|
|
||||||
| (bytes[2] as u64) << 24
|
|
||||||
| (bytes[3] as u64) << 16
|
|
||||||
| (bytes[4] as u64) << 8
|
|
||||||
| (bytes[5] as u64);
|
|
||||||
|
|
||||||
millis
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{NoContext, Variant, Version};
|
use crate::{std::string::ToString, NoContext, Variant, Version};
|
||||||
use std::string::ToString;
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_bindgen_test::*;
|
use wasm_bindgen_test::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
|
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
|
||||||
fn test_new_v7() {
|
fn test_new_v7() {
|
||||||
let time: u64 = 1_496_854_535;
|
let ts: u64 = 1645557742000;
|
||||||
let time_fraction: u32 = 812_946_000;
|
|
||||||
|
|
||||||
let uuid = Uuid::new_v7(Timestamp::from_unix(NoContext, time, time_fraction));
|
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();
|
let uustr = uuid.hyphenated().to_string();
|
||||||
|
|
||||||
assert_eq!(uuid.get_version(), Some(Version::SortRand));
|
assert_eq!(uuid.get_version(), Some(Version::SortRand));
|
||||||
assert_eq!(uuid.get_variant(), Variant::RFC4122);
|
assert_eq!(uuid.get_variant(), Variant::RFC4122);
|
||||||
assert!(uustr.starts_with("015c837b-9e84-7"));
|
assert!(uuid.hyphenated().to_string().starts_with("017f22e2-79b0-7"));
|
||||||
|
|
||||||
// Ensure parsing the same UUID produces the same timestamp
|
// Ensure parsing the same UUID produces the same timestamp
|
||||||
let parsed = Uuid::parse_str(uustr.as_str()).unwrap();
|
let parsed = Uuid::parse_str(uustr.as_str()).unwrap();
|
||||||
@ -116,7 +86,7 @@ mod tests {
|
|||||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
|
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
|
||||||
fn test_new_v7_timestamp_roundtrip() {
|
fn test_new_v7_timestamp_roundtrip() {
|
||||||
let time: u64 = 1_496_854_535;
|
let time: u64 = 1_496_854_535;
|
||||||
let time_fraction: u32 = 812_946_000;
|
let time_fraction: u32 = 812_000_000;
|
||||||
|
|
||||||
let ts = Timestamp::from_unix(NoContext, time, time_fraction);
|
let ts = Timestamp::from_unix(NoContext, time, time_fraction);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user