1use core::borrow;
5use core::convert::TryInto;
6use core::fmt;
7use core::mem;
8use core::str::from_utf8;
9
10#[repr(C)]
14#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, Ord, PartialOrd)]
15pub struct Guid {
16 data1: u32,
17 data2: u16,
18 data3: u16,
19 data4: [u8; 8],
20}
21
22impl Guid {
23 pub const fn zero() -> Self {
25 return Self {
26 data1: 0,
27 data2: 0,
28 data3: 0,
29 data4: [0; 8],
30 };
31 }
32
33 #[cfg(all(windows, not(proc_macro)))]
40 pub fn new() -> Self {
41 #[link(name = "rpcrt4")]
42 extern "system" {
43 fn UuidCreate(uuid: &mut Guid) -> u32;
44 }
45
46 let mut g = Guid::zero();
47
48 unsafe {
50 UuidCreate(&mut g);
51 }
52 return g;
53 }
54
55 pub fn from_name(event_provider_name: &str) -> Self {
65 let mut hasher = Sha1NonSecret::new();
66 hasher.write(&[
67 0x48, 0x2C, 0x2D, 0xB2, 0xC3, 0x90, 0x47, 0xC8, 0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1,
68 0x30, 0xFB,
69 ]);
70
71 let mut u16buf = [0u16; 2];
73 for upper_ch in event_provider_name.chars().flat_map(char::to_uppercase) {
74 for upper_u16 in upper_ch.encode_utf16(&mut u16buf) {
75 hasher.write(&upper_u16.to_be_bytes());
76 }
77 }
78
79 let mut v = hasher.finish();
80 v[7] = (v[7] & 0x0F) | 0x50;
81 return Guid::from_bytes_le(v[0..16].try_into().unwrap());
82 }
83
84 pub const fn from_fields(data1: u32, data2: u16, data3: u16, data4: [u8; 8]) -> Self {
92 return Self {
93 data1,
94 data2,
95 data3,
96 data4,
97 };
98 }
99
100 pub const fn from_bytes_be(bytes_be: &[u8; 16]) -> Self {
108 let b = bytes_be;
109 return Self {
110 data1: u32::from_be_bytes([b[0], b[1], b[2], b[3]]),
111 data2: u16::from_be_bytes([b[4], b[5]]),
112 data3: u16::from_be_bytes([b[6], b[7]]),
113 data4: [b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]],
114 };
115 }
116
117 pub const fn from_bytes_le(bytes_le: &[u8; 16]) -> Self {
125 let b = bytes_le;
126 return Self {
127 data1: u32::from_le_bytes([b[0], b[1], b[2], b[3]]),
128 data2: u16::from_le_bytes([b[4], b[5]]),
129 data3: u16::from_le_bytes([b[6], b[7]]),
130 data4: [b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15]],
131 };
132 }
133
134 pub const fn from_u128(value: &u128) -> Self {
142 return Self {
143 data1: u32::from_le(value.wrapping_shr(96) as u32),
144 data2: u16::from_le(value.wrapping_shr(80) as u16),
145 data3: u16::from_le(value.wrapping_shr(64) as u16),
146 data4: (*value as u64).to_be_bytes(),
147 };
148 }
149
150 pub fn try_parse(value: &str) -> Option<Self> {
165 return Self::try_parse_ascii(value.as_bytes());
166 }
167
168 pub fn try_parse_ascii(value: &[u8]) -> Option<Self> {
183 if value.len() < 32 {
184 return None;
185 }
186
187 let mut state = GuidParseState {
188 input: if value[0] != b'{' || value[value.len() - 1] != b'}' {
189 value
190 } else {
191 &value[1..value.len() - 1]
192 },
193 pos: 0,
194 dash: 0,
195 highbits: 0,
196 };
197
198 if (state.input.len() == 36)
199 & (state.input[8] == b'-')
200 & (state.input[13] == b'-')
201 & (state.input[18] == b'-')
202 & (state.input[23] == b'-')
203 {
204 state.dash = 1;
205 } else if state.input.len() != 32 {
206 return None;
207 }
208
209 let b = [
210 state.next(),
211 state.next(),
212 state.next(),
213 state.next(),
214 state.next_dash(),
215 state.next(),
216 state.next_dash(),
217 state.next(),
218 state.next_dash(),
219 state.next(),
220 state.next_dash(),
221 state.next(),
222 state.next(),
223 state.next(),
224 state.next(),
225 state.next(),
226 ];
227
228 if (state.highbits & 0xFFFFFF00) != 0 {
229 return None;
230 }
231
232 return Some(Self::from_bytes_be(&b));
233 }
234
235 #[allow(clippy::wrong_self_convention)]
243 pub const fn to_fields(&self) -> (u32, u16, u16, [u8; 8]) {
244 return (self.data1, self.data2, self.data3, self.data4);
245 }
246
247 pub const fn as_bytes_raw(&self) -> &[u8; 16] {
249 return unsafe { mem::transmute(self) };
250 }
251
252 #[allow(clippy::wrong_self_convention)]
260 pub const fn to_bytes_be(&self) -> [u8; 16] {
261 return [
262 (self.data1 >> 24) as u8,
263 (self.data1 >> 16) as u8,
264 (self.data1 >> 8) as u8,
265 self.data1 as u8,
266 (self.data2 >> 8) as u8,
267 self.data2 as u8,
268 (self.data3 >> 8) as u8,
269 self.data3 as u8,
270 self.data4[0],
271 self.data4[1],
272 self.data4[2],
273 self.data4[3],
274 self.data4[4],
275 self.data4[5],
276 self.data4[6],
277 self.data4[7],
278 ];
279 }
280
281 #[allow(clippy::wrong_self_convention)]
289 pub const fn to_bytes_le(&self) -> [u8; 16] {
290 return [
291 self.data1 as u8,
292 (self.data1 >> 8) as u8,
293 (self.data1 >> 16) as u8,
294 (self.data1 >> 24) as u8,
295 self.data2 as u8,
296 (self.data2 >> 8) as u8,
297 self.data3 as u8,
298 (self.data3 >> 8) as u8,
299 self.data4[0],
300 self.data4[1],
301 self.data4[2],
302 self.data4[3],
303 self.data4[4],
304 self.data4[5],
305 self.data4[6],
306 self.data4[7],
307 ];
308 }
309
310 #[allow(clippy::wrong_self_convention)]
318 pub const fn to_u128(&self) -> u128 {
319 return (self.data1.to_le() as u128) << 96
320 | (self.data2.to_le() as u128) << 80
321 | (self.data3.to_le() as u128) << 64
322 | u64::from_be_bytes(self.data4) as u128;
323 }
324
325 #[allow(clippy::wrong_self_convention)]
334 pub const fn to_utf8_bytes(&self) -> [u8; 36] {
335 const HEX_DIGITS: &[u8] = b"0123456789abcdef";
336 return [
337 HEX_DIGITS[((self.data1 >> 28) & 0xf) as usize],
338 HEX_DIGITS[((self.data1 >> 24) & 0xf) as usize],
339 HEX_DIGITS[((self.data1 >> 20) & 0xf) as usize],
340 HEX_DIGITS[((self.data1 >> 16) & 0xf) as usize],
341 HEX_DIGITS[((self.data1 >> 12) & 0xf) as usize],
342 HEX_DIGITS[((self.data1 >> 8) & 0xf) as usize],
343 HEX_DIGITS[((self.data1 >> 4) & 0xf) as usize],
344 HEX_DIGITS[(self.data1 & 0xf) as usize],
345 b'-',
346 HEX_DIGITS[((self.data2 >> 12) & 0xf) as usize],
347 HEX_DIGITS[((self.data2 >> 8) & 0xf) as usize],
348 HEX_DIGITS[((self.data2 >> 4) & 0xf) as usize],
349 HEX_DIGITS[(self.data2 & 0xf) as usize],
350 b'-',
351 HEX_DIGITS[((self.data3 >> 12) & 0xf) as usize],
352 HEX_DIGITS[((self.data3 >> 8) & 0xf) as usize],
353 HEX_DIGITS[((self.data3 >> 4) & 0xf) as usize],
354 HEX_DIGITS[(self.data3 & 0xf) as usize],
355 b'-',
356 HEX_DIGITS[((self.data4[0] >> 4) & 0xf) as usize],
357 HEX_DIGITS[(self.data4[0] & 0xf) as usize],
358 HEX_DIGITS[((self.data4[1] >> 4) & 0xf) as usize],
359 HEX_DIGITS[(self.data4[1] & 0xf) as usize],
360 b'-',
361 HEX_DIGITS[((self.data4[2] >> 4) & 0xf) as usize],
362 HEX_DIGITS[(self.data4[2] & 0xf) as usize],
363 HEX_DIGITS[((self.data4[3] >> 4) & 0xf) as usize],
364 HEX_DIGITS[(self.data4[3] & 0xf) as usize],
365 HEX_DIGITS[((self.data4[4] >> 4) & 0xf) as usize],
366 HEX_DIGITS[(self.data4[4] & 0xf) as usize],
367 HEX_DIGITS[((self.data4[5] >> 4) & 0xf) as usize],
368 HEX_DIGITS[(self.data4[5] & 0xf) as usize],
369 HEX_DIGITS[((self.data4[6] >> 4) & 0xf) as usize],
370 HEX_DIGITS[(self.data4[6] & 0xf) as usize],
371 HEX_DIGITS[((self.data4[7] >> 4) & 0xf) as usize],
372 HEX_DIGITS[(self.data4[7] & 0xf) as usize],
373 ];
374 }
375}
376
377impl fmt::Debug for Guid {
378 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
380 return f.write_str(from_utf8(&self.to_utf8_bytes()).unwrap());
381 }
382}
383
384impl borrow::Borrow<[u8; 16]> for Guid {
385 fn borrow(&self) -> &[u8; 16] {
387 return unsafe { mem::transmute(self) };
388 }
389}
390
391struct GuidParseState<'a> {
392 input: &'a [u8],
393 pos: usize,
394 dash: usize,
395 highbits: u32,
396}
397
398impl GuidParseState<'_> {
399 fn next(&mut self) -> u8 {
400 let val1 = Self::hex_to_u4(self.input[self.pos]);
401 let val2 = Self::hex_to_u4(self.input[self.pos + 1]);
402 self.pos += 2;
403 let val = (val1 << 4) | val2;
404 self.highbits |= val;
405 return val as u8;
406 }
407
408 fn next_dash(&mut self) -> u8 {
409 self.pos += self.dash;
410 return self.next();
411 }
412
413 fn hex_to_u4(ch: u8) -> u32 {
414 let hexval;
415 let mut index = ch.wrapping_sub(48);
416 if index < 10 {
417 hexval = index as u32;
418 } else {
419 index = (ch | 32).wrapping_sub(97);
420 hexval = if index < 6 { (index + 10) as u32 } else { 256 };
421 }
422 return hexval;
423 }
424}
425
426struct Sha1NonSecret {
431 chunk: [u8; 64], chunk_count: u32, chunk_pos: u8,
434 results: [u32; 5],
435}
436
437impl Sha1NonSecret {
438 pub fn new() -> Sha1NonSecret {
439 return Self {
440 chunk: [0; 64],
441 chunk_count: 0,
442 chunk_pos: 0,
443 results: [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0],
444 };
445 }
446
447 pub fn write_u8(&mut self, val: u8) {
448 self.chunk[self.chunk_pos as usize] = val;
449 self.chunk_pos = (self.chunk_pos + 1) & 63;
450 if self.chunk_pos == 0 {
451 self.drain();
452 }
453 }
454
455 pub fn write(&mut self, bytes: &[u8]) {
456 for i in bytes {
457 self.write_u8(*i);
458 }
459 }
460
461 pub fn finish(&mut self) -> [u8; 20] {
462 let total_bit_count = (self.chunk_count as u64 * 512) + (self.chunk_pos as u64 * 8);
464
465 self.write_u8(0x80);
467
468 while self.chunk_pos != 56 {
470 self.write_u8(0);
471 }
472
473 self.write(&total_bit_count.to_be_bytes());
475 debug_assert_eq!(self.chunk_pos, 0, "Bug: write should have drained");
476
477 let mut sha1 = [0u8; 20];
478 for i in 0..5 {
479 sha1[(i * 4)..(i * 4 + 4)].copy_from_slice(&self.results[i].to_be_bytes());
480 }
481
482 return sha1;
483 }
484
485 fn drain(&mut self) {
486 let mut w = [0u32; 80];
487
488 let mut wpos = 0;
489 while wpos != 16 {
490 w[wpos] = u32::from_be_bytes([
491 self.chunk[wpos * 4],
492 self.chunk[wpos * 4 + 1],
493 self.chunk[wpos * 4 + 2],
494 self.chunk[wpos * 4 + 3],
495 ]);
496 wpos += 1;
497 }
498
499 while wpos != 80 {
500 w[wpos] = (w[wpos - 3] ^ w[wpos - 8] ^ w[wpos - 14] ^ w[wpos - 16]).rotate_left(1);
501 wpos += 1;
502 }
503
504 let mut a = self.results[0];
505 let mut b = self.results[1];
506 let mut c = self.results[2];
507 let mut d = self.results[3];
508 let mut e = self.results[4];
509
510 wpos = 0;
511 while wpos != 20 {
512 const K: u32 = 0x5A827999;
513 let f = (b & c) | (!b & d);
514 let temp = a
515 .rotate_left(5)
516 .wrapping_add(f)
517 .wrapping_add(e)
518 .wrapping_add(K)
519 .wrapping_add(w[wpos]);
520 e = d;
521 d = c;
522 c = b.rotate_left(30);
523 b = a;
524 a = temp;
525 wpos += 1;
526 }
527
528 while wpos != 40 {
529 const K: u32 = 0x6ED9EBA1;
530 let f = b ^ c ^ d;
531 let temp = a
532 .rotate_left(5)
533 .wrapping_add(f)
534 .wrapping_add(e)
535 .wrapping_add(K)
536 .wrapping_add(w[wpos]);
537 e = d;
538 d = c;
539 c = b.rotate_left(30);
540 b = a;
541 a = temp;
542 wpos += 1;
543 }
544
545 while wpos != 60 {
546 const K: u32 = 0x8F1BBCDC;
547 let f = (b & c) | (b & d) | (c & d);
548 let temp = a
549 .rotate_left(5)
550 .wrapping_add(f)
551 .wrapping_add(e)
552 .wrapping_add(K)
553 .wrapping_add(w[wpos]);
554 e = d;
555 d = c;
556 c = b.rotate_left(30);
557 b = a;
558 a = temp;
559 wpos += 1;
560 }
561
562 while wpos != 80 {
563 const K: u32 = 0xCA62C1D6;
564 let f = b ^ c ^ d;
565 let temp = a
566 .rotate_left(5)
567 .wrapping_add(f)
568 .wrapping_add(e)
569 .wrapping_add(K)
570 .wrapping_add(w[wpos]);
571 e = d;
572 d = c;
573 c = b.rotate_left(30);
574 b = a;
575 a = temp;
576 wpos += 1;
577 }
578
579 self.results[0] = self.results[0].wrapping_add(a);
580 self.results[1] = self.results[1].wrapping_add(b);
581 self.results[2] = self.results[2].wrapping_add(c);
582 self.results[3] = self.results[3].wrapping_add(d);
583 self.results[4] = self.results[4].wrapping_add(e);
584 self.chunk_count += 1;
585 }
586}