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