• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013-2014 The Rust Project Developers.
2 // Copyright 2018 The Uuid Project Developers.
3 //
4 // See the COPYRIGHT file at the top-level directory of this distribution.
5 //
6 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
7 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
9 // option. This file may not be copied, modified, or distributed
10 // except according to those terms.
11 
12 //! A Builder type for [`Uuid`]s.
13 //!
14 //! [`Uuid`]: ../struct.Uuid.html
15 
16 mod error;
17 pub(crate) use self::error::Error;
18 
19 use crate::prelude::*;
20 
21 impl Uuid {
22     /// The 'nil UUID'.
23     ///
24     /// The nil UUID is special form of UUID that is specified to have all
25     /// 128 bits set to zero, as defined in [IETF RFC 4122 Section 4.1.7][RFC].
26     ///
27     /// [RFC]: https://tools.ietf.org/html/rfc4122.html#section-4.1.7
28     ///
29     /// # Examples
30     ///
31     /// Basic usage:
32     ///
33     /// ```
34     /// use uuid::Uuid;
35     ///
36     /// let uuid = Uuid::nil();
37     ///
38     /// assert_eq!(
39     ///     uuid.to_hyphenated().to_string(),
40     ///     "00000000-0000-0000-0000-000000000000"
41     /// );
42     /// ```
nil() -> Self43     pub const fn nil() -> Self {
44         Uuid::from_bytes([0; 16])
45     }
46 
47     /// Creates a UUID from four field values in big-endian order.
48     ///
49     /// # Errors
50     ///
51     /// This function will return an error if `d4`'s length is not 8 bytes.
52     ///
53     /// # Examples
54     ///
55     /// Basic usage:
56     ///
57     /// ```
58     /// use uuid::Uuid;
59     ///
60     /// let d4 = [12, 3, 9, 56, 54, 43, 8, 9];
61     ///
62     /// let uuid = Uuid::from_fields(42, 12, 5, &d4);
63     /// let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string());
64     ///
65     /// let expected_uuid =
66     ///     Ok(String::from("0000002a-000c-0005-0c03-0938362b0809"));
67     ///
68     /// assert_eq!(expected_uuid, uuid);
69     /// ```
from_fields( d1: u32, d2: u16, d3: u16, d4: &[u8], ) -> Result<Uuid, crate::Error>70     pub fn from_fields(
71         d1: u32,
72         d2: u16,
73         d3: u16,
74         d4: &[u8],
75     ) -> Result<Uuid, crate::Error> {
76         const D4_LEN: usize = 8;
77 
78         let len = d4.len();
79 
80         if len != D4_LEN {
81             Err(Error::new(D4_LEN, len))?;
82         }
83 
84         Ok(Uuid::from_bytes([
85             (d1 >> 24) as u8,
86             (d1 >> 16) as u8,
87             (d1 >> 8) as u8,
88             d1 as u8,
89             (d2 >> 8) as u8,
90             d2 as u8,
91             (d3 >> 8) as u8,
92             d3 as u8,
93             d4[0],
94             d4[1],
95             d4[2],
96             d4[3],
97             d4[4],
98             d4[5],
99             d4[6],
100             d4[7],
101         ]))
102     }
103 
104     /// Creates a UUID from four field values in little-endian order.
105     ///
106     /// The bytes in the `d1`, `d2` and `d3` fields will
107     /// be converted into big-endian order.
108     ///
109     /// # Examples
110     ///
111     /// ```
112     /// use uuid::Uuid;
113     ///
114     /// let d1 = 0xAB3F1097u32;
115     /// let d2 = 0x501Eu16;
116     /// let d3 = 0xB736u16;
117     /// let d4 = [12, 3, 9, 56, 54, 43, 8, 9];
118     ///
119     /// let uuid = Uuid::from_fields_le(d1, d2, d3, &d4);
120     /// let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string());
121     ///
122     /// let expected_uuid =
123     ///     Ok(String::from("97103fab-1e50-36b7-0c03-0938362b0809"));
124     ///
125     /// assert_eq!(expected_uuid, uuid);
126     /// ```
from_fields_le( d1: u32, d2: u16, d3: u16, d4: &[u8], ) -> Result<Uuid, crate::Error>127     pub fn from_fields_le(
128         d1: u32,
129         d2: u16,
130         d3: u16,
131         d4: &[u8],
132     ) -> Result<Uuid, crate::Error> {
133         const D4_LEN: usize = 8;
134 
135         let len = d4.len();
136 
137         if len != D4_LEN {
138             Err(Error::new(D4_LEN, len))?;
139         }
140 
141         Ok(Uuid::from_bytes([
142             d1 as u8,
143             (d1 >> 8) as u8,
144             (d1 >> 16) as u8,
145             (d1 >> 24) as u8,
146             (d2) as u8,
147             (d2 >> 8) as u8,
148             d3 as u8,
149             (d3 >> 8) as u8,
150             d4[0],
151             d4[1],
152             d4[2],
153             d4[3],
154             d4[4],
155             d4[5],
156             d4[6],
157             d4[7],
158         ]))
159     }
160 
161     /// Creates a UUID from a 128bit value in big-endian order.
from_u128(v: u128) -> Self162     pub const fn from_u128(v: u128) -> Self {
163         Uuid::from_bytes([
164             (v >> 120) as u8,
165             (v >> 112) as u8,
166             (v >> 104) as u8,
167             (v >> 96) as u8,
168             (v >> 88) as u8,
169             (v >> 80) as u8,
170             (v >> 72) as u8,
171             (v >> 64) as u8,
172             (v >> 56) as u8,
173             (v >> 48) as u8,
174             (v >> 40) as u8,
175             (v >> 32) as u8,
176             (v >> 24) as u8,
177             (v >> 16) as u8,
178             (v >> 8) as u8,
179             v as u8,
180         ])
181     }
182 
183     /// Creates a UUID from a 128bit value in little-endian order.
from_u128_le(v: u128) -> Self184     pub const fn from_u128_le(v: u128) -> Self {
185         Uuid::from_bytes([
186             v as u8,
187             (v >> 8) as u8,
188             (v >> 16) as u8,
189             (v >> 24) as u8,
190             (v >> 32) as u8,
191             (v >> 40) as u8,
192             (v >> 48) as u8,
193             (v >> 56) as u8,
194             (v >> 64) as u8,
195             (v >> 72) as u8,
196             (v >> 80) as u8,
197             (v >> 88) as u8,
198             (v >> 96) as u8,
199             (v >> 104) as u8,
200             (v >> 112) as u8,
201             (v >> 120) as u8,
202         ])
203     }
204 
205     /// Creates a UUID using the supplied big-endian bytes.
206     ///
207     /// # Errors
208     ///
209     /// This function will return an error if `b` has any length other than 16.
210     ///
211     /// # Examples
212     ///
213     /// Basic usage:
214     ///
215     /// ```
216     /// use uuid::Uuid;
217     ///
218     /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76, 32, 50, 87, 5, 1, 33, 43, 87];
219     ///
220     /// let uuid = Uuid::from_slice(&bytes);
221     /// let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string());
222     ///
223     /// let expected_uuid =
224     ///     Ok(String::from("0436430c-2b02-624c-2032-570501212b57"));
225     ///
226     /// assert_eq!(expected_uuid, uuid);
227     /// ```
228     ///
229     /// An incorrect number of bytes:
230     ///
231     /// ```
232     /// use uuid::Uuid;
233     ///
234     /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76];
235     ///
236     /// let uuid = Uuid::from_slice(&bytes);
237     ///
238     /// assert!(uuid.is_err());
239     /// ```
from_slice(b: &[u8]) -> Result<Uuid, crate::Error>240     pub fn from_slice(b: &[u8]) -> Result<Uuid, crate::Error> {
241         const BYTES_LEN: usize = 16;
242 
243         let len = b.len();
244 
245         if len != BYTES_LEN {
246             Err(Error::new(BYTES_LEN, len))?;
247         }
248 
249         let mut bytes: Bytes = [0; 16];
250         bytes.copy_from_slice(b);
251         Ok(Uuid::from_bytes(bytes))
252     }
253 
254     /// Creates a UUID using the supplied big-endian bytes.
from_bytes(bytes: Bytes) -> Uuid255     pub const fn from_bytes(bytes: Bytes) -> Uuid {
256         Uuid(bytes)
257     }
258 }
259 
260 /// A builder struct for creating a UUID.
261 ///
262 /// # Examples
263 ///
264 /// Creating a v4 UUID from externally generated bytes:
265 ///
266 /// ```
267 /// use uuid::{Builder, Variant, Version};
268 ///
269 /// # let rng = || [
270 /// #     70, 235, 208, 238, 14, 109, 67, 201, 185, 13, 204, 195, 90,
271 /// # 145, 63, 62,
272 /// # ];
273 /// let random_bytes = rng();
274 /// let uuid = Builder::from_bytes(random_bytes)
275 ///     .set_variant(Variant::RFC4122)
276 ///     .set_version(Version::Random)
277 ///     .build();
278 /// ```
279 // TODO: remove in 1.0.0
280 #[allow(dead_code)]
281 #[deprecated]
282 pub type Builder = crate::Builder;
283 
284 impl crate::Builder {
285     /// Creates a `Builder` using the supplied big-endian bytes.
286     ///
287     /// # Examples
288     ///
289     /// Basic usage:
290     ///
291     /// ```
292     /// let bytes: uuid::Bytes = [
293     ///     70, 235, 208, 238, 14, 109, 67, 201, 185, 13, 204, 195, 90, 145, 63, 62,
294     /// ];
295     ///
296     /// let mut builder = uuid::Builder::from_bytes(bytes);
297     /// let uuid = builder.build().to_hyphenated().to_string();
298     ///
299     /// let expected_uuid = String::from("46ebd0ee-0e6d-43c9-b90d-ccc35a913f3e");
300     ///
301     /// assert_eq!(expected_uuid, uuid);
302     /// ```
303     ///
304     /// An incorrect number of bytes:
305     ///
306     /// ```compile_fail
307     /// let bytes: uuid::Bytes = [4, 54, 67, 12, 43, 2, 98, 76]; // doesn't compile
308     ///
309     /// let uuid = uuid::Builder::from_bytes(bytes);
310     /// ```
from_bytes(b: Bytes) -> Self311     pub const fn from_bytes(b: Bytes) -> Self {
312         Builder(b)
313     }
314 
315     /// Creates a `Builder` using the supplied big-endian bytes.
316     ///
317     /// # Errors
318     ///
319     /// This function will return an error if `b` has any length other than 16.
320     ///
321     /// # Examples
322     ///
323     /// Basic usage:
324     ///
325     /// ```
326     /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76, 32, 50, 87, 5, 1, 33, 43, 87];
327     ///
328     /// let builder = uuid::Builder::from_slice(&bytes);
329     /// let uuid =
330     ///     builder.map(|mut builder| builder.build().to_hyphenated().to_string());
331     ///
332     /// let expected_uuid =
333     ///     Ok(String::from("0436430c-2b02-624c-2032-570501212b57"));
334     ///
335     /// assert_eq!(expected_uuid, uuid);
336     /// ```
337     ///
338     /// An incorrect number of bytes:
339     ///
340     /// ```
341     /// let bytes = [4, 54, 67, 12, 43, 2, 98, 76];
342     ///
343     /// let builder = uuid::Builder::from_slice(&bytes);
344     ///
345     /// assert!(builder.is_err());
346     /// ```
from_slice(b: &[u8]) -> Result<Self, crate::Error>347     pub fn from_slice(b: &[u8]) -> Result<Self, crate::Error> {
348         const BYTES_LEN: usize = 16;
349 
350         let len = b.len();
351 
352         if len != BYTES_LEN {
353             Err(Error::new(BYTES_LEN, len))?;
354         }
355 
356         let mut bytes: crate::Bytes = [0; 16];
357         bytes.copy_from_slice(b);
358         Ok(Self::from_bytes(bytes))
359     }
360 
361     /// Creates a `Builder` from four big-endian field values.
362     ///
363     /// # Errors
364     ///
365     /// This function will return an error if `d4`'s length is not 8 bytes.
366     ///
367     /// # Examples
368     ///
369     /// Basic usage:
370     ///
371     /// ```
372     /// let d4 = [12, 3, 9, 56, 54, 43, 8, 9];
373     ///
374     /// let builder = uuid::Builder::from_fields(42, 12, 5, &d4);
375     /// let uuid =
376     ///     builder.map(|mut builder| builder.build().to_hyphenated().to_string());
377     ///
378     /// let expected_uuid =
379     ///     Ok(String::from("0000002a-000c-0005-0c03-0938362b0809"));
380     ///
381     /// assert_eq!(expected_uuid, uuid);
382     /// ```
383     ///
384     /// An invalid length:
385     ///
386     /// ```
387     /// let d4 = [12];
388     ///
389     /// let builder = uuid::Builder::from_fields(42, 12, 5, &d4);
390     ///
391     /// assert!(builder.is_err());
392     /// ```
from_fields( d1: u32, d2: u16, d3: u16, d4: &[u8], ) -> Result<Self, crate::Error>393     pub fn from_fields(
394         d1: u32,
395         d2: u16,
396         d3: u16,
397         d4: &[u8],
398     ) -> Result<Self, crate::Error> {
399         Uuid::from_fields(d1, d2, d3, d4).map(|uuid| {
400             let bytes = *uuid.as_bytes();
401 
402             crate::Builder::from_bytes(bytes)
403         })
404     }
405 
406     /// Creates a `Builder` from a big-endian 128bit value.
from_u128(v: u128) -> Self407     pub fn from_u128(v: u128) -> Self {
408         crate::Builder::from_bytes(*Uuid::from_u128(v).as_bytes())
409     }
410 
411     /// Creates a `Builder` with an initial [`Uuid::nil`].
412     ///
413     /// # Examples
414     ///
415     /// Basic usage:
416     ///
417     /// ```
418     /// use uuid::Builder;
419     ///
420     /// let mut builder = Builder::nil();
421     ///
422     /// assert_eq!(
423     ///     builder.build().to_hyphenated().to_string(),
424     ///     "00000000-0000-0000-0000-000000000000"
425     /// );
426     /// ```
nil() -> Self427     pub const fn nil() -> Self {
428         Builder([0; 16])
429     }
430 
431     /// Specifies the variant of the UUID.
set_variant(&mut self, v: crate::Variant) -> &mut Self432     pub fn set_variant(&mut self, v: crate::Variant) -> &mut Self {
433         let byte = self.0[8];
434 
435         self.0[8] = match v {
436             crate::Variant::NCS => byte & 0x7f,
437             crate::Variant::RFC4122 => (byte & 0x3f) | 0x80,
438             crate::Variant::Microsoft => (byte & 0x1f) | 0xc0,
439             crate::Variant::Future => (byte & 0x1f) | 0xe0,
440         };
441 
442         self
443     }
444 
445     /// Specifies the version number of the UUID.
set_version(&mut self, v: crate::Version) -> &mut Self446     pub fn set_version(&mut self, v: crate::Version) -> &mut Self {
447         self.0[6] = (self.0[6] & 0x0f) | ((v as u8) << 4);
448 
449         self
450     }
451 
452     /// Hands over the internal constructed [`Uuid`].
453     ///
454     /// # Examples
455     ///
456     /// Basic usage:
457     ///
458     /// ```
459     /// use uuid::Builder;
460     ///
461     /// let uuid = Builder::nil().build();
462     ///
463     /// assert_eq!(
464     ///     uuid.to_hyphenated().to_string(),
465     ///     "00000000-0000-0000-0000-000000000000"
466     /// );
467     /// ```
468     ///
469     /// [`Uuid`]: struct.Uuid.html
build(&mut self) -> Uuid470     pub fn build(&mut self) -> Uuid {
471         Uuid::from_bytes(self.0)
472     }
473 }
474