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