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