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