Skip to content

Commit

Permalink
ConstBuffer
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr committed Dec 7, 2023
1 parent 43bcb74 commit 1488eb0
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 36 deletions.
53 changes: 25 additions & 28 deletions crates/libs/bindgen/src/rust/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Self>() }
} else if generics.is_empty() {
quote! { ::windows_core::imp::ConstBuffer::for_interface::<Self>() }
} 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")")
}
}
};
Expand Down
48 changes: 44 additions & 4 deletions crates/libs/core/src/imp/sha1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ pub struct ConstBuffer {
}

impl ConstBuffer {
pub const fn for_class<T: crate::RuntimeName + crate::ComInterface>() -> 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<T: crate::ComInterface>() -> Self {
Self::new().push_guid(&T::IID)
}

pub const fn from_slice(slice: &[u8]) -> Self {
let s = Self::new();
s.push_slice(slice)
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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;
}
Expand Down
19 changes: 15 additions & 4 deletions crates/tests/winrt/tests/generic_guids.rs
Original file line number Diff line number Diff line change
@@ -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<IStringable>;
Expand Down Expand Up @@ -204,6 +217,4 @@ fn generic_guids() -> windows::core::Result<()> {
);

// TODO: structs and enums

Ok(())
}

0 comments on commit 1488eb0

Please sign in to comment.