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