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