1 #![allow(clippy::many_single_char_names)] 2 3 use super::*; 4 use bindings::Windows::Win32::System::Com::CoCreateGuid; 5 6 /// A globally unique identifier [(GUID)](https://docs.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid) 7 /// used to identify COM and WinRT interfaces. 8 #[repr(C)] 9 #[derive(Clone, Copy, Default, PartialEq, Eq, Hash)] 10 pub struct GUID { 11 pub data1: u32, 12 pub data2: u16, 13 pub data3: u16, 14 pub data4: [u8; 8], 15 } 16 17 impl GUID { 18 /// Creates a unique `GUID` value. new() -> Result<Self>19 pub fn new() -> Result<Self> { 20 unsafe { CoCreateGuid() } 21 } 22 23 /// Creates a `GUID` represented by the all-zero byte-pattern. zeroed() -> GUID24 pub const fn zeroed() -> GUID { 25 GUID { data1: 0, data2: 0, data3: 0, data4: [0, 0, 0, 0, 0, 0, 0, 0] } 26 } 27 28 /// Creates a `GUID` with the given constant values. from_values(data1: u32, data2: u16, data3: u16, data4: [u8; 8]) -> GUID29 pub const fn from_values(data1: u32, data2: u16, data3: u16, data4: [u8; 8]) -> GUID { 30 GUID { data1, data2, data3, data4 } 31 } 32 33 /// Creates a `GUID` for a "generic" WinRT type. from_signature(signature: ConstBuffer) -> GUID34 pub const fn from_signature(signature: ConstBuffer) -> GUID { 35 let data = ConstBuffer::from_slice(&[0x11, 0xf4, 0x7a, 0xd5, 0x7b, 0x73, 0x42, 0xc0, 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16, 0xad, 0xee]); 36 37 let data = data.push_other(signature); 38 39 let bytes = sha1(&data).bytes(); 40 let first = u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]); 41 42 let second = u16::from_be_bytes([bytes[4], bytes[5]]); 43 let mut third = u16::from_be_bytes([bytes[6], bytes[7]]); 44 third = (third & 0x0fff) | (5 << 12); 45 let fourth = (bytes[8] & 0x3f) | 0x80; 46 47 Self::from_values(first, second, third, [fourth, bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]]) 48 } 49 } 50 51 unsafe impl Abi for GUID { 52 type Abi = Self; 53 type DefaultType = Self; 54 } 55 56 unsafe impl RuntimeType for GUID { 57 const SIGNATURE: ConstBuffer = ConstBuffer::from_slice(b"g16"); 58 } 59 60 impl std::fmt::Debug for GUID { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 62 write!(f, "{:08X?}-{:04X?}-{:04X?}-{:02X?}{:02X?}-{:02X?}{:02X?}{:02X?}{:02X?}{:02X?}{:02X?}", self.data1, self.data2, self.data3, self.data4[0], self.data4[1], self.data4[2], self.data4[3], self.data4[4], self.data4[5], self.data4[6], self.data4[7]) 63 } 64 } 65 66 impl From<&str> for GUID { from(value: &str) -> GUID67 fn from(value: &str) -> GUID { 68 assert!(value.len() == 36, "Invalid GUID string"); 69 let mut bytes = value.bytes(); 70 71 let a = ((bytes.next_u32() * 16 + bytes.next_u32()) << 24) + ((bytes.next_u32() * 16 + bytes.next_u32()) << 16) + ((bytes.next_u32() * 16 + bytes.next_u32()) << 8) + bytes.next_u32() * 16 + bytes.next_u32(); 72 assert!(bytes.next().unwrap() == b'-', "Invalid GUID string"); 73 let b = ((bytes.next_u16() * 16 + (bytes.next_u16())) << 8) + bytes.next_u16() * 16 + bytes.next_u16(); 74 assert!(bytes.next().unwrap() == b'-', "Invalid GUID string"); 75 let c = ((bytes.next_u16() * 16 + bytes.next_u16()) << 8) + bytes.next_u16() * 16 + bytes.next_u16(); 76 assert!(bytes.next().unwrap() == b'-', "Invalid GUID string"); 77 let d = bytes.next_u8() * 16 + bytes.next_u8(); 78 let e = bytes.next_u8() * 16 + bytes.next_u8(); 79 assert!(bytes.next().unwrap() == b'-', "Invalid GUID string"); 80 81 let f = bytes.next_u8() * 16 + bytes.next_u8(); 82 let g = bytes.next_u8() * 16 + bytes.next_u8(); 83 let h = bytes.next_u8() * 16 + bytes.next_u8(); 84 let i = bytes.next_u8() * 16 + bytes.next_u8(); 85 let j = bytes.next_u8() * 16 + bytes.next_u8(); 86 let k = bytes.next_u8() * 16 + bytes.next_u8(); 87 88 GUID::from_values(a, b, c, [d, e, f, g, h, i, j, k]) 89 } 90 } 91 92 trait HexReader { next_u8(&mut self) -> u893 fn next_u8(&mut self) -> u8; next_u16(&mut self) -> u1694 fn next_u16(&mut self) -> u16; next_u32(&mut self) -> u3295 fn next_u32(&mut self) -> u32; 96 } 97 98 impl HexReader for std::str::Bytes<'_> { next_u8(&mut self) -> u899 fn next_u8(&mut self) -> u8 { 100 let value = self.next().unwrap(); 101 match value { 102 b'0'..=b'9' => value - b'0', 103 b'A'..=b'F' => 10 + value - b'A', 104 b'a'..=b'f' => 10 + value - b'a', 105 _ => panic!(), 106 } 107 } 108 next_u16(&mut self) -> u16109 fn next_u16(&mut self) -> u16 { 110 self.next_u8().into() 111 } 112 next_u32(&mut self) -> u32113 fn next_u32(&mut self) -> u32 { 114 self.next_u8().into() 115 } 116 } 117 118 #[cfg(test)] 119 mod tests { 120 use super::*; 121 122 #[test] test_new()123 fn test_new() { 124 let zeroed = GUID::zeroed(); 125 let unique = GUID::new().unwrap(); 126 assert_ne!(zeroed, unique); 127 } 128 } 129