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 //! Adapters for alternative string formats.
13 
14 use crate::{
15     std::{borrow::Borrow, fmt, ptr, str},
16     Uuid, Variant,
17 };
18 
19 #[cfg(feature = "std")]
20 use crate::std::string::{String, ToString};
21 
22 impl std::fmt::Debug for Uuid {
23     #[inline]
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result24     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25         fmt::LowerHex::fmt(self, f)
26     }
27 }
28 
29 impl fmt::Display for Uuid {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result30     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31         fmt::LowerHex::fmt(self, f)
32     }
33 }
34 
35 #[cfg(feature = "std")]
36 impl From<Uuid> for String {
from(uuid: Uuid) -> Self37     fn from(uuid: Uuid) -> Self {
38         uuid.to_string()
39     }
40 }
41 
42 impl fmt::Display for Variant {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result43     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44         match *self {
45             Variant::NCS => write!(f, "NCS"),
46             Variant::RFC4122 => write!(f, "RFC4122"),
47             Variant::Microsoft => write!(f, "Microsoft"),
48             Variant::Future => write!(f, "Future"),
49         }
50     }
51 }
52 
53 impl fmt::LowerHex for Uuid {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result54     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55         fmt::LowerHex::fmt(self.as_hyphenated(), f)
56     }
57 }
58 
59 impl fmt::UpperHex for Uuid {
60     #[inline]
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result61     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62         fmt::UpperHex::fmt(self.as_hyphenated(), f)
63     }
64 }
65 
66 /// Format a [`Uuid`] as a hyphenated string, like
67 /// `67e55044-10b1-426f-9247-bb680e5fe0c8`.
68 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
69 #[repr(transparent)]
70 pub struct Hyphenated(Uuid);
71 
72 /// Format a [`Uuid`] as a simple string, like
73 /// `67e5504410b1426f9247bb680e5fe0c8`.
74 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
75 #[repr(transparent)]
76 pub struct Simple(Uuid);
77 
78 /// Format a [`Uuid`] as a URN string, like
79 /// `urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8`.
80 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
81 #[repr(transparent)]
82 pub struct Urn(Uuid);
83 
84 /// Format a [`Uuid`] as a braced hyphenated string, like
85 /// `{67e55044-10b1-426f-9247-bb680e5fe0c8}`.
86 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
87 #[repr(transparent)]
88 pub struct Braced(Uuid);
89 
90 impl Uuid {
91     /// Get a [`Hyphenated`] formatter.
92     #[inline]
hyphenated(self) -> Hyphenated93     pub const fn hyphenated(self) -> Hyphenated {
94         Hyphenated(self)
95     }
96 
97     /// Get a borrowed [`Hyphenated`] formatter.
98     #[inline]
as_hyphenated(&self) -> &Hyphenated99     pub fn as_hyphenated(&self) -> &Hyphenated {
100         // SAFETY: `Uuid` and `Hyphenated` have the same ABI
101         unsafe { &*(self as *const Uuid as *const Hyphenated) }
102     }
103 
104     /// Get a [`Simple`] formatter.
105     #[inline]
simple(self) -> Simple106     pub const fn simple(self) -> Simple {
107         Simple(self)
108     }
109 
110     /// Get a borrowed [`Simple`] formatter.
111     #[inline]
as_simple(&self) -> &Simple112     pub fn as_simple(&self) -> &Simple {
113         // SAFETY: `Uuid` and `Simple` have the same ABI
114         unsafe { &*(self as *const Uuid as *const Simple) }
115     }
116 
117     /// Get a [`Urn`] formatter.
118     #[inline]
urn(self) -> Urn119     pub const fn urn(self) -> Urn {
120         Urn(self)
121     }
122 
123     /// Get a borrowed [`Urn`] formatter.
124     #[inline]
as_urn(&self) -> &Urn125     pub fn as_urn(&self) -> &Urn {
126         // SAFETY: `Uuid` and `Urn` have the same ABI
127         unsafe { &*(self as *const Uuid as *const Urn) }
128     }
129 
130     /// Get a [`Braced`] formatter.
131     #[inline]
braced(self) -> Braced132     pub const fn braced(self) -> Braced {
133         Braced(self)
134     }
135 
136     /// Get a borrowed [`Braced`] formatter.
137     #[inline]
as_braced(&self) -> &Braced138     pub fn as_braced(&self) -> &Braced {
139         // SAFETY: `Uuid` and `Braced` have the same ABI
140         unsafe { &*(self as *const Uuid as *const Braced) }
141     }
142 }
143 
144 const UPPER: [u8; 16] = [
145     b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'A', b'B', b'C', b'D', b'E', b'F',
146 ];
147 const LOWER: [u8; 16] = [
148     b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f',
149 ];
150 
151 #[inline]
format_simple(src: &[u8; 16], upper: bool) -> [u8; 32]152 const fn format_simple(src: &[u8; 16], upper: bool) -> [u8; 32] {
153     let lut = if upper { &UPPER } else { &LOWER };
154     let mut dst = [0; 32];
155     let mut i = 0;
156     while i < 16 {
157         let x = src[i];
158         dst[i * 2] = lut[(x >> 4) as usize];
159         dst[i * 2 + 1] = lut[(x & 0x0f) as usize];
160         i += 1;
161     }
162     dst
163 }
164 
165 #[inline]
format_hyphenated(src: &[u8; 16], upper: bool) -> [u8; 36]166 const fn format_hyphenated(src: &[u8; 16], upper: bool) -> [u8; 36] {
167     let lut = if upper { &UPPER } else { &LOWER };
168     let groups = [(0, 8), (9, 13), (14, 18), (19, 23), (24, 36)];
169     let mut dst = [0; 36];
170 
171     let mut group_idx = 0;
172     let mut i = 0;
173     while group_idx < 5 {
174         let (start, end) = groups[group_idx];
175         let mut j = start;
176         while j < end {
177             let x = src[i];
178             i += 1;
179 
180             dst[j] = lut[(x >> 4) as usize];
181             dst[j + 1] = lut[(x & 0x0f) as usize];
182             j += 2;
183         }
184         if group_idx < 4 {
185             dst[end] = b'-';
186         }
187         group_idx += 1;
188     }
189     dst
190 }
191 
192 #[inline]
encode_simple<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str193 fn encode_simple<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
194     let buf = &mut buffer[..Simple::LENGTH];
195     let dst = buf.as_mut_ptr();
196 
197     // SAFETY: `buf` is guaranteed to be at least `LEN` bytes
198     // SAFETY: The encoded buffer is ASCII encoded
199     unsafe {
200         ptr::write(dst.cast(), format_simple(src, upper));
201         str::from_utf8_unchecked_mut(buf)
202     }
203 }
204 
205 #[inline]
encode_hyphenated<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str206 fn encode_hyphenated<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
207     let buf = &mut buffer[..Hyphenated::LENGTH];
208     let dst = buf.as_mut_ptr();
209 
210     // SAFETY: `buf` is guaranteed to be at least `LEN` bytes
211     // SAFETY: The encoded buffer is ASCII encoded
212     unsafe {
213         ptr::write(dst.cast(), format_hyphenated(src, upper));
214         str::from_utf8_unchecked_mut(buf)
215     }
216 }
217 
218 #[inline]
encode_braced<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str219 fn encode_braced<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
220     let buf = &mut buffer[..Braced::LENGTH];
221     buf[0] = b'{';
222     buf[Braced::LENGTH - 1] = b'}';
223 
224     // SAFETY: `buf` is guaranteed to be at least `LEN` bytes
225     // SAFETY: The encoded buffer is ASCII encoded
226     unsafe {
227         let dst = buf.as_mut_ptr().add(1);
228 
229         ptr::write(dst.cast(), format_hyphenated(src, upper));
230         str::from_utf8_unchecked_mut(buf)
231     }
232 }
233 
234 #[inline]
encode_urn<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str235 fn encode_urn<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
236     let buf = &mut buffer[..Urn::LENGTH];
237     buf[..9].copy_from_slice(b"urn:uuid:");
238 
239     // SAFETY: `buf` is guaranteed to be at least `LEN` bytes
240     // SAFETY: The encoded buffer is ASCII encoded
241     unsafe {
242         let dst = buf.as_mut_ptr().add(9);
243 
244         ptr::write(dst.cast(), format_hyphenated(src, upper));
245         str::from_utf8_unchecked_mut(buf)
246     }
247 }
248 
249 impl Hyphenated {
250     /// The length of a hyphenated [`Uuid`] string.
251     ///
252     /// [`Uuid`]: ../struct.Uuid.html
253     pub const LENGTH: usize = 36;
254 
255     /// Creates a [`Hyphenated`] from a [`Uuid`].
256     ///
257     /// [`Uuid`]: ../struct.Uuid.html
258     /// [`Hyphenated`]: struct.Hyphenated.html
from_uuid(uuid: Uuid) -> Self259     pub const fn from_uuid(uuid: Uuid) -> Self {
260         Hyphenated(uuid)
261     }
262 
263     /// Writes the [`Uuid`] as a lower-case hyphenated string to
264     /// `buffer`, and returns the subslice of the buffer that contains the
265     /// encoded UUID.
266     ///
267     /// This is slightly more efficient than using the formatting
268     /// infrastructure as it avoids virtual calls, and may avoid
269     /// double buffering.
270     ///
271     /// [`Uuid`]: ../struct.Uuid.html
272     ///
273     /// # Panics
274     ///
275     /// Panics if the buffer is not large enough: it must have length at least
276     /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
277     /// sufficiently-large temporary buffer.
278     ///
279     /// [`LENGTH`]: #associatedconstant.LENGTH
280     /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
281     ///
282     /// # Examples
283     ///
284     /// ```rust
285     /// use uuid::Uuid;
286     ///
287     /// fn main() -> Result<(), uuid::Error> {
288     ///     let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
289     ///
290     ///     // the encoded portion is returned
291     ///     assert_eq!(
292     ///         uuid.hyphenated()
293     ///             .encode_lower(&mut Uuid::encode_buffer()),
294     ///         "936da01f-9abd-4d9d-80c7-02af85c822a8"
295     ///     );
296     ///
297     ///     // the buffer is mutated directly, and trailing contents remains
298     ///     let mut buf = [b'!'; 40];
299     ///     uuid.hyphenated().encode_lower(&mut buf);
300     ///     assert_eq!(
301     ///         &buf as &[_],
302     ///         b"936da01f-9abd-4d9d-80c7-02af85c822a8!!!!" as &[_]
303     ///     );
304     ///
305     ///     Ok(())
306     /// }
307     /// ```
308     /// */
309     #[inline]
encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str310     pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
311         encode_hyphenated(self.0.as_bytes(), buffer, false)
312     }
313 
314     /// Writes the [`Uuid`] as an upper-case hyphenated string to
315     /// `buffer`, and returns the subslice of the buffer that contains the
316     /// encoded UUID.
317     ///
318     /// This is slightly more efficient than using the formatting
319     /// infrastructure as it avoids virtual calls, and may avoid
320     /// double buffering.
321     ///
322     /// [`Uuid`]: ../struct.Uuid.html
323     ///
324     /// # Panics
325     ///
326     /// Panics if the buffer is not large enough: it must have length at least
327     /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
328     /// sufficiently-large temporary buffer.
329     ///
330     /// [`LENGTH`]: #associatedconstant.LENGTH
331     /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
332     ///
333     /// # Examples
334     ///
335     /// ```rust
336     /// use uuid::Uuid;
337     ///
338     /// fn main() -> Result<(), uuid::Error> {
339     ///     let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
340     ///
341     ///     // the encoded portion is returned
342     ///     assert_eq!(
343     ///         uuid.hyphenated()
344     ///             .encode_upper(&mut Uuid::encode_buffer()),
345     ///         "936DA01F-9ABD-4D9D-80C7-02AF85C822A8"
346     ///     );
347     ///
348     ///     // the buffer is mutated directly, and trailing contents remains
349     ///     let mut buf = [b'!'; 40];
350     ///     uuid.hyphenated().encode_upper(&mut buf);
351     ///     assert_eq!(
352     ///         &buf as &[_],
353     ///         b"936DA01F-9ABD-4D9D-80C7-02AF85C822A8!!!!" as &[_]
354     ///     );
355     ///
356     ///     Ok(())
357     /// }
358     /// ```
359     /// */
360     #[inline]
encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str361     pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
362         encode_hyphenated(self.0.as_bytes(), buffer, true)
363     }
364 
365     /// Get a reference to the underlying [`Uuid`].
366     ///
367     /// # Examples
368     ///
369     /// ```rust
370     /// use uuid::Uuid;
371     ///
372     /// let hyphenated = Uuid::nil().hyphenated();
373     /// assert_eq!(*hyphenated.as_uuid(), Uuid::nil());
374     /// ```
as_uuid(&self) -> &Uuid375     pub const fn as_uuid(&self) -> &Uuid {
376         &self.0
377     }
378 
379     /// Consumes the [`Hyphenated`], returning the underlying [`Uuid`].
380     ///
381     /// # Examples
382     ///
383     /// ```rust
384     /// use uuid::Uuid;
385     ///
386     /// let hyphenated = Uuid::nil().hyphenated();
387     /// assert_eq!(hyphenated.into_uuid(), Uuid::nil());
388     /// ```
into_uuid(self) -> Uuid389     pub const fn into_uuid(self) -> Uuid {
390         self.0
391     }
392 }
393 
394 impl Braced {
395     /// The length of a braced [`Uuid`] string.
396     ///
397     /// [`Uuid`]: ../struct.Uuid.html
398     pub const LENGTH: usize = 38;
399 
400     /// Creates a [`Braced`] from a [`Uuid`].
401     ///
402     /// [`Uuid`]: ../struct.Uuid.html
403     /// [`Braced`]: struct.Braced.html
from_uuid(uuid: Uuid) -> Self404     pub const fn from_uuid(uuid: Uuid) -> Self {
405         Braced(uuid)
406     }
407 
408     /// Writes the [`Uuid`] as a lower-case hyphenated string surrounded by
409     /// braces to `buffer`, and returns the subslice of the buffer that contains
410     /// the encoded UUID.
411     ///
412     /// This is slightly more efficient than using the formatting
413     /// infrastructure as it avoids virtual calls, and may avoid
414     /// double buffering.
415     ///
416     /// [`Uuid`]: ../struct.Uuid.html
417     ///
418     /// # Panics
419     ///
420     /// Panics if the buffer is not large enough: it must have length at least
421     /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
422     /// sufficiently-large temporary buffer.
423     ///
424     /// [`LENGTH`]: #associatedconstant.LENGTH
425     /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
426     ///
427     /// # Examples
428     ///
429     /// ```rust
430     /// use uuid::Uuid;
431     ///
432     /// fn main() -> Result<(), uuid::Error> {
433     ///     let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
434     ///
435     ///     // the encoded portion is returned
436     ///     assert_eq!(
437     ///         uuid.braced()
438     ///             .encode_lower(&mut Uuid::encode_buffer()),
439     ///         "{936da01f-9abd-4d9d-80c7-02af85c822a8}"
440     ///     );
441     ///
442     ///     // the buffer is mutated directly, and trailing contents remains
443     ///     let mut buf = [b'!'; 40];
444     ///     uuid.braced().encode_lower(&mut buf);
445     ///     assert_eq!(
446     ///         &buf as &[_],
447     ///         b"{936da01f-9abd-4d9d-80c7-02af85c822a8}!!" as &[_]
448     ///     );
449     ///
450     ///     Ok(())
451     /// }
452     /// ```
453     /// */
454     #[inline]
encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str455     pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
456         encode_braced(self.0.as_bytes(), buffer, false)
457     }
458 
459     /// Writes the [`Uuid`] as an upper-case hyphenated string surrounded by
460     /// braces to `buffer`, and returns the subslice of the buffer that contains
461     /// the encoded UUID.
462     ///
463     /// This is slightly more efficient than using the formatting
464     /// infrastructure as it avoids virtual calls, and may avoid
465     /// double buffering.
466     ///
467     /// [`Uuid`]: ../struct.Uuid.html
468     ///
469     /// # Panics
470     ///
471     /// Panics if the buffer is not large enough: it must have length at least
472     /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
473     /// sufficiently-large temporary buffer.
474     ///
475     /// [`LENGTH`]: #associatedconstant.LENGTH
476     /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
477     ///
478     /// # Examples
479     ///
480     /// ```rust
481     /// use uuid::Uuid;
482     ///
483     /// fn main() -> Result<(), uuid::Error> {
484     ///     let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
485     ///
486     ///     // the encoded portion is returned
487     ///     assert_eq!(
488     ///         uuid.braced()
489     ///             .encode_upper(&mut Uuid::encode_buffer()),
490     ///         "{936DA01F-9ABD-4D9D-80C7-02AF85C822A8}"
491     ///     );
492     ///
493     ///     // the buffer is mutated directly, and trailing contents remains
494     ///     let mut buf = [b'!'; 40];
495     ///     uuid.braced().encode_upper(&mut buf);
496     ///     assert_eq!(
497     ///         &buf as &[_],
498     ///         b"{936DA01F-9ABD-4D9D-80C7-02AF85C822A8}!!" as &[_]
499     ///     );
500     ///
501     ///     Ok(())
502     /// }
503     /// ```
504     /// */
505     #[inline]
encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str506     pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
507         encode_braced(self.0.as_bytes(), buffer, true)
508     }
509 
510     /// Get a reference to the underlying [`Uuid`].
511     ///
512     /// # Examples
513     ///
514     /// ```rust
515     /// use uuid::Uuid;
516     ///
517     /// let braced = Uuid::nil().braced();
518     /// assert_eq!(*braced.as_uuid(), Uuid::nil());
519     /// ```
as_uuid(&self) -> &Uuid520     pub const fn as_uuid(&self) -> &Uuid {
521         &self.0
522     }
523 
524     /// Consumes the [`Braced`], returning the underlying [`Uuid`].
525     ///
526     /// # Examples
527     ///
528     /// ```rust
529     /// use uuid::Uuid;
530     ///
531     /// let braced = Uuid::nil().braced();
532     /// assert_eq!(braced.into_uuid(), Uuid::nil());
533     /// ```
into_uuid(self) -> Uuid534     pub const fn into_uuid(self) -> Uuid {
535         self.0
536     }
537 }
538 
539 impl Simple {
540     /// The length of a simple [`Uuid`] string.
541     ///
542     /// [`Uuid`]: ../struct.Uuid.html
543     pub const LENGTH: usize = 32;
544 
545     /// Creates a [`Simple`] from a [`Uuid`].
546     ///
547     /// [`Uuid`]: ../struct.Uuid.html
548     /// [`Simple`]: struct.Simple.html
from_uuid(uuid: Uuid) -> Self549     pub const fn from_uuid(uuid: Uuid) -> Self {
550         Simple(uuid)
551     }
552 
553     /// Writes the [`Uuid`] as a lower-case simple string to `buffer`,
554     /// and returns the subslice of the buffer that contains the encoded UUID.
555     ///
556     /// This is slightly more efficient than using the formatting
557     /// infrastructure as it avoids virtual calls, and may avoid
558     /// double buffering.
559     ///
560     /// [`Uuid`]: ../struct.Uuid.html
561     ///
562     /// # Panics
563     ///
564     /// Panics if the buffer is not large enough: it must have length at least
565     /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
566     /// sufficiently-large temporary buffer.
567     ///
568     /// [`LENGTH`]: #associatedconstant.LENGTH
569     /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
570     ///
571     /// # Examples
572     ///
573     /// ```rust
574     /// use uuid::Uuid;
575     ///
576     /// fn main() -> Result<(), uuid::Error> {
577     ///     let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
578     ///
579     ///     // the encoded portion is returned
580     ///     assert_eq!(
581     ///         uuid.simple().encode_lower(&mut Uuid::encode_buffer()),
582     ///         "936da01f9abd4d9d80c702af85c822a8"
583     ///     );
584     ///
585     ///     // the buffer is mutated directly, and trailing contents remains
586     ///     let mut buf = [b'!'; 36];
587     ///     assert_eq!(
588     ///         uuid.simple().encode_lower(&mut buf),
589     ///         "936da01f9abd4d9d80c702af85c822a8"
590     ///     );
591     ///     assert_eq!(
592     ///         &buf as &[_],
593     ///         b"936da01f9abd4d9d80c702af85c822a8!!!!" as &[_]
594     ///     );
595     ///
596     ///     Ok(())
597     /// }
598     /// ```
599     /// */
600     #[inline]
encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str601     pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
602         encode_simple(self.0.as_bytes(), buffer, false)
603     }
604 
605     /// Writes the [`Uuid`] as an upper-case simple string to `buffer`,
606     /// and returns the subslice of the buffer that contains the encoded UUID.
607     ///
608     /// [`Uuid`]: ../struct.Uuid.html
609     ///
610     /// # Panics
611     ///
612     /// Panics if the buffer is not large enough: it must have length at least
613     /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
614     /// sufficiently-large temporary buffer.
615     ///
616     /// [`LENGTH`]: #associatedconstant.LENGTH
617     /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
618     ///
619     /// # Examples
620     ///
621     /// ```rust
622     /// use uuid::Uuid;
623     ///
624     /// fn main() -> Result<(), uuid::Error> {
625     ///     let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
626     ///
627     ///     // the encoded portion is returned
628     ///     assert_eq!(
629     ///         uuid.simple().encode_upper(&mut Uuid::encode_buffer()),
630     ///         "936DA01F9ABD4D9D80C702AF85C822A8"
631     ///     );
632     ///
633     ///     // the buffer is mutated directly, and trailing contents remains
634     ///     let mut buf = [b'!'; 36];
635     ///     assert_eq!(
636     ///         uuid.simple().encode_upper(&mut buf),
637     ///         "936DA01F9ABD4D9D80C702AF85C822A8"
638     ///     );
639     ///     assert_eq!(
640     ///         &buf as &[_],
641     ///         b"936DA01F9ABD4D9D80C702AF85C822A8!!!!" as &[_]
642     ///     );
643     ///
644     ///     Ok(())
645     /// }
646     /// ```
647     /// */
648     #[inline]
encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str649     pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
650         encode_simple(self.0.as_bytes(), buffer, true)
651     }
652 
653     /// Get a reference to the underlying [`Uuid`].
654     ///
655     /// # Examples
656     ///
657     /// ```rust
658     /// use uuid::Uuid;
659     ///
660     /// let simple = Uuid::nil().simple();
661     /// assert_eq!(*simple.as_uuid(), Uuid::nil());
662     /// ```
as_uuid(&self) -> &Uuid663     pub const fn as_uuid(&self) -> &Uuid {
664         &self.0
665     }
666 
667     /// Consumes the [`Simple`], returning the underlying [`Uuid`].
668     ///
669     /// # Examples
670     ///
671     /// ```rust
672     /// use uuid::Uuid;
673     ///
674     /// let simple = Uuid::nil().simple();
675     /// assert_eq!(simple.into_uuid(), Uuid::nil());
676     /// ```
into_uuid(self) -> Uuid677     pub const fn into_uuid(self) -> Uuid {
678         self.0
679     }
680 }
681 
682 impl Urn {
683     /// The length of a URN [`Uuid`] string.
684     ///
685     /// [`Uuid`]: ../struct.Uuid.html
686     pub const LENGTH: usize = 45;
687 
688     /// Creates a [`Urn`] from a [`Uuid`].
689     ///
690     /// [`Uuid`]: ../struct.Uuid.html
691     /// [`Urn`]: struct.Urn.html
from_uuid(uuid: Uuid) -> Self692     pub const fn from_uuid(uuid: Uuid) -> Self {
693         Urn(uuid)
694     }
695 
696     /// Writes the [`Uuid`] as a lower-case URN string to
697     /// `buffer`, and returns the subslice of the buffer that contains the
698     /// encoded UUID.
699     ///
700     /// This is slightly more efficient than using the formatting
701     /// infrastructure as it avoids virtual calls, and may avoid
702     /// double buffering.
703     ///
704     /// [`Uuid`]: ../struct.Uuid.html
705     ///
706     /// # Panics
707     ///
708     /// Panics if the buffer is not large enough: it must have length at least
709     /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
710     /// sufficiently-large temporary buffer.
711     ///
712     /// [`LENGTH`]: #associatedconstant.LENGTH
713     /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
714     ///
715     /// # Examples
716     ///
717     /// ```rust
718     /// use uuid::Uuid;
719     ///
720     /// fn main() -> Result<(), uuid::Error> {
721     ///     let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
722     ///
723     ///     // the encoded portion is returned
724     ///     assert_eq!(
725     ///         uuid.urn().encode_lower(&mut Uuid::encode_buffer()),
726     ///         "urn:uuid:936da01f-9abd-4d9d-80c7-02af85c822a8"
727     ///     );
728     ///
729     ///     // the buffer is mutated directly, and trailing contents remains
730     ///     let mut buf = [b'!'; 49];
731     ///     uuid.urn().encode_lower(&mut buf);
732     ///     assert_eq!(
733     ///         uuid.urn().encode_lower(&mut buf),
734     ///         "urn:uuid:936da01f-9abd-4d9d-80c7-02af85c822a8"
735     ///     );
736     ///     assert_eq!(
737     ///         &buf as &[_],
738     ///         b"urn:uuid:936da01f-9abd-4d9d-80c7-02af85c822a8!!!!" as &[_]
739     ///     );
740     ///
741     ///     Ok(())
742     /// }
743     /// ```
744     /// */
745     #[inline]
encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str746     pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
747         encode_urn(self.0.as_bytes(), buffer, false)
748     }
749 
750     /// Writes the [`Uuid`] as an upper-case URN string to
751     /// `buffer`, and returns the subslice of the buffer that contains the
752     /// encoded UUID.
753     ///
754     /// This is slightly more efficient than using the formatting
755     /// infrastructure as it avoids virtual calls, and may avoid
756     /// double buffering.
757     ///
758     /// [`Uuid`]: ../struct.Uuid.html
759     ///
760     /// # Panics
761     ///
762     /// Panics if the buffer is not large enough: it must have length at least
763     /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
764     /// sufficiently-large temporary buffer.
765     ///
766     /// [`LENGTH`]: #associatedconstant.LENGTH
767     /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
768     ///
769     /// # Examples
770     ///
771     /// ```rust
772     /// use uuid::Uuid;
773     ///
774     /// fn main() -> Result<(), uuid::Error> {
775     ///     let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
776     ///
777     ///     // the encoded portion is returned
778     ///     assert_eq!(
779     ///         uuid.urn().encode_upper(&mut Uuid::encode_buffer()),
780     ///         "urn:uuid:936DA01F-9ABD-4D9D-80C7-02AF85C822A8"
781     ///     );
782     ///
783     ///     // the buffer is mutated directly, and trailing contents remains
784     ///     let mut buf = [b'!'; 49];
785     ///     assert_eq!(
786     ///         uuid.urn().encode_upper(&mut buf),
787     ///         "urn:uuid:936DA01F-9ABD-4D9D-80C7-02AF85C822A8"
788     ///     );
789     ///     assert_eq!(
790     ///         &buf as &[_],
791     ///         b"urn:uuid:936DA01F-9ABD-4D9D-80C7-02AF85C822A8!!!!" as &[_]
792     ///     );
793     ///
794     ///     Ok(())
795     /// }
796     /// ```
797     /// */
798     #[inline]
encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str799     pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
800         encode_urn(self.0.as_bytes(), buffer, true)
801     }
802 
803     /// Get a reference to the underlying [`Uuid`].
804     ///
805     /// # Examples
806     ///
807     /// ```rust
808     /// use uuid::Uuid;
809     ///
810     /// let urn = Uuid::nil().urn();
811     /// assert_eq!(*urn.as_uuid(), Uuid::nil());
812     /// ```
as_uuid(&self) -> &Uuid813     pub const fn as_uuid(&self) -> &Uuid {
814         &self.0
815     }
816 
817     /// Consumes the [`Urn`], returning the underlying [`Uuid`].
818     ///
819     /// # Examples
820     ///
821     /// ```rust
822     /// use uuid::Uuid;
823     ///
824     /// let urn = Uuid::nil().urn();
825     /// assert_eq!(urn.into_uuid(), Uuid::nil());
826     /// ```
into_uuid(self) -> Uuid827     pub const fn into_uuid(self) -> Uuid {
828         self.0
829     }
830 }
831 
832 macro_rules! impl_fmt_traits {
833     ($($T:ident<$($a:lifetime),*>),+) => {$(
834         impl<$($a),*> fmt::Display for $T<$($a),*> {
835             #[inline]
836             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
837                 fmt::LowerHex::fmt(self, f)
838             }
839         }
840 
841         impl<$($a),*> fmt::LowerHex for $T<$($a),*> {
842             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
843                 f.write_str(self.encode_lower(&mut [0; Self::LENGTH]))
844             }
845         }
846 
847         impl<$($a),*> fmt::UpperHex for $T<$($a),*> {
848             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
849                 f.write_str(self.encode_upper(&mut [0; Self::LENGTH]))
850             }
851         }
852 
853         impl_fmt_from!($T<$($a),*>);
854     )+}
855 }
856 
857 macro_rules! impl_fmt_from {
858     ($T:ident<>) => {
859         impl From<Uuid> for $T {
860             #[inline]
861             fn from(f: Uuid) -> Self {
862                 $T(f)
863             }
864         }
865 
866         impl From<$T> for Uuid {
867             #[inline]
868             fn from(f: $T) -> Self {
869                 f.into_uuid()
870             }
871         }
872 
873         impl AsRef<Uuid> for $T {
874             #[inline]
875             fn as_ref(&self) -> &Uuid {
876                 &self.0
877             }
878         }
879 
880         impl Borrow<Uuid> for $T {
881             #[inline]
882             fn borrow(&self) -> &Uuid {
883                 &self.0
884             }
885         }
886     };
887     ($T:ident<$a:lifetime>) => {
888         impl<$a> From<&$a Uuid> for $T<$a> {
889             #[inline]
890             fn from(f: &$a Uuid) -> Self {
891                 $T::from_uuid_ref(f)
892             }
893         }
894 
895         impl<$a> From<$T<$a>> for &$a Uuid {
896             #[inline]
897             fn from(f: $T<$a>) -> &$a Uuid {
898                 f.0
899             }
900         }
901 
902         impl<$a> AsRef<Uuid> for $T<$a> {
903             #[inline]
904             fn as_ref(&self) -> &Uuid {
905                 self.0
906             }
907         }
908 
909         impl<$a> Borrow<Uuid> for $T<$a> {
910             #[inline]
911             fn borrow(&self) -> &Uuid {
912                 self.0
913             }
914         }
915     };
916 }
917 
918 impl_fmt_traits! {
919     Hyphenated<>,
920     Simple<>,
921     Urn<>,
922     Braced<>
923 }
924 
925 #[cfg(test)]
926 mod tests {
927     use super::*;
928 
929     #[test]
hyphenated_trailing()930     fn hyphenated_trailing() {
931         let mut buf = [b'x'; 100];
932         let len = Uuid::nil().hyphenated().encode_lower(&mut buf).len();
933         assert_eq!(len, super::Hyphenated::LENGTH);
934         assert!(buf[len..].iter().all(|x| *x == b'x'));
935     }
936 
937     #[test]
hyphenated_ref_trailing()938     fn hyphenated_ref_trailing() {
939         let mut buf = [b'x'; 100];
940         let len = Uuid::nil().as_hyphenated().encode_lower(&mut buf).len();
941         assert_eq!(len, super::Hyphenated::LENGTH);
942         assert!(buf[len..].iter().all(|x| *x == b'x'));
943     }
944 
945     #[test]
simple_trailing()946     fn simple_trailing() {
947         let mut buf = [b'x'; 100];
948         let len = Uuid::nil().simple().encode_lower(&mut buf).len();
949         assert_eq!(len, super::Simple::LENGTH);
950         assert!(buf[len..].iter().all(|x| *x == b'x'));
951     }
952 
953     #[test]
simple_ref_trailing()954     fn simple_ref_trailing() {
955         let mut buf = [b'x'; 100];
956         let len = Uuid::nil().as_simple().encode_lower(&mut buf).len();
957         assert_eq!(len, super::Simple::LENGTH);
958         assert!(buf[len..].iter().all(|x| *x == b'x'));
959     }
960 
961     #[test]
urn_trailing()962     fn urn_trailing() {
963         let mut buf = [b'x'; 100];
964         let len = Uuid::nil().urn().encode_lower(&mut buf).len();
965         assert_eq!(len, super::Urn::LENGTH);
966         assert!(buf[len..].iter().all(|x| *x == b'x'));
967     }
968 
969     #[test]
urn_ref_trailing()970     fn urn_ref_trailing() {
971         let mut buf = [b'x'; 100];
972         let len = Uuid::nil().as_urn().encode_lower(&mut buf).len();
973         assert_eq!(len, super::Urn::LENGTH);
974         assert!(buf[len..].iter().all(|x| *x == b'x'));
975     }
976 
977     #[test]
braced_trailing()978     fn braced_trailing() {
979         let mut buf = [b'x'; 100];
980         let len = Uuid::nil().braced().encode_lower(&mut buf).len();
981         assert_eq!(len, super::Braced::LENGTH);
982         assert!(buf[len..].iter().all(|x| *x == b'x'));
983     }
984 
985     #[test]
braced_ref_trailing()986     fn braced_ref_trailing() {
987         let mut buf = [b'x'; 100];
988         let len = Uuid::nil().as_braced().encode_lower(&mut buf).len();
989         assert_eq!(len, super::Braced::LENGTH);
990         assert!(buf[len..].iter().all(|x| *x == b'x'));
991     }
992 
993     #[test]
994     #[should_panic]
hyphenated_too_small()995     fn hyphenated_too_small() {
996         Uuid::nil().hyphenated().encode_lower(&mut [0; 35]);
997     }
998 
999     #[test]
1000     #[should_panic]
simple_too_small()1001     fn simple_too_small() {
1002         Uuid::nil().simple().encode_lower(&mut [0; 31]);
1003     }
1004 
1005     #[test]
1006     #[should_panic]
urn_too_small()1007     fn urn_too_small() {
1008         Uuid::nil().urn().encode_lower(&mut [0; 44]);
1009     }
1010 
1011     #[test]
1012     #[should_panic]
braced_too_small()1013     fn braced_too_small() {
1014         Uuid::nil().braced().encode_lower(&mut [0; 37]);
1015     }
1016 
1017     #[test]
hyphenated_to_inner()1018     fn hyphenated_to_inner() {
1019         let hyphenated = Uuid::nil().hyphenated();
1020         assert_eq!(Uuid::from(hyphenated), Uuid::nil());
1021     }
1022 
1023     #[test]
simple_to_inner()1024     fn simple_to_inner() {
1025         let simple = Uuid::nil().simple();
1026         assert_eq!(Uuid::from(simple), Uuid::nil());
1027     }
1028 
1029     #[test]
urn_to_inner()1030     fn urn_to_inner() {
1031         let urn = Uuid::nil().urn();
1032         assert_eq!(Uuid::from(urn), Uuid::nil());
1033     }
1034 
1035     #[test]
braced_to_inner()1036     fn braced_to_inner() {
1037         let braced = Uuid::nil().braced();
1038         assert_eq!(Uuid::from(braced), Uuid::nil());
1039     }
1040 }
1041