Skip to main content

uuid/
fmt.rs

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