1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
//! The implementation for Version 1 UUIDs.
//!
//! This module is soft-deprecated. Instead of using the `Context` type re-exported here,
//! use the one from the crate root.
use crate::{Builder, Uuid};
#[deprecated(note = "use types from the crate root instead")]
pub use crate::{timestamp::context::Context, Timestamp};
impl Uuid {
/// Create a new version 1 UUID using the current system time and node ID.
///
/// 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.
///
/// Note that usage of this method requires the `v1`, `std`, and `rng` features of this crate
/// to be enabled.
#[cfg(all(feature = "std", feature = "rng"))]
pub fn now_v1(node_id: &[u8; 6]) -> Self {
let ts = Timestamp::now(crate::timestamp::context::shared_context());
Self::new_v1(ts, node_id)
}
/// Create a new version 1 UUID using the given timestamp and node ID.
///
/// Also see [`Uuid::now_v1`] for a convenient way to generate version 1
/// UUIDs using the current system time.
///
/// When generating [`Timestamp`]s using a [`ClockSequence`], this function
/// is only guaranteed to produce unique values if the following conditions
/// hold:
///
/// 1. The *node ID* is unique for this process,
/// 2. The *context* is shared across all threads which are generating version 1
/// UUIDs,
/// 3. The [`ClockSequence`] implementation reliably returns unique
/// clock sequences (this crate provides [`Context`] for this
/// purpose. However you can create your own [`ClockSequence`]
/// implementation, if [`Context`] does not meet your needs).
///
/// Note that usage of this method requires the `v1` feature of this crate
/// to be enabled.
///
/// # Examples
///
/// A UUID can be created from a unix [`Timestamp`] with a
/// [`ClockSequence`]. RFC4122 requires the clock sequence
/// is seeded with a random value:
///
/// ```
/// # use uuid::{Timestamp, Context};
/// # use uuid::Uuid;
/// # fn random_seed() -> u16 { 42 }
/// let context = Context::new(random_seed());
/// let ts = Timestamp::from_unix(&context, 1497624119, 1234);
///
/// let uuid = Uuid::new_v1(ts, &[1, 2, 3, 4, 5, 6]);
///
/// assert_eq!(
/// uuid.hyphenated().to_string(),
/// "f3b4958c-52a1-11e7-802a-010203040506"
/// );
/// ```
///
/// The timestamp can also be created manually as per RFC4122:
///
/// ```
/// # use uuid::{Uuid, Timestamp, Context, ClockSequence};
/// let context = Context::new(42);
/// let ts = Timestamp::from_rfc4122(14976234442241191232, context.generate_sequence(0, 0));
///
/// let uuid = Uuid::new_v1(ts, &[1, 2, 3, 4, 5, 6]);
///
/// assert_eq!(
/// uuid.hyphenated().to_string(),
/// "b2c1ad40-45e0-1fd6-802a-010203040506"
/// );
/// ```
///
/// # References
///
/// * [Version 1 UUIDs in RFC4122](https://www.rfc-editor.org/rfc/rfc4122#section-4.2)
///
/// [`Timestamp`]: v1/struct.Timestamp.html
/// [`ClockSequence`]: v1/trait.ClockSequence.html
/// [`Context`]: v1/struct.Context.html
pub fn new_v1(ts: Timestamp, node_id: &[u8; 6]) -> Self {
let (ticks, counter) = ts.to_rfc4122();
Builder::from_rfc4122_timestamp(ticks, counter, node_id).into_uuid()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{std::string::ToString, Variant, Version};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::*;
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn test_new() {
let time: u64 = 1_496_854_535;
let time_fraction: u32 = 812_946_000;
let node = [1, 2, 3, 4, 5, 6];
let context = Context::new(0);
let uuid = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
assert_eq!(uuid.get_version(), Some(Version::Mac));
assert_eq!(uuid.get_variant(), Variant::RFC4122);
assert_eq!(
uuid.hyphenated().to_string(),
"20616934-4ba2-11e7-8000-010203040506"
);
let ts = uuid.get_timestamp().unwrap().to_rfc4122();
assert_eq!(ts.0 - 0x01B2_1DD2_1381_4000, 14_968_545_358_129_460);
// 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()
);
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
#[cfg(all(feature = "std", feature = "rng"))]
fn test_now() {
let node = [1, 2, 3, 4, 5, 6];
let uuid = Uuid::now_v1(&node);
assert_eq!(uuid.get_version(), Some(Version::Mac));
assert_eq!(uuid.get_variant(), Variant::RFC4122);
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn test_new_context() {
let time: u64 = 1_496_854_535;
let time_fraction: u32 = 812_946_000;
let node = [1, 2, 3, 4, 5, 6];
// This context will wrap
let context = Context::new((u16::MAX >> 2) - 1);
let uuid1 = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
let time: u64 = 1_496_854_536;
let uuid2 = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
assert_eq!(uuid1.get_timestamp().unwrap().to_rfc4122().1, 16382);
assert_eq!(uuid2.get_timestamp().unwrap().to_rfc4122().1, 0);
let time = 1_496_854_535;
let uuid3 = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
let uuid4 = Uuid::new_v1(Timestamp::from_unix(&context, time, time_fraction), &node);
assert_eq!(uuid3.get_timestamp().unwrap().to_rfc4122().1, 1);
assert_eq!(uuid4.get_timestamp().unwrap().to_rfc4122().1, 2);
}
}