| // Copyright 2013-2014 The Rust Project Developers. | |
| // Copyright 2018 The Uuid Project Developers. | |
| // | |
| // See the COPYRIGHT file at the top-level directory of this distribution. | |
| // | |
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
| // option. This file may not be copied, modified, or distributed | |
| // except according to those terms. | |
| //! A Builder type for [`Uuid`]s. | |
| //! | |
| //! [`Uuid`]: ../struct.Uuid.html | |
| mod error; | |
| pub(crate) use self::error::Error; | |
| use crate::prelude::*; | |
| impl Uuid { | |
| /// The 'nil UUID'. | |
| /// | |
| /// The nil UUID is 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]. | |
| /// | |
| /// [RFC]: https://tools.ietf.org/html/rfc4122.html#section-4.1.7 | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage: | |
| /// | |
| /// ``` | |
| /// use uuid::Uuid; | |
| /// | |
| /// let uuid = Uuid::nil(); | |
| /// | |
| /// assert_eq!( | |
| /// uuid.to_hyphenated().to_string(), | |
| /// "00000000-0000-0000-0000-000000000000" | |
| /// ); | |
| /// ``` | |
| pub const fn nil() -> Self { | |
| Uuid::from_bytes([0; 16]) | |
| } | |
| /// Creates a UUID from four field values in big-endian order. | |
| /// | |
| /// # Errors | |
| /// | |
| /// This function will return an error if `d4`'s length is not 8 bytes. | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage: | |
| /// | |
| /// ``` | |
| /// use uuid::Uuid; | |
| /// | |
| /// let d4 = [12, 3, 9, 56, 54, 43, 8, 9]; | |
| /// | |
| /// let uuid = Uuid::from_fields(42, 12, 5, &d4); | |
| /// let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string()); | |
| /// | |
| /// let expected_uuid = | |
| /// Ok(String::from("0000002a-000c-0005-0c03-0938362b0809")); | |
| /// | |
| /// assert_eq!(expected_uuid, uuid); | |
| /// ``` | |
| pub fn from_fields( | |
| d1: u32, | |
| d2: u16, | |
| d3: u16, | |
| d4: &[u8], | |
| ) -> Result<Uuid, crate::Error> { | |
| const D4_LEN: usize = 8; | |
| let len = d4.len(); | |
| if len != D4_LEN { | |
| Err(Error::new(D4_LEN, len))?; | |
| } | |
| Ok(Uuid::from_bytes([ | |
| (d1 >> 24) as u8, | |
| (d1 >> 16) as u8, | |
| (d1 >> 8) as u8, | |
| d1 as u8, | |
| (d2 >> 8) as u8, | |
| d2 as u8, | |
| (d3 >> 8) as u8, | |
| d3 as u8, | |
| d4[0], | |
| d4[1], | |
| d4[2], | |
| d4[3], | |
| d4[4], | |
| d4[5], | |
| d4[6], | |
| d4[7], | |
| ])) | |
| } | |
| /// Creates a UUID from four field values in little-endian order. | |
| /// | |
| /// The bytes in the `d1`, `d2` and `d3` fields will | |
| /// be converted into big-endian order. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use uuid::Uuid; | |
| /// | |
| /// let d1 = 0xAB3F1097u32; | |
| /// let d2 = 0x501Eu16; | |
| /// let d3 = 0xB736u16; | |
| /// let d4 = [12, 3, 9, 56, 54, 43, 8, 9]; | |
| /// | |
| /// let uuid = Uuid::from_fields_le(d1, d2, d3, &d4); | |
| /// let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string()); | |
| /// | |
| /// let expected_uuid = | |
| /// Ok(String::from("97103fab-1e50-36b7-0c03-0938362b0809")); | |
| /// | |
| /// assert_eq!(expected_uuid, uuid); | |
| /// ``` | |
| pub fn from_fields_le( | |
| d1: u32, | |
| d2: u16, | |
| d3: u16, | |
| d4: &[u8], | |
| ) -> Result<Uuid, crate::Error> { | |
| const D4_LEN: usize = 8; | |
| let len = d4.len(); | |
| if len != D4_LEN { | |
| Err(Error::new(D4_LEN, len))?; | |
| } | |
| Ok(Uuid::from_bytes([ | |
| d1 as u8, | |
| (d1 >> 8) as u8, | |
| (d1 >> 16) as u8, | |
| (d1 >> 24) as u8, | |
| (d2) as u8, | |
| (d2 >> 8) as u8, | |
| d3 as u8, | |
| (d3 >> 8) as u8, | |
| d4[0], | |
| d4[1], | |
| d4[2], | |
| d4[3], | |
| d4[4], | |
| d4[5], | |
| d4[6], | |
| d4[7], | |
| ])) | |
| } | |
| /// Creates a UUID from a 128bit value in big-endian order. | |
| pub const fn from_u128(v: u128) -> Self { | |
| Uuid::from_bytes([ | |
| (v >> 120) as u8, | |
| (v >> 112) as u8, | |
| (v >> 104) as u8, | |
| (v >> 96) as u8, | |
| (v >> 88) as u8, | |
| (v >> 80) as u8, | |
| (v >> 72) as u8, | |
| (v >> 64) as u8, | |
| (v >> 56) as u8, | |
| (v >> 48) as u8, | |
| (v >> 40) as u8, | |
| (v >> 32) as u8, | |
| (v >> 24) as u8, | |
| (v >> 16) as u8, | |
| (v >> 8) as u8, | |
| v as u8, | |
| ]) | |
| } | |
| /// Creates a UUID from a 128bit value in little-endian order. | |
| pub const fn from_u128_le(v: u128) -> Self { | |
| Uuid::from_bytes([ | |
| v as u8, | |
| (v >> 8) as u8, | |
| (v >> 16) as u8, | |
| (v >> 24) as u8, | |
| (v >> 32) as u8, | |
| (v >> 40) as u8, | |
| (v >> 48) as u8, | |
| (v >> 56) as u8, | |
| (v >> 64) as u8, | |
| (v >> 72) as u8, | |
| (v >> 80) as u8, | |
| (v >> 88) as u8, | |
| (v >> 96) as u8, | |
| (v >> 104) as u8, | |
| (v >> 112) as u8, | |
| (v >> 120) as u8, | |
| ]) | |
| } | |
| /// Creates a UUID using the supplied big-endian bytes. | |
| /// | |
| /// # Errors | |
| /// | |
| /// This function will return an error if `b` has any length other than 16. | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage: | |
| /// | |
| /// ``` | |
| /// use uuid::Uuid; | |
| /// | |
| /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76, 32, 50, 87, 5, 1, 33, 43, 87]; | |
| /// | |
| /// let uuid = Uuid::from_slice(&bytes); | |
| /// let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string()); | |
| /// | |
| /// let expected_uuid = | |
| /// Ok(String::from("0436430c-2b02-624c-2032-570501212b57")); | |
| /// | |
| /// assert_eq!(expected_uuid, uuid); | |
| /// ``` | |
| /// | |
| /// An incorrect number of bytes: | |
| /// | |
| /// ``` | |
| /// use uuid::Uuid; | |
| /// | |
| /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76]; | |
| /// | |
| /// let uuid = Uuid::from_slice(&bytes); | |
| /// | |
| /// assert!(uuid.is_err()); | |
| /// ``` | |
| pub fn from_slice(b: &[u8]) -> Result<Uuid, crate::Error> { | |
| const BYTES_LEN: usize = 16; | |
| let len = b.len(); | |
| if len != BYTES_LEN { | |
| Err(Error::new(BYTES_LEN, len))?; | |
| } | |
| let mut bytes: Bytes = [0; 16]; | |
| bytes.copy_from_slice(b); | |
| Ok(Uuid::from_bytes(bytes)) | |
| } | |
| /// Creates a UUID using the supplied big-endian bytes. | |
| pub const fn from_bytes(bytes: Bytes) -> Uuid { | |
| Uuid(bytes) | |
| } | |
| } | |
| /// A builder struct for creating a UUID. | |
| /// | |
| /// # Examples | |
| /// | |
| /// Creating a v4 UUID from externally generated bytes: | |
| /// | |
| /// ``` | |
| /// use uuid::{Builder, Variant, Version}; | |
| /// | |
| /// # let rng = || [ | |
| /// # 70, 235, 208, 238, 14, 109, 67, 201, 185, 13, 204, 195, 90, | |
| /// # 145, 63, 62, | |
| /// # ]; | |
| /// let random_bytes = rng(); | |
| /// let uuid = Builder::from_bytes(random_bytes) | |
| /// .set_variant(Variant::RFC4122) | |
| /// .set_version(Version::Random) | |
| /// .build(); | |
| /// ``` | |
| // TODO: remove in 1.0.0 | |
| #[allow(dead_code)] | |
| #[deprecated] | |
| pub type Builder = crate::Builder; | |
| impl crate::Builder { | |
| /// Creates a `Builder` using the supplied big-endian bytes. | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage: | |
| /// | |
| /// ``` | |
| /// let bytes: uuid::Bytes = [ | |
| /// 70, 235, 208, 238, 14, 109, 67, 201, 185, 13, 204, 195, 90, 145, 63, 62, | |
| /// ]; | |
| /// | |
| /// let mut builder = uuid::Builder::from_bytes(bytes); | |
| /// let uuid = builder.build().to_hyphenated().to_string(); | |
| /// | |
| /// let expected_uuid = String::from("46ebd0ee-0e6d-43c9-b90d-ccc35a913f3e"); | |
| /// | |
| /// assert_eq!(expected_uuid, uuid); | |
| /// ``` | |
| /// | |
| /// An incorrect number of bytes: | |
| /// | |
| /// ```compile_fail | |
| /// let bytes: uuid::Bytes = [4, 54, 67, 12, 43, 2, 98, 76]; // doesn't compile | |
| /// | |
| /// let uuid = uuid::Builder::from_bytes(bytes); | |
| /// ``` | |
| pub const fn from_bytes(b: Bytes) -> Self { | |
| Builder(b) | |
| } | |
| /// Creates a `Builder` using the supplied big-endian bytes. | |
| /// | |
| /// # Errors | |
| /// | |
| /// This function will return an error if `b` has any length other than 16. | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage: | |
| /// | |
| /// ``` | |
| /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76, 32, 50, 87, 5, 1, 33, 43, 87]; | |
| /// | |
| /// let builder = uuid::Builder::from_slice(&bytes); | |
| /// let uuid = | |
| /// builder.map(|mut builder| builder.build().to_hyphenated().to_string()); | |
| /// | |
| /// let expected_uuid = | |
| /// Ok(String::from("0436430c-2b02-624c-2032-570501212b57")); | |
| /// | |
| /// assert_eq!(expected_uuid, uuid); | |
| /// ``` | |
| /// | |
| /// An incorrect number of bytes: | |
| /// | |
| /// ``` | |
| /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76]; | |
| /// | |
| /// let builder = uuid::Builder::from_slice(&bytes); | |
| /// | |
| /// assert!(builder.is_err()); | |
| /// ``` | |
| pub fn from_slice(b: &[u8]) -> Result<Self, crate::Error> { | |
| const BYTES_LEN: usize = 16; | |
| let len = b.len(); | |
| if len != BYTES_LEN { | |
| Err(Error::new(BYTES_LEN, len))?; | |
| } | |
| let mut bytes: crate::Bytes = [0; 16]; | |
| bytes.copy_from_slice(b); | |
| Ok(Self::from_bytes(bytes)) | |
| } | |
| /// Creates a `Builder` from four big-endian field values. | |
| /// | |
| /// # Errors | |
| /// | |
| /// This function will return an error if `d4`'s length is not 8 bytes. | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage: | |
| /// | |
| /// ``` | |
| /// let d4 = [12, 3, 9, 56, 54, 43, 8, 9]; | |
| /// | |
| /// let builder = uuid::Builder::from_fields(42, 12, 5, &d4); | |
| /// let uuid = | |
| /// builder.map(|mut builder| builder.build().to_hyphenated().to_string()); | |
| /// | |
| /// let expected_uuid = | |
| /// Ok(String::from("0000002a-000c-0005-0c03-0938362b0809")); | |
| /// | |
| /// assert_eq!(expected_uuid, uuid); | |
| /// ``` | |
| /// | |
| /// An invalid length: | |
| /// | |
| /// ``` | |
| /// let d4 = [12]; | |
| /// | |
| /// let builder = uuid::Builder::from_fields(42, 12, 5, &d4); | |
| /// | |
| /// assert!(builder.is_err()); | |
| /// ``` | |
| pub fn from_fields( | |
| d1: u32, | |
| d2: u16, | |
| d3: u16, | |
| d4: &[u8], | |
| ) -> Result<Self, crate::Error> { | |
| Uuid::from_fields(d1, d2, d3, d4).map(|uuid| { | |
| let bytes = *uuid.as_bytes(); | |
| crate::Builder::from_bytes(bytes) | |
| }) | |
| } | |
| /// Creates a `Builder` from a big-endian 128bit value. | |
| pub fn from_u128(v: u128) -> Self { | |
| crate::Builder::from_bytes(*Uuid::from_u128(v).as_bytes()) | |
| } | |
| /// Creates a `Builder` with an initial [`Uuid::nil`]. | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage: | |
| /// | |
| /// ``` | |
| /// use uuid::Builder; | |
| /// | |
| /// let mut builder = Builder::nil(); | |
| /// | |
| /// assert_eq!( | |
| /// builder.build().to_hyphenated().to_string(), | |
| /// "00000000-0000-0000-0000-000000000000" | |
| /// ); | |
| /// ``` | |
| pub const fn nil() -> Self { | |
| Builder([0; 16]) | |
| } | |
| /// Specifies the variant of the UUID. | |
| pub fn set_variant(&mut self, v: crate::Variant) -> &mut Self { | |
| let byte = self.0[8]; | |
| self.0[8] = match v { | |
| crate::Variant::NCS => byte & 0x7f, | |
| crate::Variant::RFC4122 => (byte & 0x3f) | 0x80, | |
| crate::Variant::Microsoft => (byte & 0x1f) | 0xc0, | |
| crate::Variant::Future => (byte & 0x1f) | 0xe0, | |
| }; | |
| self | |
| } | |
| /// Specifies the version number of the UUID. | |
| pub fn set_version(&mut self, v: crate::Version) -> &mut Self { | |
| self.0[6] = (self.0[6] & 0x0f) | ((v as u8) << 4); | |
| self | |
| } | |
| /// Hands over the internal constructed [`Uuid`]. | |
| /// | |
| /// # Examples | |
| /// | |
| /// Basic usage: | |
| /// | |
| /// ``` | |
| /// use uuid::Builder; | |
| /// | |
| /// let uuid = Builder::nil().build(); | |
| /// | |
| /// assert_eq!( | |
| /// uuid.to_hyphenated().to_string(), | |
| /// "00000000-0000-0000-0000-000000000000" | |
| /// ); | |
| /// ``` | |
| /// | |
| /// [`Uuid`]: struct.Uuid.html | |
| pub fn build(&mut self) -> Uuid { | |
| Uuid::from_bytes(self.0) | |
| } | |
| } |