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::{mem::MaybeUninit, ptr, slice, 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(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
71#[cfg_attr(
72 all(uuid_unstable, feature = "zerocopy"),
73 derive(
74 zerocopy::IntoBytes,
75 zerocopy::FromBytes,
76 zerocopy::KnownLayout,
77 zerocopy::Immutable,
78 zerocopy::Unaligned
79 )
80)]
81#[repr(transparent)]
82pub struct Hyphenated(Uuid);
83
84/// Format a [`Uuid`] as a simple string, like
85/// `67e5504410b1426f9247bb680e5fe0c8`.
86#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
87#[cfg_attr(
88 all(uuid_unstable, feature = "zerocopy"),
89 derive(
90 zerocopy::IntoBytes,
91 zerocopy::FromBytes,
92 zerocopy::KnownLayout,
93 zerocopy::Immutable,
94 zerocopy::Unaligned
95 )
96)]
97#[repr(transparent)]
98pub struct Simple(Uuid);
99
100/// Format a [`Uuid`] as a URN string, like
101/// `urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8`.
102#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
103#[cfg_attr(
104 all(uuid_unstable, feature = "zerocopy"),
105 derive(
106 zerocopy::IntoBytes,
107 zerocopy::FromBytes,
108 zerocopy::KnownLayout,
109 zerocopy::Immutable,
110 zerocopy::Unaligned
111 )
112)]
113#[repr(transparent)]
114pub struct Urn(Uuid);
115
116/// Format a [`Uuid`] as a braced hyphenated string, like
117/// `{67e55044-10b1-426f-9247-bb680e5fe0c8}`.
118#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
119#[cfg_attr(
120 all(uuid_unstable, feature = "zerocopy"),
121 derive(
122 zerocopy::IntoBytes,
123 zerocopy::FromBytes,
124 zerocopy::KnownLayout,
125 zerocopy::Immutable,
126 zerocopy::Unaligned
127 )
128)]
129#[repr(transparent)]
130pub struct Braced(Uuid);
131
132impl Uuid {
133 /// Get a [`Hyphenated`] formatter.
134 #[inline]
135 pub const fn hyphenated(self) -> Hyphenated {
136 Hyphenated(self)
137 }
138
139 /// Get a borrowed [`Hyphenated`] formatter.
140 #[inline]
141 pub fn as_hyphenated(&self) -> &Hyphenated {
142 unsafe_transmute_ref!(self)
143 }
144
145 /// Get a [`Simple`] formatter.
146 #[inline]
147 pub const fn simple(self) -> Simple {
148 Simple(self)
149 }
150
151 /// Get a borrowed [`Simple`] formatter.
152 #[inline]
153 pub fn as_simple(&self) -> &Simple {
154 unsafe_transmute_ref!(self)
155 }
156
157 /// Get a [`Urn`] formatter.
158 #[inline]
159 pub const fn urn(self) -> Urn {
160 Urn(self)
161 }
162
163 /// Get a borrowed [`Urn`] formatter.
164 #[inline]
165 pub fn as_urn(&self) -> &Urn {
166 unsafe_transmute_ref!(self)
167 }
168
169 /// Get a [`Braced`] formatter.
170 #[inline]
171 pub const fn braced(self) -> Braced {
172 Braced(self)
173 }
174
175 /// Get a borrowed [`Braced`] formatter.
176 #[inline]
177 pub fn as_braced(&self) -> &Braced {
178 unsafe_transmute_ref!(self)
179 }
180}
181
182// Maps a hex nibble (0..=15) to its ASCII character. `alpha_offset` is added
183// for values above 9: 0x27 for lowercase, 0x07 for uppercase.
184#[inline]
185const fn nibble_to_hex(nibble: u8, alpha_offset: u8) -> u8 {
186 nibble + b'0' + if nibble > 9 { alpha_offset } else { 0 }
187}
188
189#[inline]
190const fn format_simple(src: &[u8; 16], upper: bool) -> [u8; 32] {
191 let alpha_offset = if upper { 0x07 } else { 0x27 };
192 let mut dst = [0; 32];
193 let mut i = 0;
194 while i < 16 {
195 let x = src[i];
196 dst[i * 2] = nibble_to_hex(x >> 4, alpha_offset);
197 dst[i * 2 + 1] = nibble_to_hex(x & 0x0f, alpha_offset);
198 i += 1;
199 }
200 dst
201}
202
203#[inline]
204const fn format_hyphenated(src: &[u8; 16], upper: bool) -> [u8; 36] {
205 let simple = format_simple(src, upper);
206 let mut dst = [0; 36];
207
208 let mut i = 0;
209 while i < 8 {
210 dst[i] = simple[i];
211 i += 1;
212 }
213 dst[8] = b'-';
214 while i < 12 {
215 dst[i + 1] = simple[i];
216 i += 1;
217 }
218 dst[13] = b'-';
219 while i < 16 {
220 dst[i + 2] = simple[i];
221 i += 1;
222 }
223 dst[18] = b'-';
224 while i < 20 {
225 dst[i + 3] = simple[i];
226 i += 1;
227 }
228 dst[23] = b'-';
229 while i < 32 {
230 dst[i + 4] = simple[i];
231 i += 1;
232 }
233 dst
234}
235
236#[inline]
237fn encode_simple<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
238 let buf = &mut buffer[..Simple::LENGTH];
239
240 encode_simple_uninit(src, slice_as_uninit_mut(buf), upper)
241}
242
243#[inline]
244fn encode_hyphenated<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
245 let buf = &mut buffer[..Hyphenated::LENGTH];
246
247 encode_hyphenated_uninit(src, slice_as_uninit_mut(buf), upper)
248}
249
250#[inline]
251fn encode_braced<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
252 let buf = &mut buffer[..Hyphenated::LENGTH + 2];
253
254 encode_braced_uninit(src, slice_as_uninit_mut(buf), upper)
255}
256
257#[inline]
258fn encode_urn<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
259 let buf = &mut buffer[..Urn::LENGTH];
260
261 encode_urn_uninit(src, slice_as_uninit_mut(buf), upper)
262}
263
264#[inline]
265fn encode_simple_uninit<'b>(
266 src: &[u8; 16],
267 buffer: &'b mut [MaybeUninit<u8>],
268 upper: bool,
269) -> &'b mut str {
270 let buf = &mut buffer[..Simple::LENGTH];
271 write_bytes(buf, &format_simple(src, upper));
272
273 // SAFETY: The encoded buffer is fully initialized and ASCII encoded.
274 unsafe { assume_init_ascii_mut(buf) }
275}
276
277#[inline]
278fn encode_hyphenated_uninit<'b>(
279 src: &[u8; 16],
280 buffer: &'b mut [MaybeUninit<u8>],
281 upper: bool,
282) -> &'b mut str {
283 let buf = &mut buffer[..Hyphenated::LENGTH];
284 write_bytes(buf, &format_hyphenated(src, upper));
285
286 // SAFETY: The encoded buffer is fully initialized and ASCII encoded.
287 unsafe { assume_init_ascii_mut(buf) }
288}
289
290#[inline]
291fn encode_braced_uninit<'b>(
292 src: &[u8; 16],
293 buffer: &'b mut [MaybeUninit<u8>],
294 upper: bool,
295) -> &'b mut str {
296 let buf = &mut buffer[..Hyphenated::LENGTH + 2];
297
298 #[cfg_attr(all(uuid_unstable, feature = "zerocopy"), derive(zerocopy::IntoBytes))]
299 #[repr(C)]
300 struct BracedBytes {
301 open_curly: u8,
302 hyphenated: [u8; Hyphenated::LENGTH],
303 close_curly: u8,
304 }
305
306 let braced = BracedBytes {
307 open_curly: b'{',
308 hyphenated: format_hyphenated(src, upper),
309 close_curly: b'}',
310 };
311 let braced: [u8; Hyphenated::LENGTH + 2] = unsafe_transmute!(braced);
312
313 write_bytes(buf, &braced);
314
315 // SAFETY: The encoded buffer is fully initialized and ASCII encoded.
316 unsafe { assume_init_ascii_mut(buf) }
317}
318
319#[inline]
320fn encode_urn_uninit<'b>(
321 src: &[u8; 16],
322 buffer: &'b mut [MaybeUninit<u8>],
323 upper: bool,
324) -> &'b mut str {
325 let buf = &mut buffer[..Urn::LENGTH];
326 write_bytes(&mut buf[..9], b"urn:uuid:");
327
328 let dst = &mut buf[9..(9 + Hyphenated::LENGTH)];
329 write_bytes(dst, &format_hyphenated(src, upper));
330
331 // SAFETY: The encoded buffer is fully initialized and ASCII encoded.
332 unsafe { assume_init_ascii_mut(buf) }
333}
334
335#[inline]
336fn write_bytes(dst: &mut [MaybeUninit<u8>], src: &[u8]) {
337 debug_assert_eq!(dst.len(), src.len());
338 let dst = &mut dst[..src.len()];
339
340 // SAFETY: `dst` and `src` are distinct slices, and `dst` has been sliced to
341 // the same length as `src`. `MaybeUninit<u8>` has the same layout as `u8`.
342 unsafe {
343 ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr().cast(), src.len());
344 }
345}
346
347#[inline]
348fn slice_as_uninit_mut(buffer: &mut [u8]) -> &mut [MaybeUninit<u8>] {
349 // SAFETY: `MaybeUninit<u8>` has the same layout as `u8`.
350 unsafe { slice::from_raw_parts_mut(buffer.as_mut_ptr().cast(), buffer.len()) }
351}
352
353#[inline]
354unsafe fn assume_init_ascii_mut(buffer: &mut [MaybeUninit<u8>]) -> &mut str {
355 // SAFETY: The caller guarantees that `buffer` has been initialized.
356 let buffer = unsafe { slice::from_raw_parts_mut(buffer.as_mut_ptr().cast(), buffer.len()) };
357
358 // SAFETY: The caller guarantees that `buffer` is ASCII encoded.
359 unsafe { str::from_utf8_unchecked_mut(buffer) }
360}
361
362impl Hyphenated {
363 /// The length of a hyphenated [`Uuid`] string.
364 ///
365 /// [`Uuid`]: ../struct.Uuid.html
366 pub const LENGTH: usize = 36;
367
368 /// Creates a [`Hyphenated`] from a [`Uuid`].
369 ///
370 /// [`Uuid`]: ../struct.Uuid.html
371 /// [`Hyphenated`]: struct.Hyphenated.html
372 pub const fn from_uuid(uuid: Uuid) -> Self {
373 Hyphenated(uuid)
374 }
375
376 /// Writes the [`Uuid`] as a lower-case hyphenated string to
377 /// `buffer`, and returns the subslice of the buffer that contains the
378 /// encoded UUID.
379 ///
380 /// This is slightly more efficient than using the formatting
381 /// infrastructure as it avoids virtual calls, and may avoid
382 /// double buffering.
383 ///
384 /// [`Uuid`]: ../struct.Uuid.html
385 ///
386 /// # Panics
387 ///
388 /// Panics if the buffer is not large enough: it must have length at least
389 /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
390 /// sufficiently-large temporary buffer.
391 ///
392 /// [`LENGTH`]: #associatedconstant.LENGTH
393 /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
394 ///
395 /// # Examples
396 ///
397 /// ```rust
398 /// use uuid::Uuid;
399 ///
400 /// fn main() -> Result<(), uuid::Error> {
401 /// let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
402 ///
403 /// // the encoded portion is returned
404 /// assert_eq!(
405 /// uuid.hyphenated()
406 /// .encode_lower(&mut Uuid::encode_buffer()),
407 /// "936da01f-9abd-4d9d-80c7-02af85c822a8"
408 /// );
409 ///
410 /// // the buffer is mutated directly, and trailing contents remains
411 /// let mut buf = [b'!'; 40];
412 /// uuid.hyphenated().encode_lower(&mut buf);
413 /// assert_eq!(
414 /// &buf as &[_],
415 /// b"936da01f-9abd-4d9d-80c7-02af85c822a8!!!!" as &[_]
416 /// );
417 ///
418 /// Ok(())
419 /// }
420 /// ```
421 /// */
422 #[inline]
423 pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
424 encode_hyphenated(self.0.as_bytes(), buffer, false)
425 }
426
427 /// Writes the [`Uuid`] as a lower-case hyphenated string to a
428 /// possibly-uninitialized `buffer`, and returns the subslice of the buffer
429 /// that contains the encoded UUID.
430 ///
431 /// This initializes the returned subslice of `buffer`. Bytes outside of the
432 /// returned subslice are not written.
433 ///
434 /// [`Uuid`]: ../struct.Uuid.html
435 ///
436 /// # Panics
437 ///
438 /// Panics if the buffer is not large enough: it must have length at least
439 /// [`LENGTH`].
440 ///
441 /// [`LENGTH`]: #associatedconstant.LENGTH
442 #[inline]
443 pub fn encode_lower_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
444 encode_hyphenated_uninit(self.0.as_bytes(), buffer, false)
445 }
446
447 /// Writes the [`Uuid`] as an upper-case hyphenated string to
448 /// `buffer`, and returns the subslice of the buffer that contains the
449 /// encoded UUID.
450 ///
451 /// This is slightly more efficient than using the formatting
452 /// infrastructure as it avoids virtual calls, and may avoid
453 /// double buffering.
454 ///
455 /// [`Uuid`]: ../struct.Uuid.html
456 ///
457 /// # Panics
458 ///
459 /// Panics if the buffer is not large enough: it must have length at least
460 /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
461 /// sufficiently-large temporary buffer.
462 ///
463 /// [`LENGTH`]: #associatedconstant.LENGTH
464 /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
465 ///
466 /// # Examples
467 ///
468 /// ```rust
469 /// use uuid::Uuid;
470 ///
471 /// fn main() -> Result<(), uuid::Error> {
472 /// let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
473 ///
474 /// // the encoded portion is returned
475 /// assert_eq!(
476 /// uuid.hyphenated()
477 /// .encode_upper(&mut Uuid::encode_buffer()),
478 /// "936DA01F-9ABD-4D9D-80C7-02AF85C822A8"
479 /// );
480 ///
481 /// // the buffer is mutated directly, and trailing contents remains
482 /// let mut buf = [b'!'; 40];
483 /// uuid.hyphenated().encode_upper(&mut buf);
484 /// assert_eq!(
485 /// &buf as &[_],
486 /// b"936DA01F-9ABD-4D9D-80C7-02AF85C822A8!!!!" as &[_]
487 /// );
488 ///
489 /// Ok(())
490 /// }
491 /// ```
492 /// */
493 #[inline]
494 pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
495 encode_hyphenated(self.0.as_bytes(), buffer, true)
496 }
497
498 /// Writes the [`Uuid`] as an upper-case hyphenated string to a
499 /// possibly-uninitialized `buffer`, and returns the subslice of the buffer
500 /// that contains the encoded UUID.
501 ///
502 /// This initializes the returned subslice of `buffer`. Bytes outside of the
503 /// returned subslice are not written.
504 ///
505 /// [`Uuid`]: ../struct.Uuid.html
506 ///
507 /// # Panics
508 ///
509 /// Panics if the buffer is not large enough: it must have length at least
510 /// [`LENGTH`].
511 ///
512 /// [`LENGTH`]: #associatedconstant.LENGTH
513 #[inline]
514 pub fn encode_upper_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
515 encode_hyphenated_uninit(self.0.as_bytes(), buffer, true)
516 }
517
518 /// Get a reference to the underlying [`Uuid`].
519 ///
520 /// # Examples
521 ///
522 /// ```rust
523 /// use uuid::Uuid;
524 ///
525 /// let hyphenated = Uuid::nil().hyphenated();
526 /// assert_eq!(*hyphenated.as_uuid(), Uuid::nil());
527 /// ```
528 pub const fn as_uuid(&self) -> &Uuid {
529 &self.0
530 }
531
532 /// Consumes the [`Hyphenated`], returning the underlying [`Uuid`].
533 ///
534 /// # Examples
535 ///
536 /// ```rust
537 /// use uuid::Uuid;
538 ///
539 /// let hyphenated = Uuid::nil().hyphenated();
540 /// assert_eq!(hyphenated.into_uuid(), Uuid::nil());
541 /// ```
542 pub const fn into_uuid(self) -> Uuid {
543 self.0
544 }
545}
546
547impl Braced {
548 /// The length of a braced [`Uuid`] string.
549 ///
550 /// [`Uuid`]: ../struct.Uuid.html
551 pub const LENGTH: usize = 38;
552
553 /// Creates a [`Braced`] from a [`Uuid`].
554 ///
555 /// [`Uuid`]: ../struct.Uuid.html
556 /// [`Braced`]: struct.Braced.html
557 pub const fn from_uuid(uuid: Uuid) -> Self {
558 Braced(uuid)
559 }
560
561 /// Writes the [`Uuid`] as a lower-case hyphenated string surrounded by
562 /// braces to `buffer`, and returns the subslice of the buffer that contains
563 /// the encoded UUID.
564 ///
565 /// This is slightly more efficient than using the formatting
566 /// infrastructure as it avoids virtual calls, and may avoid
567 /// double buffering.
568 ///
569 /// [`Uuid`]: ../struct.Uuid.html
570 ///
571 /// # Panics
572 ///
573 /// Panics if the buffer is not large enough: it must have length at least
574 /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
575 /// sufficiently-large temporary buffer.
576 ///
577 /// [`LENGTH`]: #associatedconstant.LENGTH
578 /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
579 ///
580 /// # Examples
581 ///
582 /// ```rust
583 /// use uuid::Uuid;
584 ///
585 /// fn main() -> Result<(), uuid::Error> {
586 /// let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
587 ///
588 /// // the encoded portion is returned
589 /// assert_eq!(
590 /// uuid.braced()
591 /// .encode_lower(&mut Uuid::encode_buffer()),
592 /// "{936da01f-9abd-4d9d-80c7-02af85c822a8}"
593 /// );
594 ///
595 /// // the buffer is mutated directly, and trailing contents remains
596 /// let mut buf = [b'!'; 40];
597 /// uuid.braced().encode_lower(&mut buf);
598 /// assert_eq!(
599 /// &buf as &[_],
600 /// b"{936da01f-9abd-4d9d-80c7-02af85c822a8}!!" as &[_]
601 /// );
602 ///
603 /// Ok(())
604 /// }
605 /// ```
606 /// */
607 #[inline]
608 pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
609 encode_braced(self.0.as_bytes(), buffer, false)
610 }
611
612 /// Writes the [`Uuid`] as a lower-case hyphenated string surrounded by
613 /// braces to a possibly-uninitialized `buffer`, and returns the subslice of
614 /// the buffer that contains the encoded UUID.
615 ///
616 /// This initializes the returned subslice of `buffer`. Bytes outside of the
617 /// returned subslice are not written.
618 ///
619 /// [`Uuid`]: ../struct.Uuid.html
620 ///
621 /// # Panics
622 ///
623 /// Panics if the buffer is not large enough: it must have length at least
624 /// [`LENGTH`].
625 ///
626 /// [`LENGTH`]: #associatedconstant.LENGTH
627 #[inline]
628 pub fn encode_lower_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
629 encode_braced_uninit(self.0.as_bytes(), buffer, false)
630 }
631
632 /// Writes the [`Uuid`] as an upper-case hyphenated string surrounded by
633 /// braces to `buffer`, and returns the subslice of the buffer that contains
634 /// the encoded UUID.
635 ///
636 /// This is slightly more efficient than using the formatting
637 /// infrastructure as it avoids virtual calls, and may avoid
638 /// double buffering.
639 ///
640 /// [`Uuid`]: ../struct.Uuid.html
641 ///
642 /// # Panics
643 ///
644 /// Panics if the buffer is not large enough: it must have length at least
645 /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
646 /// sufficiently-large temporary buffer.
647 ///
648 /// [`LENGTH`]: #associatedconstant.LENGTH
649 /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
650 ///
651 /// # Examples
652 ///
653 /// ```rust
654 /// use uuid::Uuid;
655 ///
656 /// fn main() -> Result<(), uuid::Error> {
657 /// let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
658 ///
659 /// // the encoded portion is returned
660 /// assert_eq!(
661 /// uuid.braced()
662 /// .encode_upper(&mut Uuid::encode_buffer()),
663 /// "{936DA01F-9ABD-4D9D-80C7-02AF85C822A8}"
664 /// );
665 ///
666 /// // the buffer is mutated directly, and trailing contents remains
667 /// let mut buf = [b'!'; 40];
668 /// uuid.braced().encode_upper(&mut buf);
669 /// assert_eq!(
670 /// &buf as &[_],
671 /// b"{936DA01F-9ABD-4D9D-80C7-02AF85C822A8}!!" as &[_]
672 /// );
673 ///
674 /// Ok(())
675 /// }
676 /// ```
677 /// */
678 #[inline]
679 pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
680 encode_braced(self.0.as_bytes(), buffer, true)
681 }
682
683 /// Writes the [`Uuid`] as an upper-case hyphenated string surrounded by
684 /// braces to a possibly-uninitialized `buffer`, and returns the subslice of
685 /// the buffer that contains the encoded UUID.
686 ///
687 /// This initializes the returned subslice of `buffer`. Bytes outside of the
688 /// returned subslice are not written.
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`].
696 ///
697 /// [`LENGTH`]: #associatedconstant.LENGTH
698 #[inline]
699 pub fn encode_upper_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
700 encode_braced_uninit(self.0.as_bytes(), buffer, true)
701 }
702
703 /// Get a reference to the underlying [`Uuid`].
704 ///
705 /// # Examples
706 ///
707 /// ```rust
708 /// use uuid::Uuid;
709 ///
710 /// let braced = Uuid::nil().braced();
711 /// assert_eq!(*braced.as_uuid(), Uuid::nil());
712 /// ```
713 pub const fn as_uuid(&self) -> &Uuid {
714 &self.0
715 }
716
717 /// Consumes the [`Braced`], returning the underlying [`Uuid`].
718 ///
719 /// # Examples
720 ///
721 /// ```rust
722 /// use uuid::Uuid;
723 ///
724 /// let braced = Uuid::nil().braced();
725 /// assert_eq!(braced.into_uuid(), Uuid::nil());
726 /// ```
727 pub const fn into_uuid(self) -> Uuid {
728 self.0
729 }
730}
731
732impl Simple {
733 /// The length of a simple [`Uuid`] string.
734 ///
735 /// [`Uuid`]: ../struct.Uuid.html
736 pub const LENGTH: usize = 32;
737
738 /// Creates a [`Simple`] from a [`Uuid`].
739 ///
740 /// [`Uuid`]: ../struct.Uuid.html
741 /// [`Simple`]: struct.Simple.html
742 pub const fn from_uuid(uuid: Uuid) -> Self {
743 Simple(uuid)
744 }
745
746 /// Writes the [`Uuid`] as a lower-case simple string to `buffer`,
747 /// and returns the subslice of the buffer that contains the encoded UUID.
748 ///
749 /// This is slightly more efficient than using the formatting
750 /// infrastructure as it avoids virtual calls, and may avoid
751 /// double buffering.
752 ///
753 /// [`Uuid`]: ../struct.Uuid.html
754 ///
755 /// # Panics
756 ///
757 /// Panics if the buffer is not large enough: it must have length at least
758 /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
759 /// sufficiently-large temporary buffer.
760 ///
761 /// [`LENGTH`]: #associatedconstant.LENGTH
762 /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
763 ///
764 /// # Examples
765 ///
766 /// ```rust
767 /// use uuid::Uuid;
768 ///
769 /// fn main() -> Result<(), uuid::Error> {
770 /// let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
771 ///
772 /// // the encoded portion is returned
773 /// assert_eq!(
774 /// uuid.simple().encode_lower(&mut Uuid::encode_buffer()),
775 /// "936da01f9abd4d9d80c702af85c822a8"
776 /// );
777 ///
778 /// // the buffer is mutated directly, and trailing contents remains
779 /// let mut buf = [b'!'; 36];
780 /// assert_eq!(
781 /// uuid.simple().encode_lower(&mut buf),
782 /// "936da01f9abd4d9d80c702af85c822a8"
783 /// );
784 /// assert_eq!(
785 /// &buf as &[_],
786 /// b"936da01f9abd4d9d80c702af85c822a8!!!!" as &[_]
787 /// );
788 ///
789 /// Ok(())
790 /// }
791 /// ```
792 /// */
793 #[inline]
794 pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
795 encode_simple(self.0.as_bytes(), buffer, false)
796 }
797
798 /// Writes the [`Uuid`] as a lower-case simple string to a
799 /// possibly-uninitialized `buffer`, and returns the subslice of the buffer
800 /// that contains the encoded UUID.
801 ///
802 /// This initializes the returned subslice of `buffer`. Bytes outside of the
803 /// returned subslice are not written.
804 ///
805 /// [`Uuid`]: ../struct.Uuid.html
806 ///
807 /// # Panics
808 ///
809 /// Panics if the buffer is not large enough: it must have length at least
810 /// [`LENGTH`].
811 ///
812 /// [`LENGTH`]: #associatedconstant.LENGTH
813 #[inline]
814 pub fn encode_lower_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
815 encode_simple_uninit(self.0.as_bytes(), buffer, false)
816 }
817
818 /// Writes the [`Uuid`] as an upper-case simple string to `buffer`,
819 /// and returns the subslice of the buffer that contains the encoded UUID.
820 ///
821 /// [`Uuid`]: ../struct.Uuid.html
822 ///
823 /// # Panics
824 ///
825 /// Panics if the buffer is not large enough: it must have length at least
826 /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
827 /// sufficiently-large temporary buffer.
828 ///
829 /// [`LENGTH`]: #associatedconstant.LENGTH
830 /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
831 ///
832 /// # Examples
833 ///
834 /// ```rust
835 /// use uuid::Uuid;
836 ///
837 /// fn main() -> Result<(), uuid::Error> {
838 /// let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
839 ///
840 /// // the encoded portion is returned
841 /// assert_eq!(
842 /// uuid.simple().encode_upper(&mut Uuid::encode_buffer()),
843 /// "936DA01F9ABD4D9D80C702AF85C822A8"
844 /// );
845 ///
846 /// // the buffer is mutated directly, and trailing contents remains
847 /// let mut buf = [b'!'; 36];
848 /// assert_eq!(
849 /// uuid.simple().encode_upper(&mut buf),
850 /// "936DA01F9ABD4D9D80C702AF85C822A8"
851 /// );
852 /// assert_eq!(
853 /// &buf as &[_],
854 /// b"936DA01F9ABD4D9D80C702AF85C822A8!!!!" as &[_]
855 /// );
856 ///
857 /// Ok(())
858 /// }
859 /// ```
860 /// */
861 #[inline]
862 pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
863 encode_simple(self.0.as_bytes(), buffer, true)
864 }
865
866 /// Writes the [`Uuid`] as an upper-case simple string to a
867 /// possibly-uninitialized `buffer`, and returns the subslice of the buffer
868 /// that contains the encoded UUID.
869 ///
870 /// This initializes the returned subslice of `buffer`. Bytes outside of the
871 /// returned subslice are not written.
872 ///
873 /// [`Uuid`]: ../struct.Uuid.html
874 ///
875 /// # Panics
876 ///
877 /// Panics if the buffer is not large enough: it must have length at least
878 /// [`LENGTH`].
879 ///
880 /// [`LENGTH`]: #associatedconstant.LENGTH
881 #[inline]
882 pub fn encode_upper_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
883 encode_simple_uninit(self.0.as_bytes(), buffer, true)
884 }
885
886 /// Get a reference to the underlying [`Uuid`].
887 ///
888 /// # Examples
889 ///
890 /// ```rust
891 /// use uuid::Uuid;
892 ///
893 /// let simple = Uuid::nil().simple();
894 /// assert_eq!(*simple.as_uuid(), Uuid::nil());
895 /// ```
896 pub const fn as_uuid(&self) -> &Uuid {
897 &self.0
898 }
899
900 /// Consumes the [`Simple`], returning the underlying [`Uuid`].
901 ///
902 /// # Examples
903 ///
904 /// ```rust
905 /// use uuid::Uuid;
906 ///
907 /// let simple = Uuid::nil().simple();
908 /// assert_eq!(simple.into_uuid(), Uuid::nil());
909 /// ```
910 pub const fn into_uuid(self) -> Uuid {
911 self.0
912 }
913}
914
915impl Urn {
916 /// The length of a URN [`Uuid`] string.
917 ///
918 /// [`Uuid`]: ../struct.Uuid.html
919 pub const LENGTH: usize = 45;
920
921 /// Creates a [`Urn`] from a [`Uuid`].
922 ///
923 /// [`Uuid`]: ../struct.Uuid.html
924 /// [`Urn`]: struct.Urn.html
925 pub const fn from_uuid(uuid: Uuid) -> Self {
926 Urn(uuid)
927 }
928
929 /// Writes the [`Uuid`] as a lower-case URN string to
930 /// `buffer`, and returns the subslice of the buffer that contains the
931 /// encoded UUID.
932 ///
933 /// This is slightly more efficient than using the formatting
934 /// infrastructure as it avoids virtual calls, and may avoid
935 /// double buffering.
936 ///
937 /// [`Uuid`]: ../struct.Uuid.html
938 ///
939 /// # Panics
940 ///
941 /// Panics if the buffer is not large enough: it must have length at least
942 /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
943 /// sufficiently-large temporary buffer.
944 ///
945 /// [`LENGTH`]: #associatedconstant.LENGTH
946 /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
947 ///
948 /// # Examples
949 ///
950 /// ```rust
951 /// use uuid::Uuid;
952 ///
953 /// fn main() -> Result<(), uuid::Error> {
954 /// let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8")?;
955 ///
956 /// // the encoded portion is returned
957 /// assert_eq!(
958 /// uuid.urn().encode_lower(&mut Uuid::encode_buffer()),
959 /// "urn:uuid:936da01f-9abd-4d9d-80c7-02af85c822a8"
960 /// );
961 ///
962 /// // the buffer is mutated directly, and trailing contents remains
963 /// let mut buf = [b'!'; 49];
964 /// uuid.urn().encode_lower(&mut buf);
965 /// assert_eq!(
966 /// uuid.urn().encode_lower(&mut buf),
967 /// "urn:uuid:936da01f-9abd-4d9d-80c7-02af85c822a8"
968 /// );
969 /// assert_eq!(
970 /// &buf as &[_],
971 /// b"urn:uuid:936da01f-9abd-4d9d-80c7-02af85c822a8!!!!" as &[_]
972 /// );
973 ///
974 /// Ok(())
975 /// }
976 /// ```
977 /// */
978 #[inline]
979 pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
980 encode_urn(self.0.as_bytes(), buffer, false)
981 }
982
983 /// Writes the [`Uuid`] as a lower-case URN string to a
984 /// possibly-uninitialized `buffer`, and returns the subslice of the buffer
985 /// that contains the encoded UUID.
986 ///
987 /// This initializes the returned subslice of `buffer`. Bytes outside of the
988 /// returned subslice are not written.
989 ///
990 /// [`Uuid`]: ../struct.Uuid.html
991 ///
992 /// # Panics
993 ///
994 /// Panics if the buffer is not large enough: it must have length at least
995 /// [`LENGTH`].
996 ///
997 /// [`LENGTH`]: #associatedconstant.LENGTH
998 #[inline]
999 pub fn encode_lower_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
1000 encode_urn_uninit(self.0.as_bytes(), buffer, false)
1001 }
1002
1003 /// Writes the [`Uuid`] as an upper-case URN string to
1004 /// `buffer`, and returns the subslice of the buffer that contains the
1005 /// encoded UUID.
1006 ///
1007 /// This is slightly more efficient than using the formatting
1008 /// infrastructure as it avoids virtual calls, and may avoid
1009 /// double buffering.
1010 ///
1011 /// [`Uuid`]: ../struct.Uuid.html
1012 ///
1013 /// # Panics
1014 ///
1015 /// Panics if the buffer is not large enough: it must have length at least
1016 /// [`LENGTH`]. [`Uuid::encode_buffer`] can be used to get a
1017 /// sufficiently-large temporary buffer.
1018 ///
1019 /// [`LENGTH`]: #associatedconstant.LENGTH
1020 /// [`Uuid::encode_buffer`]: ../struct.Uuid.html#method.encode_buffer
1021 ///
1022 /// # Examples
1023 ///
1024 /// ```rust
1025 /// use uuid::Uuid;
1026 ///
1027 /// fn main() -> Result<(), uuid::Error> {
1028 /// let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8")?;
1029 ///
1030 /// // the encoded portion is returned
1031 /// assert_eq!(
1032 /// uuid.urn().encode_upper(&mut Uuid::encode_buffer()),
1033 /// "urn:uuid:936DA01F-9ABD-4D9D-80C7-02AF85C822A8"
1034 /// );
1035 ///
1036 /// // the buffer is mutated directly, and trailing contents remains
1037 /// let mut buf = [b'!'; 49];
1038 /// assert_eq!(
1039 /// uuid.urn().encode_upper(&mut buf),
1040 /// "urn:uuid:936DA01F-9ABD-4D9D-80C7-02AF85C822A8"
1041 /// );
1042 /// assert_eq!(
1043 /// &buf as &[_],
1044 /// b"urn:uuid:936DA01F-9ABD-4D9D-80C7-02AF85C822A8!!!!" as &[_]
1045 /// );
1046 ///
1047 /// Ok(())
1048 /// }
1049 /// ```
1050 /// */
1051 #[inline]
1052 pub fn encode_upper<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
1053 encode_urn(self.0.as_bytes(), buffer, true)
1054 }
1055
1056 /// Writes the [`Uuid`] as an upper-case URN string to a
1057 /// possibly-uninitialized `buffer`, and returns the subslice of the buffer
1058 /// that contains the encoded UUID.
1059 ///
1060 /// This initializes the returned subslice of `buffer`. Bytes outside of the
1061 /// returned subslice are not written.
1062 ///
1063 /// [`Uuid`]: ../struct.Uuid.html
1064 ///
1065 /// # Panics
1066 ///
1067 /// Panics if the buffer is not large enough: it must have length at least
1068 /// [`LENGTH`].
1069 ///
1070 /// [`LENGTH`]: #associatedconstant.LENGTH
1071 #[inline]
1072 pub fn encode_upper_uninit<'buf>(&self, buffer: &'buf mut [MaybeUninit<u8>]) -> &'buf mut str {
1073 encode_urn_uninit(self.0.as_bytes(), buffer, true)
1074 }
1075
1076 /// Get a reference to the underlying [`Uuid`].
1077 ///
1078 /// # Examples
1079 ///
1080 /// ```rust
1081 /// use uuid::Uuid;
1082 ///
1083 /// let urn = Uuid::nil().urn();
1084 /// assert_eq!(*urn.as_uuid(), Uuid::nil());
1085 /// ```
1086 pub const fn as_uuid(&self) -> &Uuid {
1087 &self.0
1088 }
1089
1090 /// Consumes the [`Urn`], returning the underlying [`Uuid`].
1091 ///
1092 /// # Examples
1093 ///
1094 /// ```rust
1095 /// use uuid::Uuid;
1096 ///
1097 /// let urn = Uuid::nil().urn();
1098 /// assert_eq!(urn.into_uuid(), Uuid::nil());
1099 /// ```
1100 pub const fn into_uuid(self) -> Uuid {
1101 self.0
1102 }
1103}
1104
1105impl FromStr for Hyphenated {
1106 type Err = Error;
1107
1108 fn from_str(s: &str) -> Result<Self, Self::Err> {
1109 crate::parser::parse_hyphenated(s.as_bytes())
1110 .map(|b| Hyphenated(Uuid(b)))
1111 .map_err(|invalid| invalid.into_err())
1112 }
1113}
1114
1115impl FromStr for Simple {
1116 type Err = Error;
1117
1118 fn from_str(s: &str) -> Result<Self, Self::Err> {
1119 crate::parser::parse_simple(s.as_bytes(), false)
1120 .map(|b| Simple(Uuid(b)))
1121 .map_err(|invalid| invalid.into_err())
1122 }
1123}
1124
1125impl FromStr for Urn {
1126 type Err = Error;
1127
1128 fn from_str(s: &str) -> Result<Self, Self::Err> {
1129 crate::parser::parse_urn(s.as_bytes())
1130 .map(|b| Urn(Uuid(b)))
1131 .map_err(|invalid| invalid.into_err())
1132 }
1133}
1134
1135impl FromStr for Braced {
1136 type Err = Error;
1137
1138 fn from_str(s: &str) -> Result<Self, Self::Err> {
1139 crate::parser::parse_braced(s.as_bytes())
1140 .map(|b| Braced(Uuid(b)))
1141 .map_err(|invalid| invalid.into_err())
1142 }
1143}
1144
1145macro_rules! impl_fmt_traits {
1146 ($($T:ident<$($a:lifetime),*>),+) => {$(
1147 impl<$($a),*> fmt::Display for $T<$($a),*> {
1148 #[inline]
1149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1150 fmt::LowerHex::fmt(self, f)
1151 }
1152 }
1153
1154 impl<$($a),*> fmt::LowerHex for $T<$($a),*> {
1155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1156 f.write_str(self.encode_lower(&mut [0; Self::LENGTH]))
1157 }
1158 }
1159
1160 impl<$($a),*> fmt::UpperHex for $T<$($a),*> {
1161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1162 f.write_str(self.encode_upper(&mut [0; Self::LENGTH]))
1163 }
1164 }
1165
1166 impl_fmt_from!($T<$($a),*>);
1167 )+}
1168}
1169
1170macro_rules! impl_fmt_from {
1171 ($T:ident<>) => {
1172 impl From<Uuid> for $T {
1173 #[inline]
1174 fn from(f: Uuid) -> Self {
1175 $T(f)
1176 }
1177 }
1178
1179 impl From<$T> for Uuid {
1180 #[inline]
1181 fn from(f: $T) -> Self {
1182 f.into_uuid()
1183 }
1184 }
1185
1186 impl AsRef<Uuid> for $T {
1187 #[inline]
1188 fn as_ref(&self) -> &Uuid {
1189 &self.0
1190 }
1191 }
1192
1193 impl Borrow<Uuid> for $T {
1194 #[inline]
1195 fn borrow(&self) -> &Uuid {
1196 &self.0
1197 }
1198 }
1199 };
1200 ($T:ident<$a:lifetime>) => {
1201 impl<$a> From<&$a Uuid> for $T<$a> {
1202 #[inline]
1203 fn from(f: &$a Uuid) -> Self {
1204 $T::from_uuid_ref(f)
1205 }
1206 }
1207
1208 impl<$a> From<$T<$a>> for &$a Uuid {
1209 #[inline]
1210 fn from(f: $T<$a>) -> &$a Uuid {
1211 f.0
1212 }
1213 }
1214
1215 impl<$a> AsRef<Uuid> for $T<$a> {
1216 #[inline]
1217 fn as_ref(&self) -> &Uuid {
1218 self.0
1219 }
1220 }
1221
1222 impl<$a> Borrow<Uuid> for $T<$a> {
1223 #[inline]
1224 fn borrow(&self) -> &Uuid {
1225 self.0
1226 }
1227 }
1228 };
1229}
1230
1231impl_fmt_traits! {
1232 Hyphenated<>,
1233 Simple<>,
1234 Urn<>,
1235 Braced<>
1236}
1237
1238#[cfg(test)]
1239mod tests {
1240 use super::*;
1241
1242 use core::mem::MaybeUninit;
1243
1244 #[test]
1245 fn encode_lower_uninit() {
1246 let uuid = Uuid::parse_str("936DA01f9abd4d9d80c702af85c822a8").unwrap();
1247
1248 let mut buf = [MaybeUninit::new(b'x'); 100];
1249 let len = {
1250 let encoded = uuid.hyphenated().encode_lower_uninit(&mut buf);
1251 assert_eq!(encoded, "936da01f-9abd-4d9d-80c7-02af85c822a8");
1252 encoded.len()
1253 };
1254 assert_eq!(len, Hyphenated::LENGTH);
1255 assert_uninit_tail_unchanged(&buf, len);
1256
1257 let mut buf = [MaybeUninit::new(b'x'); 100];
1258 let len = {
1259 let encoded = uuid.simple().encode_lower_uninit(&mut buf);
1260 assert_eq!(encoded, "936da01f9abd4d9d80c702af85c822a8");
1261 encoded.len()
1262 };
1263 assert_eq!(len, Simple::LENGTH);
1264 assert_uninit_tail_unchanged(&buf, len);
1265
1266 let mut buf = [MaybeUninit::new(b'x'); 100];
1267 let len = {
1268 let encoded = uuid.urn().encode_lower_uninit(&mut buf);
1269 assert_eq!(encoded, "urn:uuid:936da01f-9abd-4d9d-80c7-02af85c822a8");
1270 encoded.len()
1271 };
1272 assert_eq!(len, Urn::LENGTH);
1273 assert_uninit_tail_unchanged(&buf, len);
1274
1275 let mut buf = [MaybeUninit::new(b'x'); 100];
1276 let len = {
1277 let encoded = uuid.braced().encode_lower_uninit(&mut buf);
1278 assert_eq!(encoded, "{936da01f-9abd-4d9d-80c7-02af85c822a8}");
1279 encoded.len()
1280 };
1281 assert_eq!(len, Braced::LENGTH);
1282 assert_uninit_tail_unchanged(&buf, len);
1283 }
1284
1285 #[test]
1286 fn encode_upper_uninit() {
1287 let uuid = Uuid::parse_str("936da01f9abd4d9d80c702af85c822a8").unwrap();
1288
1289 let mut buf = [MaybeUninit::new(b'x'); 100];
1290 let len = {
1291 let encoded = uuid.hyphenated().encode_upper_uninit(&mut buf);
1292 assert_eq!(encoded, "936DA01F-9ABD-4D9D-80C7-02AF85C822A8");
1293 encoded.len()
1294 };
1295 assert_eq!(len, Hyphenated::LENGTH);
1296 assert_uninit_tail_unchanged(&buf, len);
1297
1298 let mut buf = [MaybeUninit::new(b'x'); 100];
1299 let len = {
1300 let encoded = uuid.simple().encode_upper_uninit(&mut buf);
1301 assert_eq!(encoded, "936DA01F9ABD4D9D80C702AF85C822A8");
1302 encoded.len()
1303 };
1304 assert_eq!(len, Simple::LENGTH);
1305 assert_uninit_tail_unchanged(&buf, len);
1306
1307 let mut buf = [MaybeUninit::new(b'x'); 100];
1308 let len = {
1309 let encoded = uuid.urn().encode_upper_uninit(&mut buf);
1310 assert_eq!(encoded, "urn:uuid:936DA01F-9ABD-4D9D-80C7-02AF85C822A8");
1311 encoded.len()
1312 };
1313 assert_eq!(len, Urn::LENGTH);
1314 assert_uninit_tail_unchanged(&buf, len);
1315
1316 let mut buf = [MaybeUninit::new(b'x'); 100];
1317 let len = {
1318 let encoded = uuid.braced().encode_upper_uninit(&mut buf);
1319 assert_eq!(encoded, "{936DA01F-9ABD-4D9D-80C7-02AF85C822A8}");
1320 encoded.len()
1321 };
1322 assert_eq!(len, Braced::LENGTH);
1323 assert_uninit_tail_unchanged(&buf, len);
1324 }
1325
1326 fn assert_uninit_tail_unchanged(buffer: &[MaybeUninit<u8>], initialized: usize) {
1327 // SAFETY: The test initializes the full buffer before encoding.
1328 let buffer: &[u8] =
1329 unsafe { core::slice::from_raw_parts(buffer.as_ptr().cast(), buffer.len()) };
1330
1331 assert!(buffer[initialized..].iter().all(|b| *b == b'x'));
1332 }
1333
1334 #[test]
1335 fn hyphenated_trailing() {
1336 let mut buf = [b'x'; 100];
1337 let len = Uuid::nil().hyphenated().encode_lower(&mut buf).len();
1338 assert_eq!(len, super::Hyphenated::LENGTH);
1339 assert!(buf[len..].iter().all(|x| *x == b'x'));
1340 }
1341
1342 #[test]
1343 fn hyphenated_ref_trailing() {
1344 let mut buf = [b'x'; 100];
1345 let len = Uuid::nil().as_hyphenated().encode_lower(&mut buf).len();
1346 assert_eq!(len, super::Hyphenated::LENGTH);
1347 assert!(buf[len..].iter().all(|x| *x == b'x'));
1348 }
1349
1350 #[test]
1351 fn simple_trailing() {
1352 let mut buf = [b'x'; 100];
1353 let len = Uuid::nil().simple().encode_lower(&mut buf).len();
1354 assert_eq!(len, super::Simple::LENGTH);
1355 assert!(buf[len..].iter().all(|x| *x == b'x'));
1356 }
1357
1358 #[test]
1359 fn simple_ref_trailing() {
1360 let mut buf = [b'x'; 100];
1361 let len = Uuid::nil().as_simple().encode_lower(&mut buf).len();
1362 assert_eq!(len, super::Simple::LENGTH);
1363 assert!(buf[len..].iter().all(|x| *x == b'x'));
1364 }
1365
1366 #[test]
1367 fn urn_trailing() {
1368 let mut buf = [b'x'; 100];
1369 let len = Uuid::nil().urn().encode_lower(&mut buf).len();
1370 assert_eq!(len, super::Urn::LENGTH);
1371 assert!(buf[len..].iter().all(|x| *x == b'x'));
1372 }
1373
1374 #[test]
1375 fn urn_ref_trailing() {
1376 let mut buf = [b'x'; 100];
1377 let len = Uuid::nil().as_urn().encode_lower(&mut buf).len();
1378 assert_eq!(len, super::Urn::LENGTH);
1379 assert!(buf[len..].iter().all(|x| *x == b'x'));
1380 }
1381
1382 #[test]
1383 fn braced_trailing() {
1384 let mut buf = [b'x'; 100];
1385 let len = Uuid::nil().braced().encode_lower(&mut buf).len();
1386 assert_eq!(len, super::Braced::LENGTH);
1387 assert!(buf[len..].iter().all(|x| *x == b'x'));
1388 }
1389
1390 #[test]
1391 fn braced_ref_trailing() {
1392 let mut buf = [b'x'; 100];
1393 let len = Uuid::nil().as_braced().encode_lower(&mut buf).len();
1394 assert_eq!(len, super::Braced::LENGTH);
1395 assert!(buf[len..].iter().all(|x| *x == b'x'));
1396 }
1397
1398 #[test]
1399 #[should_panic]
1400 fn hyphenated_too_small() {
1401 Uuid::nil().hyphenated().encode_lower(&mut [0; 35]);
1402 }
1403
1404 #[test]
1405 #[should_panic]
1406 fn simple_too_small() {
1407 Uuid::nil().simple().encode_lower(&mut [0; 31]);
1408 }
1409
1410 #[test]
1411 #[should_panic]
1412 fn urn_too_small() {
1413 Uuid::nil().urn().encode_lower(&mut [0; 44]);
1414 }
1415
1416 #[test]
1417 #[should_panic]
1418 fn braced_too_small() {
1419 Uuid::nil().braced().encode_lower(&mut [0; 37]);
1420 }
1421
1422 #[test]
1423 fn hyphenated_to_inner() {
1424 let hyphenated = Uuid::nil().hyphenated();
1425 assert_eq!(Uuid::from(hyphenated), Uuid::nil());
1426 }
1427
1428 #[test]
1429 fn simple_to_inner() {
1430 let simple = Uuid::nil().simple();
1431 assert_eq!(Uuid::from(simple), Uuid::nil());
1432 }
1433
1434 #[test]
1435 fn urn_to_inner() {
1436 let urn = Uuid::nil().urn();
1437 assert_eq!(Uuid::from(urn), Uuid::nil());
1438 }
1439
1440 #[test]
1441 fn braced_to_inner() {
1442 let braced = Uuid::nil().braced();
1443 assert_eq!(Uuid::from(braced), Uuid::nil());
1444 }
1445}