Skip to main content

uuid/
fmt.rs

1// Copyright 2013-2014 The Rust Project Developers.
2// Copyright 2018 The Uuid Project Developers.
3//
4// See the COPYRIGHT file at the top-level directory of this distribution.
5//
6// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
7// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
9// option. This file may not be copied, modified, or distributed
10// except according to those terms.
11
12//! Adapters for alternative string formats.
13
14use core::{mem::MaybeUninit, ptr, slice, str::FromStr};
15
16use crate::{
17    std::{borrow::Borrow, fmt, str},
18    Error, Uuid, Variant,
19};
20
21#[cfg(feature = "std")]
22use crate::std::string::{String, ToString};
23
24impl std::fmt::Debug for Uuid {
25    #[inline]
26    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        fmt::LowerHex::fmt(self, f)
28    }
29}
30
31impl fmt::Display for Uuid {
32    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33        fmt::LowerHex::fmt(self, f)
34    }
35}
36
37#[cfg(feature = "std")]
38impl From<Uuid> for String {
39    fn from(uuid: Uuid) -> Self {
40        uuid.to_string()
41    }
42}
43
44impl fmt::Display for Variant {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        match *self {
47            Variant::NCS => write!(f, "NCS"),
48            Variant::RFC4122 => write!(f, "RFC4122"),
49            Variant::Microsoft => write!(f, "Microsoft"),
50            Variant::Future => write!(f, "Future"),
51        }
52    }
53}
54
55impl fmt::LowerHex for Uuid {
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        fmt::LowerHex::fmt(self.as_hyphenated(), f)
58    }
59}
60
61impl fmt::UpperHex for Uuid {
62    #[inline]
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        fmt::UpperHex::fmt(self.as_hyphenated(), f)
65    }
66}
67
68/// Format a [`Uuid`] as a hyphenated string, like
69/// `67e55044-10b1-426f-9247-bb680e5fe0c8`.
70#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
71#[cfg_attr(
72    all(uuid_unstable, feature = "zerocopy"),
73    derive(
74        zerocopy::IntoBytes,
75        zerocopy::FromBytes,
76        zerocopy::KnownLayout,
77        zerocopy::Immutable,
78        zerocopy::Unaligned
79    )
80)]
81#[repr(transparent)]
82pub struct Hyphenated(Uuid);
83
84/// Format a [`Uuid`] as a simple string, like
85/// `67e5504410b1426f9247bb680e5fe0c8`.
86#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
87#[cfg_attr(
88    all(uuid_unstable, feature = "zerocopy"),
89    derive(
90        zerocopy::IntoBytes,
91        zerocopy::FromBytes,
92        zerocopy::KnownLayout,
93        zerocopy::Immutable,
94        zerocopy::Unaligned
95    )
96)]
97#[repr(transparent)]
98pub struct Simple(Uuid);
99
100/// Format a [`Uuid`] as a URN string, like
101/// `urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8`.
102#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
103#[cfg_attr(
104    all(uuid_unstable, feature = "zerocopy"),
105    derive(
106        zerocopy::IntoBytes,
107        zerocopy::FromBytes,
108        zerocopy::KnownLayout,
109        zerocopy::Immutable,
110        zerocopy::Unaligned
111    )
112)]
113#[repr(transparent)]
114pub struct Urn(Uuid);
115
116/// Format a [`Uuid`] as a braced hyphenated string, like
117/// `{67e55044-10b1-426f-9247-bb680e5fe0c8}`.
118#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
119#[cfg_attr(
120    all(uuid_unstable, feature = "zerocopy"),
121    derive(
122        zerocopy::IntoBytes,
123        zerocopy::FromBytes,
124        zerocopy::KnownLayout,
125        zerocopy::Immutable,
126        zerocopy::Unaligned
127    )
128)]
129#[repr(transparent)]
130pub struct Braced(Uuid);
131
132impl Uuid {
133    /// Get a [`Hyphenated`] formatter.
134    #[inline]
135    pub const fn hyphenated(self) -> Hyphenated {
136        Hyphenated(self)
137    }
138
139    /// Get a borrowed [`Hyphenated`] formatter.
140    #[inline]
141    pub fn as_hyphenated(&self) -> &Hyphenated {
142        unsafe_transmute_ref!(self)
143    }
144
145    /// Get a [`Simple`] formatter.
146    #[inline]
147    pub const fn simple(self) -> Simple {
148        Simple(self)
149    }
150
151    /// Get a borrowed [`Simple`] formatter.
152    #[inline]
153    pub fn as_simple(&self) -> &Simple {
154        unsafe_transmute_ref!(self)
155    }
156
157    /// Get a [`Urn`] formatter.
158    #[inline]
159    pub const fn urn(self) -> Urn {
160        Urn(self)
161    }
162
163    /// Get a borrowed [`Urn`] formatter.
164    #[inline]
165    pub fn as_urn(&self) -> &Urn {
166        unsafe_transmute_ref!(self)
167    }
168
169    /// Get a [`Braced`] formatter.
170    #[inline]
171    pub const fn braced(self) -> Braced {
172        Braced(self)
173    }
174
175    /// Get a borrowed [`Braced`] formatter.
176    #[inline]
177    pub fn as_braced(&self) -> &Braced {
178        unsafe_transmute_ref!(self)
179    }
180}
181
182// Maps a hex nibble (0..=15) to its ASCII character. `alpha_offset` is added
183// for values above 9: 0x27 for lowercase, 0x07 for uppercase.
184#[inline]
185const fn nibble_to_hex(nibble: u8, alpha_offset: u8) -> u8 {
186    nibble + b'0' + if nibble > 9 { alpha_offset } else { 0 }
187}
188
189#[inline]
190const fn format_simple(src: &[u8; 16], upper: bool) -> [u8; 32] {
191    let alpha_offset = if upper { 0x07 } else { 0x27 };
192    let mut dst = [0; 32];
193    let mut i = 0;
194    while i < 16 {
195        let x = src[i];
196        dst[i * 2] = nibble_to_hex(x >> 4, alpha_offset);
197        dst[i * 2 + 1] = nibble_to_hex(x & 0x0f, alpha_offset);
198        i += 1;
199    }
200    dst
201}
202
203#[inline]
204const fn format_hyphenated(src: &[u8; 16], upper: bool) -> [u8; 36] {
205    let simple = format_simple(src, upper);
206    let mut dst = [0; 36];
207
208    let mut i = 0;
209    while i < 8 {
210        dst[i] = simple[i];
211        i += 1;
212    }
213    dst[8] = b'-';
214    while i < 12 {
215        dst[i + 1] = simple[i];
216        i += 1;
217    }
218    dst[13] = b'-';
219    while i < 16 {
220        dst[i + 2] = simple[i];
221        i += 1;
222    }
223    dst[18] = b'-';
224    while i < 20 {
225        dst[i + 3] = simple[i];
226        i += 1;
227    }
228    dst[23] = b'-';
229    while i < 32 {
230        dst[i + 4] = simple[i];
231        i += 1;
232    }
233    dst
234}
235
236#[inline]
237fn encode_simple<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
238    let buf = &mut buffer[..Simple::LENGTH];
239
240    encode_simple_uninit(src, slice_as_uninit_mut(buf), upper)
241}
242
243#[inline]
244fn encode_hyphenated<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
245    let buf = &mut buffer[..Hyphenated::LENGTH];
246
247    encode_hyphenated_uninit(src, slice_as_uninit_mut(buf), upper)
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
254    encode_braced_uninit(src, slice_as_uninit_mut(buf), upper)
255}
256
257#[inline]
258fn encode_urn<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
259    let buf = &mut buffer[..Urn::LENGTH];
260
261    encode_urn_uninit(src, slice_as_uninit_mut(buf), upper)
262}
263
264#[inline]
265fn encode_simple_uninit<'b>(
266    src: &[u8; 16],
267    buffer: &'b mut [MaybeUninit<u8>],
268    upper: bool,
269) -> &'b mut str {
270    let buf = &mut buffer[..Simple::LENGTH];
271    write_bytes(buf, &format_simple(src, upper));
272
273    // SAFETY: The encoded buffer is fully initialized and ASCII encoded.
274    unsafe { assume_init_ascii_mut(buf) }
275}
276
277#[inline]
278fn encode_hyphenated_uninit<'b>(
279    src: &[u8; 16],
280    buffer: &'b mut [MaybeUninit<u8>],
281    upper: bool,
282) -> &'b mut str {
283    let buf = &mut buffer[..Hyphenated::LENGTH];
284    write_bytes(buf, &format_hyphenated(src, upper));
285
286    // SAFETY: The encoded buffer is fully initialized and ASCII encoded.
287    unsafe { assume_init_ascii_mut(buf) }
288}
289
290#[inline]
291fn encode_braced_uninit<'b>(
292    src: &[u8; 16],
293    buffer: &'b mut [MaybeUninit<u8>],
294    upper: bool,
295) -> &'b mut str {
296    let buf = &mut buffer[..Hyphenated::LENGTH + 2];
297
298    #[cfg_attr(all(uuid_unstable, feature = "zerocopy"), derive(zerocopy::IntoBytes))]
299    #[repr(C)]
300    struct BracedBytes {
301        open_curly: u8,
302        hyphenated: [u8; Hyphenated::LENGTH],
303        close_curly: u8,
304    }
305
306    let braced = BracedBytes {
307        open_curly: b'{',
308        hyphenated: format_hyphenated(src, upper),
309        close_curly: b'}',
310    };
311    let braced: [u8; Hyphenated::LENGTH + 2] = unsafe_transmute!(braced);
312
313    write_bytes(buf, &braced);
314
315    // SAFETY: The encoded buffer is fully initialized and ASCII encoded.
316    unsafe { assume_init_ascii_mut(buf) }
317}
318
319#[inline]
320fn encode_urn_uninit<'b>(
321    src: &[u8; 16],
322    buffer: &'b mut [MaybeUninit<u8>],
323    upper: bool,
324) -> &'b mut str {
325    let buf = &mut buffer[..Urn::LENGTH];
326    write_bytes(&mut buf[..9], b"urn:uuid:");
327
328    let dst = &mut buf[9..(9 + Hyphenated::LENGTH)];
329    write_bytes(dst, &format_hyphenated(src, upper));
330
331    // SAFETY: The encoded buffer is fully initialized and ASCII encoded.
332    unsafe { assume_init_ascii_mut(buf) }
333}
334
335#[inline]
336fn write_bytes(dst: &mut [MaybeUninit<u8>], src: &[u8]) {
337    debug_assert_eq!(dst.len(), src.len());
338    let dst = &mut dst[..src.len()];
339
340    // SAFETY: `dst` and `src` are distinct slices, and `dst` has been sliced to
341    // the same length as `src`. `MaybeUninit<u8>` has the same layout as `u8`.
342    unsafe {
343        ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr().cast(), src.len());
344    }
345}
346
347#[inline]
348fn slice_as_uninit_mut(buffer: &mut [u8]) -> &mut [MaybeUninit<u8>] {
349    // SAFETY: `MaybeUninit<u8>` has the same layout as `u8`.
350    unsafe { slice::from_raw_parts_mut(buffer.as_mut_ptr().cast(), buffer.len()) }
351}
352
353#[inline]
354unsafe fn assume_init_ascii_mut(buffer: &mut [MaybeUninit<u8>]) -> &mut str {
355    // SAFETY: The caller guarantees that `buffer` has been initialized.
356    let buffer = unsafe { slice::from_raw_parts_mut(buffer.as_mut_ptr().cast(), buffer.len()) };
357
358    // SAFETY: The caller guarantees that `buffer` is ASCII encoded.
359    unsafe { str::from_utf8_unchecked_mut(buffer) }
360}
361
362impl Hyphenated {
363    /// The length of a hyphenated [`Uuid`] string.
364    ///
365    /// [`Uuid`]: ../struct.Uuid.html
366    pub const LENGTH: usize = 36;
367
368    /// Creates a [`Hyphenated`] from a [`Uuid`].
369    ///
370    /// [`Uuid`]: ../struct.Uuid.html
371    /// [`Hyphenated`]: struct.Hyphenated.html
372    pub const fn from_uuid(uuid: Uuid) -> Self {
373        Hyphenated(uuid)
374    }
375
376    /// Writes the [`Uuid`] as a lower-case hyphenated string to
377    /// `buffer`, and returns the subslice of the buffer that contains the
378    /// encoded UUID.
379    ///
380    /// This is slightly more efficient than using the formatting
381    /// infrastructure as it avoids virtual calls, and may avoid
382    /// double buffering.
383    ///
384    /// [`Uuid`]: ../struct.Uuid.html
385    ///
386    /// # Panics
387    ///
388    /// Panics if the buffer is not large enough: it must have length at least
389    /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
390    /// sufficiently-large temporary buffer.
391    ///
392    /// [`LENGTH`]: #associatedconstant.LENGTH
393    /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
394    ///
395    /// # Examples
396    ///
397    /// ```rust
398    /// use uuid::Uuid;
399    ///
400    /// fn main() -> Result<(), uuid::Error> {
401    ///     let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
402    ///
403    ///     // the encoded portion is returned
404    ///     assert_eq!(
405    ///         uuid.hyphenated()
406    ///             .encode_lower(&mut Uuid::encode_buffer()),
407    ///         "936da01f-9abd-4d9d-80c7-02af85c822a8"
408    ///     );
409    ///
410    ///     // the buffer is mutated directly, and trailing contents remains
411    ///     let mut buf = [b'!'; 40];
412    ///     uuid.hyphenated().encode_lower(&mut buf);
413    ///     assert_eq!(
414    ///         &buf as &[_],
415    ///         b"936da01f-9abd-4d9d-80c7-02af85c822a8!!!!" as &[_]
416    ///     );
417    ///
418    ///     Ok(())
419    /// }
420    /// ```
421    /// */
422    #[inline]
423    pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
424        encode_hyphenated(self.0.as_bytes(), buffer, false)
425    }
426
427    /// Writes the [`Uuid`] as a lower-case hyphenated string to a
428    /// possibly-uninitialized `buffer`, and returns the subslice of the buffer
429    /// that contains the encoded UUID.
430    ///
431    /// This initializes the returned subslice of `buffer`. Bytes outside of the
432    /// returned subslice are not written.
433    ///
434    /// [`Uuid`]: ../struct.Uuid.html
435    ///
436    /// # Panics
437    ///
438    /// Panics if the buffer is not large enough: it must have length at least
439    /// [`LENGTH`].
440    ///
441    /// [`LENGTH`]: #associatedconstant.LENGTH
442    #[inline]
443    pub fn encode_lower_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
444        encode_hyphenated_uninit(self.0.as_bytes(), buffer, false)
445    }
446
447    /// Writes the [`Uuid`] as an upper-case hyphenated string to
448    /// `buffer`, and returns the subslice of the buffer that contains the
449    /// 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.hyphenated()
477    ///             .encode_upper(&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.hyphenated().encode_upper(&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_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
495        encode_hyphenated(self.0.as_bytes(), buffer, true)
496    }
497
498    /// Writes the [`Uuid`] as an upper-case hyphenated string to a
499    /// possibly-uninitialized `buffer`, and returns the subslice of the buffer
500    /// that contains the encoded UUID.
501    ///
502    /// This initializes the returned subslice of `buffer`. Bytes outside of the
503    /// returned subslice are not written.
504    ///
505    /// [`Uuid`]: ../struct.Uuid.html
506    ///
507    /// # Panics
508    ///
509    /// Panics if the buffer is not large enough: it must have length at least
510    /// [`LENGTH`].
511    ///
512    /// [`LENGTH`]: #associatedconstant.LENGTH
513    #[inline]
514    pub fn encode_upper_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
515        encode_hyphenated_uninit(self.0.as_bytes(), buffer, true)
516    }
517
518    /// Get a reference to the underlying [`Uuid`].
519    ///
520    /// # Examples
521    ///
522    /// ```rust
523    /// use uuid::Uuid;
524    ///
525    /// let hyphenated = Uuid::nil().hyphenated();
526    /// assert_eq!(*hyphenated.as_uuid(), Uuid::nil());
527    /// ```
528    pub const fn as_uuid(&self) -> &Uuid {
529        &self.0
530    }
531
532    /// Consumes the [`Hyphenated`], returning the underlying [`Uuid`].
533    ///
534    /// # Examples
535    ///
536    /// ```rust
537    /// use uuid::Uuid;
538    ///
539    /// let hyphenated = Uuid::nil().hyphenated();
540    /// assert_eq!(hyphenated.into_uuid(), Uuid::nil());
541    /// ```
542    pub const fn into_uuid(self) -> Uuid {
543        self.0
544    }
545}
546
547impl Braced {
548    /// The length of a braced [`Uuid`] string.
549    ///
550    /// [`Uuid`]: ../struct.Uuid.html
551    pub const LENGTH: usize = 38;
552
553    /// Creates a [`Braced`] from a [`Uuid`].
554    ///
555    /// [`Uuid`]: ../struct.Uuid.html
556    /// [`Braced`]: struct.Braced.html
557    pub const fn from_uuid(uuid: Uuid) -> Self {
558        Braced(uuid)
559    }
560
561    /// Writes the [`Uuid`] as a lower-case hyphenated string surrounded by
562    /// braces to `buffer`, and returns the subslice of the buffer that contains
563    /// the encoded UUID.
564    ///
565    /// This is slightly more efficient than using the formatting
566    /// infrastructure as it avoids virtual calls, and may avoid
567    /// double buffering.
568    ///
569    /// [`Uuid`]: ../struct.Uuid.html
570    ///
571    /// # Panics
572    ///
573    /// Panics if the buffer is not large enough: it must have length at least
574    /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
575    /// sufficiently-large temporary buffer.
576    ///
577    /// [`LENGTH`]: #associatedconstant.LENGTH
578    /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
579    ///
580    /// # Examples
581    ///
582    /// ```rust
583    /// use uuid::Uuid;
584    ///
585    /// fn main() -> Result<(), uuid::Error> {
586    ///     let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
587    ///
588    ///     // the encoded portion is returned
589    ///     assert_eq!(
590    ///         uuid.braced()
591    ///             .encode_lower(&mut Uuid::encode_buffer()),
592    ///         "{936da01f-9abd-4d9d-80c7-02af85c822a8}"
593    ///     );
594    ///
595    ///     // the buffer is mutated directly, and trailing contents remains
596    ///     let mut buf = [b'!'; 40];
597    ///     uuid.braced().encode_lower(&mut buf);
598    ///     assert_eq!(
599    ///         &buf as &[_],
600    ///         b"{936da01f-9abd-4d9d-80c7-02af85c822a8}!!" as &[_]
601    ///     );
602    ///
603    ///     Ok(())
604    /// }
605    /// ```
606    /// */
607    #[inline]
608    pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
609        encode_braced(self.0.as_bytes(), buffer, false)
610    }
611
612    /// Writes the [`Uuid`] as a lower-case hyphenated string surrounded by
613    /// braces to a possibly-uninitialized `buffer`, and returns the subslice of
614    /// the buffer that contains the encoded UUID.
615    ///
616    /// This initializes the returned subslice of `buffer`. Bytes outside of the
617    /// returned subslice are not written.
618    ///
619    /// [`Uuid`]: ../struct.Uuid.html
620    ///
621    /// # Panics
622    ///
623    /// Panics if the buffer is not large enough: it must have length at least
624    /// [`LENGTH`].
625    ///
626    /// [`LENGTH`]: #associatedconstant.LENGTH
627    #[inline]
628    pub fn encode_lower_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
629        encode_braced_uninit(self.0.as_bytes(), buffer, false)
630    }
631
632    /// Writes the [`Uuid`] as an upper-case hyphenated string surrounded by
633    /// braces to `buffer`, and returns the subslice of the buffer that contains
634    /// the encoded UUID.
635    ///
636    /// This is slightly more efficient than using the formatting
637    /// infrastructure as it avoids virtual calls, and may avoid
638    /// double buffering.
639    ///
640    /// [`Uuid`]: ../struct.Uuid.html
641    ///
642    /// # Panics
643    ///
644    /// Panics if the buffer is not large enough: it must have length at least
645    /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
646    /// sufficiently-large temporary buffer.
647    ///
648    /// [`LENGTH`]: #associatedconstant.LENGTH
649    /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
650    ///
651    /// # Examples
652    ///
653    /// ```rust
654    /// use uuid::Uuid;
655    ///
656    /// fn main() -> Result<(), uuid::Error> {
657    ///     let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
658    ///
659    ///     // the encoded portion is returned
660    ///     assert_eq!(
661    ///         uuid.braced()
662    ///             .encode_upper(&mut Uuid::encode_buffer()),
663    ///         "{936DA01F-9ABD-4D9D-80C7-02AF85C822A8}"
664    ///     );
665    ///
666    ///     // the buffer is mutated directly, and trailing contents remains
667    ///     let mut buf = [b'!'; 40];
668    ///     uuid.braced().encode_upper(&mut buf);
669    ///     assert_eq!(
670    ///         &buf as &[_],
671    ///         b"{936DA01F-9ABD-4D9D-80C7-02AF85C822A8}!!" as &[_]
672    ///     );
673    ///
674    ///     Ok(())
675    /// }
676    /// ```
677    /// */
678    #[inline]
679    pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
680        encode_braced(self.0.as_bytes(), buffer, true)
681    }
682
683    /// Writes the [`Uuid`] as an upper-case hyphenated string surrounded by
684    /// braces to a possibly-uninitialized `buffer`, and returns the subslice of
685    /// the buffer that contains the encoded UUID.
686    ///
687    /// This initializes the returned subslice of `buffer`. Bytes outside of the
688    /// returned subslice are not written.
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`].
696    ///
697    /// [`LENGTH`]: #associatedconstant.LENGTH
698    #[inline]
699    pub fn encode_upper_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
700        encode_braced_uninit(self.0.as_bytes(), buffer, true)
701    }
702
703    /// Get a reference to the underlying [`Uuid`].
704    ///
705    /// # Examples
706    ///
707    /// ```rust
708    /// use uuid::Uuid;
709    ///
710    /// let braced = Uuid::nil().braced();
711    /// assert_eq!(*braced.as_uuid(), Uuid::nil());
712    /// ```
713    pub const fn as_uuid(&self) -> &Uuid {
714        &self.0
715    }
716
717    /// Consumes the [`Braced`], returning the underlying [`Uuid`].
718    ///
719    /// # Examples
720    ///
721    /// ```rust
722    /// use uuid::Uuid;
723    ///
724    /// let braced = Uuid::nil().braced();
725    /// assert_eq!(braced.into_uuid(), Uuid::nil());
726    /// ```
727    pub const fn into_uuid(self) -> Uuid {
728        self.0
729    }
730}
731
732impl Simple {
733    /// The length of a simple [`Uuid`] string.
734    ///
735    /// [`Uuid`]: ../struct.Uuid.html
736    pub const LENGTH: usize = 32;
737
738    /// Creates a [`Simple`] from a [`Uuid`].
739    ///
740    /// [`Uuid`]: ../struct.Uuid.html
741    /// [`Simple`]: struct.Simple.html
742    pub const fn from_uuid(uuid: Uuid) -> Self {
743        Simple(uuid)
744    }
745
746    /// Writes the [`Uuid`] as a lower-case simple string to `buffer`,
747    /// and returns the subslice of the buffer that contains the encoded UUID.
748    ///
749    /// This is slightly more efficient than using the formatting
750    /// infrastructure as it avoids virtual calls, and may avoid
751    /// double buffering.
752    ///
753    /// [`Uuid`]: ../struct.Uuid.html
754    ///
755    /// # Panics
756    ///
757    /// Panics if the buffer is not large enough: it must have length at least
758    /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
759    /// sufficiently-large temporary buffer.
760    ///
761    /// [`LENGTH`]: #associatedconstant.LENGTH
762    /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
763    ///
764    /// # Examples
765    ///
766    /// ```rust
767    /// use uuid::Uuid;
768    ///
769    /// fn main() -> Result<(), uuid::Error> {
770    ///     let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
771    ///
772    ///     // the encoded portion is returned
773    ///     assert_eq!(
774    ///         uuid.simple().encode_lower(&mut Uuid::encode_buffer()),
775    ///         "936da01f9abd4d9d80c702af85c822a8"
776    ///     );
777    ///
778    ///     // the buffer is mutated directly, and trailing contents remains
779    ///     let mut buf = [b'!'; 36];
780    ///     assert_eq!(
781    ///         uuid.simple().encode_lower(&mut buf),
782    ///         "936da01f9abd4d9d80c702af85c822a8"
783    ///     );
784    ///     assert_eq!(
785    ///         &buf as &[_],
786    ///         b"936da01f9abd4d9d80c702af85c822a8!!!!" as &[_]
787    ///     );
788    ///
789    ///     Ok(())
790    /// }
791    /// ```
792    /// */
793    #[inline]
794    pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
795        encode_simple(self.0.as_bytes(), buffer, false)
796    }
797
798    /// Writes the [`Uuid`] as a lower-case simple string to a
799    /// possibly-uninitialized `buffer`, and returns the subslice of the buffer
800    /// that contains the encoded UUID.
801    ///
802    /// This initializes the returned subslice of `buffer`. Bytes outside of the
803    /// returned subslice are not written.
804    ///
805    /// [`Uuid`]: ../struct.Uuid.html
806    ///
807    /// # Panics
808    ///
809    /// Panics if the buffer is not large enough: it must have length at least
810    /// [`LENGTH`].
811    ///
812    /// [`LENGTH`]: #associatedconstant.LENGTH
813    #[inline]
814    pub fn encode_lower_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
815        encode_simple_uninit(self.0.as_bytes(), buffer, false)
816    }
817
818    /// Writes the [`Uuid`] as an upper-case simple string to `buffer`,
819    /// and returns the subslice of the buffer that contains the encoded UUID.
820    ///
821    /// [`Uuid`]: ../struct.Uuid.html
822    ///
823    /// # Panics
824    ///
825    /// Panics if the buffer is not large enough: it must have length at least
826    /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
827    /// sufficiently-large temporary buffer.
828    ///
829    /// [`LENGTH`]: #associatedconstant.LENGTH
830    /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
831    ///
832    /// # Examples
833    ///
834    /// ```rust
835    /// use uuid::Uuid;
836    ///
837    /// fn main() -> Result<(), uuid::Error> {
838    ///     let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
839    ///
840    ///     // the encoded portion is returned
841    ///     assert_eq!(
842    ///         uuid.simple().encode_upper(&mut Uuid::encode_buffer()),
843    ///         "936DA01F9ABD4D9D80C702AF85C822A8"
844    ///     );
845    ///
846    ///     // the buffer is mutated directly, and trailing contents remains
847    ///     let mut buf = [b'!'; 36];
848    ///     assert_eq!(
849    ///         uuid.simple().encode_upper(&mut buf),
850    ///         "936DA01F9ABD4D9D80C702AF85C822A8"
851    ///     );
852    ///     assert_eq!(
853    ///         &buf as &[_],
854    ///         b"936DA01F9ABD4D9D80C702AF85C822A8!!!!" as &[_]
855    ///     );
856    ///
857    ///     Ok(())
858    /// }
859    /// ```
860    /// */
861    #[inline]
862    pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
863        encode_simple(self.0.as_bytes(), buffer, true)
864    }
865
866    /// Writes the [`Uuid`] as an upper-case simple string to a
867    /// possibly-uninitialized `buffer`, and returns the subslice of the buffer
868    /// that contains the encoded UUID.
869    ///
870    /// This initializes the returned subslice of `buffer`. Bytes outside of the
871    /// returned subslice are not written.
872    ///
873    /// [`Uuid`]: ../struct.Uuid.html
874    ///
875    /// # Panics
876    ///
877    /// Panics if the buffer is not large enough: it must have length at least
878    /// [`LENGTH`].
879    ///
880    /// [`LENGTH`]: #associatedconstant.LENGTH
881    #[inline]
882    pub fn encode_upper_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
883        encode_simple_uninit(self.0.as_bytes(), buffer, true)
884    }
885
886    /// Get a reference to the underlying [`Uuid`].
887    ///
888    /// # Examples
889    ///
890    /// ```rust
891    /// use uuid::Uuid;
892    ///
893    /// let simple = Uuid::nil().simple();
894    /// assert_eq!(*simple.as_uuid(), Uuid::nil());
895    /// ```
896    pub const fn as_uuid(&self) -> &Uuid {
897        &self.0
898    }
899
900    /// Consumes the [`Simple`], returning the underlying [`Uuid`].
901    ///
902    /// # Examples
903    ///
904    /// ```rust
905    /// use uuid::Uuid;
906    ///
907    /// let simple = Uuid::nil().simple();
908    /// assert_eq!(simple.into_uuid(), Uuid::nil());
909    /// ```
910    pub const fn into_uuid(self) -> Uuid {
911        self.0
912    }
913}
914
915impl Urn {
916    /// The length of a URN [`Uuid`] string.
917    ///
918    /// [`Uuid`]: ../struct.Uuid.html
919    pub const LENGTH: usize = 45;
920
921    /// Creates a [`Urn`] from a [`Uuid`].
922    ///
923    /// [`Uuid`]: ../struct.Uuid.html
924    /// [`Urn`]: struct.Urn.html
925    pub const fn from_uuid(uuid: Uuid) -> Self {
926        Urn(uuid)
927    }
928
929    /// Writes the [`Uuid`] as a lower-case URN string to
930    /// `buffer`, and returns the subslice of the buffer that contains the
931    /// encoded UUID.
932    ///
933    /// This is slightly more efficient than using the formatting
934    /// infrastructure as it avoids virtual calls, and may avoid
935    /// double buffering.
936    ///
937    /// [`Uuid`]: ../struct.Uuid.html
938    ///
939    /// # Panics
940    ///
941    /// Panics if the buffer is not large enough: it must have length at least
942    /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
943    /// sufficiently-large temporary buffer.
944    ///
945    /// [`LENGTH`]: #associatedconstant.LENGTH
946    /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
947    ///
948    /// # Examples
949    ///
950    /// ```rust
951    /// use uuid::Uuid;
952    ///
953    /// fn main() -> Result<(), uuid::Error> {
954    ///     let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
955    ///
956    ///     // the encoded portion is returned
957    ///     assert_eq!(
958    ///         uuid.urn().encode_lower(&mut Uuid::encode_buffer()),
959    ///         "urn:uuid:936da01f-9abd-4d9d-80c7-02af85c822a8"
960    ///     );
961    ///
962    ///     // the buffer is mutated directly, and trailing contents remains
963    ///     let mut buf = [b'!'; 49];
964    ///     uuid.urn().encode_lower(&mut buf);
965    ///     assert_eq!(
966    ///         uuid.urn().encode_lower(&mut buf),
967    ///         "urn:uuid:936da01f-9abd-4d9d-80c7-02af85c822a8"
968    ///     );
969    ///     assert_eq!(
970    ///         &buf as &[_],
971    ///         b"urn:uuid:936da01f-9abd-4d9d-80c7-02af85c822a8!!!!" as &[_]
972    ///     );
973    ///     
974    ///     Ok(())
975    /// }
976    /// ```
977    /// */
978    #[inline]
979    pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
980        encode_urn(self.0.as_bytes(), buffer, false)
981    }
982
983    /// Writes the [`Uuid`] as a lower-case URN string to a
984    /// possibly-uninitialized `buffer`, and returns the subslice of the buffer
985    /// that contains the encoded UUID.
986    ///
987    /// This initializes the returned subslice of `buffer`. Bytes outside of the
988    /// returned subslice are not written.
989    ///
990    /// [`Uuid`]: ../struct.Uuid.html
991    ///
992    /// # Panics
993    ///
994    /// Panics if the buffer is not large enough: it must have length at least
995    /// [`LENGTH`].
996    ///
997    /// [`LENGTH`]: #associatedconstant.LENGTH
998    #[inline]
999    pub fn encode_lower_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
1000        encode_urn_uninit(self.0.as_bytes(), buffer, false)
1001    }
1002
1003    /// Writes the [`Uuid`] as an upper-case URN string to
1004    /// `buffer`, and returns the subslice of the buffer that contains the
1005    /// encoded UUID.
1006    ///
1007    /// This is slightly more efficient than using the formatting
1008    /// infrastructure as it avoids virtual calls, and may avoid
1009    /// double buffering.
1010    ///
1011    /// [`Uuid`]: ../struct.Uuid.html
1012    ///
1013    /// # Panics
1014    ///
1015    /// Panics if the buffer is not large enough: it must have length at least
1016    /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
1017    /// sufficiently-large temporary buffer.
1018    ///
1019    /// [`LENGTH`]: #associatedconstant.LENGTH
1020    /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
1021    ///
1022    /// # Examples
1023    ///
1024    /// ```rust
1025    /// use uuid::Uuid;
1026    ///
1027    /// fn main() -> Result<(), uuid::Error> {
1028    ///     let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
1029    ///
1030    ///     // the encoded portion is returned
1031    ///     assert_eq!(
1032    ///         uuid.urn().encode_upper(&mut Uuid::encode_buffer()),
1033    ///         "urn:uuid:936DA01F-9ABD-4D9D-80C7-02AF85C822A8"
1034    ///     );
1035    ///
1036    ///     // the buffer is mutated directly, and trailing contents remains
1037    ///     let mut buf = [b'!'; 49];
1038    ///     assert_eq!(
1039    ///         uuid.urn().encode_upper(&mut buf),
1040    ///         "urn:uuid:936DA01F-9ABD-4D9D-80C7-02AF85C822A8"
1041    ///     );
1042    ///     assert_eq!(
1043    ///         &buf as &[_],
1044    ///         b"urn:uuid:936DA01F-9ABD-4D9D-80C7-02AF85C822A8!!!!" as &[_]
1045    ///     );
1046    ///
1047    ///     Ok(())
1048    /// }
1049    /// ```
1050    /// */
1051    #[inline]
1052    pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
1053        encode_urn(self.0.as_bytes(), buffer, true)
1054    }
1055
1056    /// Writes the [`Uuid`] as an upper-case URN string to a
1057    /// possibly-uninitialized `buffer`, and returns the subslice of the buffer
1058    /// that contains the encoded UUID.
1059    ///
1060    /// This initializes the returned subslice of `buffer`. Bytes outside of the
1061    /// returned subslice are not written.
1062    ///
1063    /// [`Uuid`]: ../struct.Uuid.html
1064    ///
1065    /// # Panics
1066    ///
1067    /// Panics if the buffer is not large enough: it must have length at least
1068    /// [`LENGTH`].
1069    ///
1070    /// [`LENGTH`]: #associatedconstant.LENGTH
1071    #[inline]
1072    pub fn encode_upper_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
1073        encode_urn_uninit(self.0.as_bytes(), buffer, true)
1074    }
1075
1076    /// Get a reference to the underlying [`Uuid`].
1077    ///
1078    /// # Examples
1079    ///
1080    /// ```rust
1081    /// use uuid::Uuid;
1082    ///
1083    /// let urn = Uuid::nil().urn();
1084    /// assert_eq!(*urn.as_uuid(), Uuid::nil());
1085    /// ```
1086    pub const fn as_uuid(&self) -> &Uuid {
1087        &self.0
1088    }
1089
1090    /// Consumes the [`Urn`], returning the underlying [`Uuid`].
1091    ///
1092    /// # Examples
1093    ///
1094    /// ```rust
1095    /// use uuid::Uuid;
1096    ///
1097    /// let urn = Uuid::nil().urn();
1098    /// assert_eq!(urn.into_uuid(), Uuid::nil());
1099    /// ```
1100    pub const fn into_uuid(self) -> Uuid {
1101        self.0
1102    }
1103}
1104
1105impl FromStr for Hyphenated {
1106    type Err = Error;
1107
1108    fn from_str(s: &str) -> Result<Self, Self::Err> {
1109        crate::parser::parse_hyphenated(s.as_bytes())
1110            .map(|b| Hyphenated(Uuid(b)))
1111            .map_err(|invalid| invalid.into_err())
1112    }
1113}
1114
1115impl FromStr for Simple {
1116    type Err = Error;
1117
1118    fn from_str(s: &str) -> Result<Self, Self::Err> {
1119        crate::parser::parse_simple(s.as_bytes(), false)
1120            .map(|b| Simple(Uuid(b)))
1121            .map_err(|invalid| invalid.into_err())
1122    }
1123}
1124
1125impl FromStr for Urn {
1126    type Err = Error;
1127
1128    fn from_str(s: &str) -> Result<Self, Self::Err> {
1129        crate::parser::parse_urn(s.as_bytes())
1130            .map(|b| Urn(Uuid(b)))
1131            .map_err(|invalid| invalid.into_err())
1132    }
1133}
1134
1135impl FromStr for Braced {
1136    type Err = Error;
1137
1138    fn from_str(s: &str) -> Result<Self, Self::Err> {
1139        crate::parser::parse_braced(s.as_bytes())
1140            .map(|b| Braced(Uuid(b)))
1141            .map_err(|invalid| invalid.into_err())
1142    }
1143}
1144
1145macro_rules! impl_fmt_traits {
1146    ($($T:ident<$($a:lifetime),*>),+) => {$(
1147        impl<$($a),*> fmt::Display for $T<$($a),*> {
1148            #[inline]
1149            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1150                fmt::LowerHex::fmt(self, f)
1151            }
1152        }
1153
1154        impl<$($a),*> fmt::LowerHex for $T<$($a),*> {
1155            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1156                f.write_str(self.encode_lower(&mut [0; Self::LENGTH]))
1157            }
1158        }
1159
1160        impl<$($a),*> fmt::UpperHex for $T<$($a),*> {
1161            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1162                f.write_str(self.encode_upper(&mut [0; Self::LENGTH]))
1163            }
1164        }
1165
1166        impl_fmt_from!($T<$($a),*>);
1167    )+}
1168}
1169
1170macro_rules! impl_fmt_from {
1171    ($T:ident<>) => {
1172        impl From<Uuid> for $T {
1173            #[inline]
1174            fn from(f: Uuid) -> Self {
1175                $T(f)
1176            }
1177        }
1178
1179        impl From<$T> for Uuid {
1180            #[inline]
1181            fn from(f: $T) -> Self {
1182                f.into_uuid()
1183            }
1184        }
1185
1186        impl AsRef<Uuid> for $T {
1187            #[inline]
1188            fn as_ref(&self) -> &Uuid {
1189                &self.0
1190            }
1191        }
1192
1193        impl Borrow<Uuid> for $T {
1194            #[inline]
1195            fn borrow(&self) -> &Uuid {
1196                &self.0
1197            }
1198        }
1199    };
1200    ($T:ident<$a:lifetime>) => {
1201        impl<$a> From<&$a Uuid> for $T<$a> {
1202            #[inline]
1203            fn from(f: &$a Uuid) -> Self {
1204                $T::from_uuid_ref(f)
1205            }
1206        }
1207
1208        impl<$a> From<$T<$a>> for &$a Uuid {
1209            #[inline]
1210            fn from(f: $T<$a>) -> &$a Uuid {
1211                f.0
1212            }
1213        }
1214
1215        impl<$a> AsRef<Uuid> for $T<$a> {
1216            #[inline]
1217            fn as_ref(&self) -> &Uuid {
1218                self.0
1219            }
1220        }
1221
1222        impl<$a> Borrow<Uuid> for $T<$a> {
1223            #[inline]
1224            fn borrow(&self) -> &Uuid {
1225                self.0
1226            }
1227        }
1228    };
1229}
1230
1231impl_fmt_traits! {
1232    Hyphenated<>,
1233    Simple<>,
1234    Urn<>,
1235    Braced<>
1236}
1237
1238#[cfg(test)]
1239mod tests {
1240    use super::*;
1241
1242    use core::mem::MaybeUninit;
1243
1244    #[test]
1245    fn encode_lower_uninit() {
1246        let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8").unwrap();
1247
1248        let mut buf = [MaybeUninit::new(b'x'); 100];
1249        let len = {
1250            let encoded = uuid.hyphenated().encode_lower_uninit(&mut buf);
1251            assert_eq!(encoded, "936da01f-9abd-4d9d-80c7-02af85c822a8");
1252            encoded.len()
1253        };
1254        assert_eq!(len, Hyphenated::LENGTH);
1255        assert_uninit_tail_unchanged(&buf, len);
1256
1257        let mut buf = [MaybeUninit::new(b'x'); 100];
1258        let len = {
1259            let encoded = uuid.simple().encode_lower_uninit(&mut buf);
1260            assert_eq!(encoded, "936da01f9abd4d9d80c702af85c822a8");
1261            encoded.len()
1262        };
1263        assert_eq!(len, Simple::LENGTH);
1264        assert_uninit_tail_unchanged(&buf, len);
1265
1266        let mut buf = [MaybeUninit::new(b'x'); 100];
1267        let len = {
1268            let encoded = uuid.urn().encode_lower_uninit(&mut buf);
1269            assert_eq!(encoded, "urn:uuid:936da01f-9abd-4d9d-80c7-02af85c822a8");
1270            encoded.len()
1271        };
1272        assert_eq!(len, Urn::LENGTH);
1273        assert_uninit_tail_unchanged(&buf, len);
1274
1275        let mut buf = [MaybeUninit::new(b'x'); 100];
1276        let len = {
1277            let encoded = uuid.braced().encode_lower_uninit(&mut buf);
1278            assert_eq!(encoded, "{936da01f-9abd-4d9d-80c7-02af85c822a8}");
1279            encoded.len()
1280        };
1281        assert_eq!(len, Braced::LENGTH);
1282        assert_uninit_tail_unchanged(&buf, len);
1283    }
1284
1285    #[test]
1286    fn encode_upper_uninit() {
1287        let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8").unwrap();
1288
1289        let mut buf = [MaybeUninit::new(b'x'); 100];
1290        let len = {
1291            let encoded = uuid.hyphenated().encode_upper_uninit(&mut buf);
1292            assert_eq!(encoded, "936DA01F-9ABD-4D9D-80C7-02AF85C822A8");
1293            encoded.len()
1294        };
1295        assert_eq!(len, Hyphenated::LENGTH);
1296        assert_uninit_tail_unchanged(&buf, len);
1297
1298        let mut buf = [MaybeUninit::new(b'x'); 100];
1299        let len = {
1300            let encoded = uuid.simple().encode_upper_uninit(&mut buf);
1301            assert_eq!(encoded, "936DA01F9ABD4D9D80C702AF85C822A8");
1302            encoded.len()
1303        };
1304        assert_eq!(len, Simple::LENGTH);
1305        assert_uninit_tail_unchanged(&buf, len);
1306
1307        let mut buf = [MaybeUninit::new(b'x'); 100];
1308        let len = {
1309            let encoded = uuid.urn().encode_upper_uninit(&mut buf);
1310            assert_eq!(encoded, "urn:uuid:936DA01F-9ABD-4D9D-80C7-02AF85C822A8");
1311            encoded.len()
1312        };
1313        assert_eq!(len, Urn::LENGTH);
1314        assert_uninit_tail_unchanged(&buf, len);
1315
1316        let mut buf = [MaybeUninit::new(b'x'); 100];
1317        let len = {
1318            let encoded = uuid.braced().encode_upper_uninit(&mut buf);
1319            assert_eq!(encoded, "{936DA01F-9ABD-4D9D-80C7-02AF85C822A8}");
1320            encoded.len()
1321        };
1322        assert_eq!(len, Braced::LENGTH);
1323        assert_uninit_tail_unchanged(&buf, len);
1324    }
1325
1326    fn assert_uninit_tail_unchanged(buffer: &[MaybeUninit<u8>], initialized: usize) {
1327        // SAFETY: The test initializes the full buffer before encoding.
1328        let buffer: &[u8] =
1329            unsafe { core::slice::from_raw_parts(buffer.as_ptr().cast(), buffer.len()) };
1330
1331        assert!(buffer[initialized..].iter().all(|b| *b == b'x'));
1332    }
1333
1334    #[test]
1335    fn hyphenated_trailing() {
1336        let mut buf = [b'x'; 100];
1337        let len = Uuid::nil().hyphenated().encode_lower(&mut buf).len();
1338        assert_eq!(len, super::Hyphenated::LENGTH);
1339        assert!(buf[len..].iter().all(|x| *x == b'x'));
1340    }
1341
1342    #[test]
1343    fn hyphenated_ref_trailing() {
1344        let mut buf = [b'x'; 100];
1345        let len = Uuid::nil().as_hyphenated().encode_lower(&mut buf).len();
1346        assert_eq!(len, super::Hyphenated::LENGTH);
1347        assert!(buf[len..].iter().all(|x| *x == b'x'));
1348    }
1349
1350    #[test]
1351    fn simple_trailing() {
1352        let mut buf = [b'x'; 100];
1353        let len = Uuid::nil().simple().encode_lower(&mut buf).len();
1354        assert_eq!(len, super::Simple::LENGTH);
1355        assert!(buf[len..].iter().all(|x| *x == b'x'));
1356    }
1357
1358    #[test]
1359    fn simple_ref_trailing() {
1360        let mut buf = [b'x'; 100];
1361        let len = Uuid::nil().as_simple().encode_lower(&mut buf).len();
1362        assert_eq!(len, super::Simple::LENGTH);
1363        assert!(buf[len..].iter().all(|x| *x == b'x'));
1364    }
1365
1366    #[test]
1367    fn urn_trailing() {
1368        let mut buf = [b'x'; 100];
1369        let len = Uuid::nil().urn().encode_lower(&mut buf).len();
1370        assert_eq!(len, super::Urn::LENGTH);
1371        assert!(buf[len..].iter().all(|x| *x == b'x'));
1372    }
1373
1374    #[test]
1375    fn urn_ref_trailing() {
1376        let mut buf = [b'x'; 100];
1377        let len = Uuid::nil().as_urn().encode_lower(&mut buf).len();
1378        assert_eq!(len, super::Urn::LENGTH);
1379        assert!(buf[len..].iter().all(|x| *x == b'x'));
1380    }
1381
1382    #[test]
1383    fn braced_trailing() {
1384        let mut buf = [b'x'; 100];
1385        let len = Uuid::nil().braced().encode_lower(&mut buf).len();
1386        assert_eq!(len, super::Braced::LENGTH);
1387        assert!(buf[len..].iter().all(|x| *x == b'x'));
1388    }
1389
1390    #[test]
1391    fn braced_ref_trailing() {
1392        let mut buf = [b'x'; 100];
1393        let len = Uuid::nil().as_braced().encode_lower(&mut buf).len();
1394        assert_eq!(len, super::Braced::LENGTH);
1395        assert!(buf[len..].iter().all(|x| *x == b'x'));
1396    }
1397
1398    #[test]
1399    #[should_panic]
1400    fn hyphenated_too_small() {
1401        Uuid::nil().hyphenated().encode_lower(&mut [0; 35]);
1402    }
1403
1404    #[test]
1405    #[should_panic]
1406    fn simple_too_small() {
1407        Uuid::nil().simple().encode_lower(&mut [0; 31]);
1408    }
1409
1410    #[test]
1411    #[should_panic]
1412    fn urn_too_small() {
1413        Uuid::nil().urn().encode_lower(&mut [0; 44]);
1414    }
1415
1416    #[test]
1417    #[should_panic]
1418    fn braced_too_small() {
1419        Uuid::nil().braced().encode_lower(&mut [0; 37]);
1420    }
1421
1422    #[test]
1423    fn hyphenated_to_inner() {
1424        let hyphenated = Uuid::nil().hyphenated();
1425        assert_eq!(Uuid::from(hyphenated), Uuid::nil());
1426    }
1427
1428    #[test]
1429    fn simple_to_inner() {
1430        let simple = Uuid::nil().simple();
1431        assert_eq!(Uuid::from(simple), Uuid::nil());
1432    }
1433
1434    #[test]
1435    fn urn_to_inner() {
1436        let urn = Uuid::nil().urn();
1437        assert_eq!(Uuid::from(urn), Uuid::nil());
1438    }
1439
1440    #[test]
1441    fn braced_to_inner() {
1442        let braced = Uuid::nil().braced();
1443        assert_eq!(Uuid::from(braced), Uuid::nil());
1444    }
1445}