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