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