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