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