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