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 | |
14 | use crate::{ |
15 | std::{borrow::Borrow, fmt, ptr, str}, |
16 | Uuid, Variant, |
17 | }; |
18 | |
19 | impl 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 | |
26 | impl fmt::Display for Uuid { |
27 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
28 | fmt::LowerHex::fmt(self, f) |
29 | } |
30 | } |
31 | |
32 | impl 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 | |
43 | impl 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 | |
49 | impl 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)] |
60 | pub 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)] |
66 | pub 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)] |
72 | pub 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)] |
78 | pub struct Braced(Uuid); |
79 | |
80 | impl 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 | |
134 | const 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 | ]; |
137 | const 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 ] |
142 | const 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 ] |
156 | const 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 ] |
183 | fn 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 ] |
196 | fn 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 ] |
209 | fn 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 ] |
225 | fn 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 | |
239 | impl 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 | |
384 | impl 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 | |
529 | impl 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 | |
672 | impl 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 | |
822 | macro_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 | |
847 | macro_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 | |
908 | impl_fmt_traits! { |
909 | Hyphenated<>, |
910 | Simple<>, |
911 | Urn<>, |
912 | Braced<> |
913 | } |
914 | |
915 | #[cfg (test)] |
916 | mod 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 | |