1use crate::util::{byte_to_ascii_hex_lower, parse_byte_from_ascii_str_at};
10use crate::GuidFromStrError;
11use core::fmt::{self, Display, Formatter};
12use core::str::{self, FromStr};
13
14#[cfg(feature = "serde")]
15use {
16 serde::de::{self, Visitor},
17 serde::{Deserialize, Deserializer, Serialize, Serializer},
18};
19
20#[cfg(feature = "bytemuck")]
21use bytemuck::{Pod, Zeroable};
22
23#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
38#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
39#[repr(C)]
40pub struct Guid {
41 time_low: u32,
47 time_mid: [u8; 2],
48 time_high_and_version: [u8; 2],
49 clock_seq_high_and_reserved: u8,
50 clock_seq_low: u8,
51 node: [u8; 6],
52}
53
54impl Guid {
55 pub const ZERO: Self = Self {
57 time_low: 0,
58 time_mid: [0, 0],
59 time_high_and_version: [0, 0],
60 clock_seq_high_and_reserved: 0,
61 clock_seq_low: 0,
62 node: [0; 6],
63 };
64
65 #[must_use]
67 pub const fn new(
68 time_low: [u8; 4],
69 time_mid: [u8; 2],
70 time_high_and_version: [u8; 2],
71 clock_seq_high_and_reserved: u8,
72 clock_seq_low: u8,
73 node: [u8; 6],
74 ) -> Self {
75 Self {
76 time_low: u32::from_ne_bytes([
77 time_low[0],
78 time_low[1],
79 time_low[2],
80 time_low[3],
81 ]),
82 time_mid: [time_mid[0], time_mid[1]],
83 time_high_and_version: [
84 time_high_and_version[0],
85 time_high_and_version[1],
86 ],
87 clock_seq_high_and_reserved,
88 clock_seq_low,
89 node,
90 }
91 }
92
93 #[must_use]
115 pub const fn from_random_bytes(mut random_bytes: [u8; 16]) -> Self {
116 random_bytes[8] &= 0b1011_1111;
118 random_bytes[8] |= 0b1000_0000;
119 random_bytes[7] &= 0b0000_1111;
121 random_bytes[7] |= 0b0100_1111;
122
123 Self::from_bytes(random_bytes)
124 }
125
126 #[must_use]
137 pub const fn is_zero(self) -> bool {
138 let b = self.to_bytes();
139 b[0] == 0
140 && b[1] == 0
141 && b[2] == 0
142 && b[3] == 0
143 && b[4] == 0
144 && b[5] == 0
145 && b[6] == 0
146 && b[7] == 0
147 && b[8] == 0
148 && b[9] == 0
149 && b[10] == 0
150 && b[11] == 0
151 && b[12] == 0
152 && b[13] == 0
153 && b[14] == 0
154 && b[15] == 0
155 }
156
157 #[must_use]
159 pub const fn time_low(self) -> [u8; 4] {
160 self.time_low.to_ne_bytes()
161 }
162
163 #[must_use]
165 pub const fn time_mid(self) -> [u8; 2] {
166 self.time_mid
167 }
168
169 #[must_use]
172 pub const fn time_high_and_version(self) -> [u8; 2] {
173 self.time_high_and_version
174 }
175
176 #[must_use]
179 pub const fn clock_seq_high_and_reserved(self) -> u8 {
180 self.clock_seq_high_and_reserved
181 }
182
183 #[must_use]
185 pub const fn clock_seq_low(self) -> u8 {
186 self.clock_seq_low
187 }
188
189 #[must_use]
191 pub const fn node(self) -> [u8; 6] {
192 self.node
193 }
194
195 #[must_use]
208 pub const fn variant(self) -> Variant {
209 let bits = (self.clock_seq_high_and_reserved & 0b1110_0000) >> 5;
211
212 if (bits & 0b100) == 0 {
213 Variant::ReservedNcs
214 } else if (bits & 0b010) == 0 {
215 Variant::Rfc4122
216 } else if (bits & 0b001) == 0 {
217 Variant::ReservedMicrosoft
218 } else {
219 Variant::ReservedFuture
220 }
221 }
222
223 #[must_use]
236 pub const fn version(self) -> u8 {
237 (self.time_high_and_version[1] & 0b1111_0000) >> 4
238 }
239
240 pub const fn try_parse(s: &str) -> Result<Self, GuidFromStrError> {
245 let s = s.as_bytes();
247
248 if s.len() != 36 {
249 return Err(GuidFromStrError::Length);
250 }
251
252 let sep = b'-';
253 if s[8] != sep {
254 return Err(GuidFromStrError::Separator(8));
255 }
256 if s[13] != sep {
257 return Err(GuidFromStrError::Separator(13));
258 }
259 if s[18] != sep {
260 return Err(GuidFromStrError::Separator(18));
261 }
262 if s[23] != sep {
263 return Err(GuidFromStrError::Separator(23));
264 }
265
266 Ok(Self::from_bytes([
267 mtry!(parse_byte_from_ascii_str_at(s, 6)),
268 mtry!(parse_byte_from_ascii_str_at(s, 4)),
269 mtry!(parse_byte_from_ascii_str_at(s, 2)),
270 mtry!(parse_byte_from_ascii_str_at(s, 0)),
271 mtry!(parse_byte_from_ascii_str_at(s, 11)),
272 mtry!(parse_byte_from_ascii_str_at(s, 9)),
273 mtry!(parse_byte_from_ascii_str_at(s, 16)),
274 mtry!(parse_byte_from_ascii_str_at(s, 14)),
275 mtry!(parse_byte_from_ascii_str_at(s, 19)),
276 mtry!(parse_byte_from_ascii_str_at(s, 21)),
277 mtry!(parse_byte_from_ascii_str_at(s, 24)),
278 mtry!(parse_byte_from_ascii_str_at(s, 26)),
279 mtry!(parse_byte_from_ascii_str_at(s, 28)),
280 mtry!(parse_byte_from_ascii_str_at(s, 30)),
281 mtry!(parse_byte_from_ascii_str_at(s, 32)),
282 mtry!(parse_byte_from_ascii_str_at(s, 34)),
283 ]))
284 }
285
286 #[must_use]
303 #[track_caller]
304 pub const fn parse_or_panic(s: &str) -> Self {
305 match Self::try_parse(s) {
306 Ok(g) => g,
307 Err(GuidFromStrError::Length) => {
308 panic!("GUID string has wrong length (expected 36 bytes)");
309 }
310 Err(GuidFromStrError::Separator(_)) => {
311 panic!("GUID string is missing one or more separators (`-`)");
312 }
313 Err(GuidFromStrError::Hex(_)) => {
314 panic!("GUID string contains one or more invalid characters");
315 }
316 }
317 }
318
319 #[must_use]
321 pub const fn from_bytes(bytes: [u8; 16]) -> Self {
322 Self::new(
323 [bytes[0], bytes[1], bytes[2], bytes[3]],
324 [bytes[4], bytes[5]],
325 [bytes[6], bytes[7]],
326 bytes[8],
327 bytes[9],
328 [
329 bytes[10], bytes[11], bytes[12], bytes[13], bytes[14],
330 bytes[15],
331 ],
332 )
333 }
334
335 #[must_use]
337 pub const fn to_bytes(self) -> [u8; 16] {
338 let time_low = self.time_low();
339
340 [
341 time_low[0],
342 time_low[1],
343 time_low[2],
344 time_low[3],
345 self.time_mid[0],
346 self.time_mid[1],
347 self.time_high_and_version[0],
348 self.time_high_and_version[1],
349 self.clock_seq_high_and_reserved,
350 self.clock_seq_low,
351 self.node[0],
352 self.node[1],
353 self.node[2],
354 self.node[3],
355 self.node[4],
356 self.node[5],
357 ]
358 }
359
360 #[must_use]
364 pub const fn to_ascii_hex_lower(self) -> [u8; 36] {
365 let bytes = self.to_bytes();
366
367 let mut buf = [0; 36];
368 (buf[0], buf[1]) = byte_to_ascii_hex_lower(bytes[3]);
369 (buf[2], buf[3]) = byte_to_ascii_hex_lower(bytes[2]);
370 (buf[4], buf[5]) = byte_to_ascii_hex_lower(bytes[1]);
371 (buf[6], buf[7]) = byte_to_ascii_hex_lower(bytes[0]);
372 buf[8] = b'-';
373 (buf[9], buf[10]) = byte_to_ascii_hex_lower(bytes[5]);
374 (buf[11], buf[12]) = byte_to_ascii_hex_lower(bytes[4]);
375 buf[13] = b'-';
376 (buf[14], buf[15]) = byte_to_ascii_hex_lower(bytes[7]);
377 (buf[16], buf[17]) = byte_to_ascii_hex_lower(bytes[6]);
378 buf[18] = b'-';
379 (buf[19], buf[20]) = byte_to_ascii_hex_lower(bytes[8]);
380 (buf[21], buf[22]) = byte_to_ascii_hex_lower(bytes[9]);
381 buf[23] = b'-';
382 (buf[24], buf[25]) = byte_to_ascii_hex_lower(bytes[10]);
383 (buf[26], buf[27]) = byte_to_ascii_hex_lower(bytes[11]);
384 (buf[28], buf[29]) = byte_to_ascii_hex_lower(bytes[12]);
385 (buf[30], buf[31]) = byte_to_ascii_hex_lower(bytes[13]);
386 (buf[32], buf[33]) = byte_to_ascii_hex_lower(bytes[14]);
387 (buf[34], buf[35]) = byte_to_ascii_hex_lower(bytes[15]);
388 buf
389 }
390}
391
392impl Default for Guid {
393 fn default() -> Self {
394 Self::ZERO
395 }
396}
397
398impl Display for Guid {
399 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
400 let ascii = self.to_ascii_hex_lower();
401 let s = str::from_utf8(&ascii).unwrap();
403 f.write_str(s)
404 }
405}
406
407impl FromStr for Guid {
408 type Err = GuidFromStrError;
409
410 fn from_str(s: &str) -> Result<Self, Self::Err> {
416 Self::try_parse(s)
417 }
418}
419
420#[cfg(feature = "serde")]
421impl Serialize for Guid {
422 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
423 where
424 S: Serializer,
425 {
426 let ascii = self.to_ascii_hex_lower();
427 let s = str::from_utf8(&ascii).unwrap();
429 serializer.serialize_str(s)
430 }
431}
432
433#[cfg(feature = "serde")]
434struct DeserializerVisitor;
435
436#[cfg(feature = "serde")]
437impl<'de> Visitor<'de> for DeserializerVisitor {
438 type Value = Guid;
439
440 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
441 formatter.write_str(
442 "a string in the format \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"",
443 )
444 }
445
446 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
447 where
448 E: de::Error,
449 {
450 Guid::try_parse(value).map_err(E::custom)
451 }
452}
453
454#[cfg(feature = "serde")]
455impl<'de> Deserialize<'de> for Guid {
456 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
457 where
458 D: Deserializer<'de>,
459 {
460 deserializer.deserialize_str(DeserializerVisitor)
461 }
462}
463
464#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
468pub enum Variant {
469 ReservedNcs,
471
472 Rfc4122,
474
475 ReservedMicrosoft,
477
478 ReservedFuture,
480}