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}