1use core::fmt;
2use std::{
3 ptr,
4 string::{String, ToString},
5};
6
7use crate::{Error, Uuid};
8
9impl Default for Uuid {
10 #[inline]
11 fn default() -> Self {
12 Uuid::nil()
13 }
14}
15
16impl AsRef<Uuid> for Uuid {
17 #[inline]
18 fn as_ref(&self) -> &Uuid {
19 self
20 }
21}
22
23impl AsRef<[u8]> for Uuid {
24 #[inline]
25 fn as_ref(&self) -> &[u8] {
26 &self.0
27 }
28}
29
30impl From<Uuid> for std::vec::Vec<u8> {
31 fn from(value: Uuid) -> Self {
32 value.0.to_vec()
33 }
34}
35
36impl std::convert::TryFrom<std::vec::Vec<u8>> for Uuid {
37 type Error = Error;
38
39 fn try_from(value: std::vec::Vec<u8>) -> Result<Self, Self::Error> {
40 Uuid::from_slice(&value)
41 }
42}
43
44impl std::fmt::Debug for Uuid {
45 #[inline]
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 std::fmt::LowerHex::fmt(self, f)
48 }
49}
50
51impl std::fmt::Display for Uuid {
52 #[inline]
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 std::fmt::LowerHex::fmt(self, f)
55 }
56}
57
58impl From<Uuid> for String {
59 #[inline]
60 fn from(uuid: Uuid) -> Self {
61 uuid.to_string()
62 }
63}
64
65impl std::fmt::LowerHex for Uuid {
66 #[inline]
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 let mut hyphenated_buf = format_hyphenated(&self.0, false);
69 let hyphenated_str = unsafe { std::str::from_utf8_unchecked_mut(&mut hyphenated_buf) };
70
71 return f.write_str(hyphenated_str);
72 }
73}
74
75impl fmt::UpperHex for Uuid {
76 #[inline]
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 let mut hyphenated_buf = format_hyphenated(&self.0, false);
79 let hyphenated_str = unsafe { std::str::from_utf8_unchecked_mut(&mut hyphenated_buf) };
80 let upper_hex = hyphenated_str.to_uppercase();
81
82 return f.write_str(&upper_hex);
83 }
84}
85
86impl Uuid {
87 pub fn encode_lower<'buf>(&self, buffer: &'buf mut [u8]) -> &'buf mut str {
88 encode_hyphenated(self.as_bytes(), buffer, false)
89 }
90
91 pub const fn encode_buffer() -> [u8; HYPHENATED_LENGTH] {
92 [0; HYPHENATED_LENGTH]
93 }
94}
95
96#[inline]
97fn encode_hyphenated<'b>(src: &[u8; 16], buffer: &'b mut [u8], upper: bool) -> &'b mut str {
98 let buf = &mut buffer[..HYPHENATED_LENGTH];
99 let dst = buf.as_mut_ptr();
100
101 unsafe {
104 ptr::write(dst.cast(), format_hyphenated(src, upper));
105 std::str::from_utf8_unchecked_mut(buf)
106 }
107}
108
109const HYPHENATED_LENGTH: usize = 36;
110
111const UPPER: [u8; 16] = [
112 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',
113];
114const LOWER: [u8; 16] = [
115 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',
116];
117
118const fn format_hyphenated(src: &[u8; 16], upper: bool) -> [u8; 36] {
119 let lut = if upper { &UPPER } else { &LOWER };
120 let groups = [(0, 8), (9, 13), (14, 18), (19, 23), (24, 36)];
121 let mut dst = [0; 36];
122
123 let mut group_idx = 0;
124 let mut i = 0;
125 while group_idx < 5 {
126 let (start, end) = groups[group_idx];
127 let mut j = start;
128 while j < end {
129 let x = src[i];
130 i += 1;
131
132 dst[j] = lut[(x >> 4) as usize];
133 dst[j + 1] = lut[(x & 0x0f) as usize];
134 j += 2;
135 }
136 if group_idx < 4 {
137 dst[end] = b'-';
138 }
139 group_idx += 1;
140 }
141 dst
142}