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