diff --git a/crates/libs/bindgen/src/rust/writer.rs b/crates/libs/bindgen/src/rust/writer.rs index 532e433c50..7f2c625b97 100644 --- a/crates/libs/bindgen/src/rust/writer.rs +++ b/crates/libs/bindgen/src/rust/writer.rs @@ -639,42 +639,39 @@ impl Writer { pub fn interface_winrt_trait(&self, def: TypeDef, generics: &[Type], ident: &TokenStream, constraints: &TokenStream, _phantoms: &TokenStream, features: &TokenStream) -> TokenStream { if def.flags().contains(TypeAttributes::WindowsRuntime) { let type_signature = if def.kind() == TypeKind::Class { - let type_signature = Literal::byte_string(type_def_signature(def, generics).as_bytes()); - quote! { ::windows_core::imp::ConstBuffer::from_slice(#type_signature) } + quote! { ::windows_core::imp::ConstBuffer::for_class::() } + } else if generics.is_empty() { + quote! { ::windows_core::imp::ConstBuffer::for_interface::() } } else { let signature = Literal::byte_string( // TODO: workaround for riddle winmd generation (no attribute support) if let Some(guid) = type_def_guid(def) { format!("{{{:#?}}}", guid) } else { "TODO".to_string() }.as_bytes(), ); - if generics.is_empty() { - quote! { ::windows_core::imp::ConstBuffer::from_slice(#signature) } - } else { - let generics = generics.iter().enumerate().map(|(index, g)| { - let g = self.type_name(g); - let semi = if index != generics.len() - 1 { - Some(quote! { - .push_slice(b";") - }) - } else { - None - }; - - quote! { - .push_other(<#g as ::windows_core::RuntimeType>::SIGNATURE) - #semi - } - }); + let generics = generics.iter().enumerate().map(|(index, g)| { + let g = self.type_name(g); + let semi = if index != generics.len() - 1 { + Some(quote! { + .push_slice(b";") + }) + } else { + None + }; quote! { - { - ::windows_core::imp::ConstBuffer::new() - .push_slice(b"pinterface(") - .push_slice(#signature) - .push_slice(b";") - #(#generics)* - .push_slice(b")") - } + .push_other(<#g as ::windows_core::RuntimeType>::SIGNATURE) + #semi + } + }); + + quote! { + { + ::windows_core::imp::ConstBuffer::new() + .push_slice(b"pinterface(") + .push_slice(#signature) + .push_slice(b";") + #(#generics)* + .push_slice(b")") } } }; diff --git a/crates/libs/core/src/imp/sha1.rs b/crates/libs/core/src/imp/sha1.rs index 5962a3d022..55afc8ce23 100644 --- a/crates/libs/core/src/imp/sha1.rs +++ b/crates/libs/core/src/imp/sha1.rs @@ -16,6 +16,14 @@ pub struct ConstBuffer { } impl ConstBuffer { + pub const fn for_class() -> Self { + Self::new().push_slice(b"rc(").push_slice(T::NAME.as_bytes()).push(b';').push_guid(&T::IID).push(b')') + } + + pub const fn for_interface() -> Self { + Self::new().push_guid(&T::IID) + } + pub const fn from_slice(slice: &[u8]) -> Self { let s = Self::new(); s.push_slice(slice) @@ -37,12 +45,40 @@ impl ConstBuffer { self.head } - const fn as_slice(&self) -> &[u8] { - &self.data + pub fn as_slice(&self) -> &[u8] { + &self.data[..self.head] } pub const fn push_other(self, other: Self) -> Self { - self.push_amount(other.as_slice(), other.len()) + self.push_amount(&other.data, other.len()) + } + + const fn push(mut self, value: u8) -> Self { + self.data[self.head] = value; + self.head += 1; + self + } + + const fn push_hex_u8(self, value: u8) -> Self { + const fn digit(mut value: u8) -> u8 { + value &= 0xF; + + if value < 10 { + b'0' + value + } else { + b'a' + (value - 10) + } + } + + self.push(digit(value >> 4)).push(digit(value)) + } + + const fn push_hex_u16(self, value: u16) -> Self { + self.push_hex_u8((value >> 8) as u8).push_hex_u8((value & 0xFF) as u8) + } + + const fn push_hex_u32(self, value: u32) -> Self { + self.push_hex_u16((value >> 16) as u16).push_hex_u16((value & 0xFFFF) as u16) } const fn push_amount(mut self, slice: &[u8], amount: usize) -> Self { @@ -54,6 +90,10 @@ impl ConstBuffer { self.head += i; self } + + const fn push_guid(self, guid: &crate::GUID) -> Self { + self.push(b'{').push_hex_u32(guid.data1).push(b'-').push_hex_u16(guid.data2).push(b'-').push_hex_u16(guid.data3).push(b'-').push_hex_u16((guid.data4[0] as u16) << 8 | guid.data4[1] as u16).push(b'-').push_hex_u16((guid.data4[2] as u16) << 8 | guid.data4[3] as u16).push_hex_u16((guid.data4[4] as u16) << 8 | guid.data4[5] as u16).push_hex_u16((guid.data4[6] as u16) << 8 | guid.data4[7] as u16).push(b'}') + } } struct Blocks { @@ -92,7 +132,7 @@ const fn process_blocks(mut blocks: Blocks, data: &ConstBuffer, mut len: u64, mu i += 64; } else { let num_elems = data.len() - i; - blocks.data = clone_from_slice_64(blocks.data, data.as_slice(), i, num_elems); + blocks.data = clone_from_slice_64(blocks.data, &data.data, i, num_elems); blocks.len = num_elems as u32; break; } diff --git a/crates/tests/winrt/tests/generic_guids.rs b/crates/tests/winrt/tests/generic_guids.rs index 9fc69b819a..c6730c2f36 100644 --- a/crates/tests/winrt/tests/generic_guids.rs +++ b/crates/tests/winrt/tests/generic_guids.rs @@ -1,7 +1,20 @@ -use windows::{Foundation::Collections::*, Foundation::*}; +use windows::{core::*, Foundation::Collections::*, Foundation::*}; #[test] -fn generic_guids() -> windows::core::Result<()> { +fn signatures() { + assert_eq!( + Uri::SIGNATURE.as_slice(), + b"rc(Windows.Foundation.Uri;{9e365e57-48b2-4160-956f-c7385120bbfc})" + ); + + assert_eq!( + IAsyncInfo::SIGNATURE.as_slice(), + b"{00000036-0000-0000-c000-000000000046}" + ); +} + +#[test] +fn generic_guids() { use windows::core::ComInterface; type A = IIterable; @@ -204,6 +217,4 @@ fn generic_guids() -> windows::core::Result<()> { ); // TODO: structs and enums - - Ok(()) }