Skip to content

Commit

Permalink
Add explicit path support to the interface macro (#2976)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Apr 8, 2024
1 parent e7a361a commit bedd359
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 14 deletions.
27 changes: 13 additions & 14 deletions crates/libs/interface/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,41 +341,40 @@ impl Interface {
}

fn parent_vtable(&self) -> Option<proc_macro2::TokenStream> {
if let Some(i) = self.parent_ident() {
let i = quote::format_ident!("{}_Vtbl", i);
Some(quote!(#i))
if let Some((ident, path)) = self.parent_path().split_last() {
let ident = quote::format_ident!("{}_Vtbl", ident);
Some(quote! { #(#path::)* #ident })
} else {
None
}
}

fn parent_is_iunknown(&self) -> bool {
if let Some(ident) = self.parent_ident() {
if let Some(ident) = self.parent_path().last() {
ident == "IUnknown"
} else {
false
}
}

fn parent_ident(&self) -> Option<&syn::Ident> {
fn parent_path(&self) -> Vec<syn::Ident> {
if let Some(parent) = &self.parent {
Some(&parent.segments.last().as_ref().expect("segements should never be empty").ident)
parent.segments.iter().map(|segment| segment.ident.clone()).collect()
} else {
None
vec![]
}
}

/// Gets the parent trait constrait which is nothing if the parent is IUnknown
fn parent_trait_constraint(&self) -> proc_macro2::TokenStream {
if let Some(i) = self.parent_ident() {
if i == "IUnknown" {
return quote!();
if let Some((ident, path)) = self.parent_path().split_last() {
if ident != "IUnknown" {
let ident = quote::format_ident!("{}_Impl", ident);
return quote! { #(#path::)* #ident };
}
let i = quote::format_ident!("{}_Impl", i);
quote!(#i)
} else {
quote!()
}

quote! {}
}
}

Expand Down
39 changes: 39 additions & 0 deletions crates/tests/interface/tests/no_use.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#![allow(non_snake_case)]

// This is a variant of the interface_core/no_use.rs test for use with more complex paths provided by the windows crate.

#[windows::core::interface("BD1AE5E0-A6AE-11CE-BD37-504200C10000")]
unsafe trait ITestPersistMemory: windows::Win32::System::Com::IPersist {
unsafe fn IsDirty(&self) -> windows::core::HRESULT;
}

#[windows::core::implement(ITestPersistMemory, windows::Win32::System::Com::IPersist)]
struct Test;

impl windows::Win32::System::Com::IPersist_Impl for Test {
fn GetClassID(&self) -> windows::core::Result<windows::core::GUID> {
Ok("CEE1D356-0860-4262-90D4-C77423F0E352".into())
}
}

impl ITestPersistMemory_Impl for Test {
unsafe fn IsDirty(&self) -> windows::core::HRESULT {
windows::Win32::Foundation::S_FALSE
}
}

#[test]
fn test() -> windows::core::Result<()> {
unsafe {
let p: windows::Win32::System::Com::IPersist = Test.into();
assert_eq!(
p.GetClassID()?,
"CEE1D356-0860-4262-90D4-C77423F0E352".into()
);

let m: ITestPersistMemory = windows_core::Interface::cast(&p)?;
assert_eq!(m.IsDirty(), windows::Win32::Foundation::S_FALSE);

Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#![allow(non_snake_case)]

// This tests uses `windows_core` via an asterisk to test that the interface/implement macros support this mode
// as opposed to no_use.rs which tests the opposite.

use windows_core::*;

#[interface("72cd87fa-9c99-42e0-8986-84a76f08fc5a")]
Expand Down
File renamed without changes.
26 changes: 26 additions & 0 deletions crates/tests/interface_core/tests/no_use.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#![allow(non_snake_case)]

// This tests uses `windows_core` explicitly to test that the interface/implement macros support this mode
// as opposed to asterisk_use.rs which tests the opposite.

#[windows_core::interface("72cd87fa-9c99-42e0-8986-84a76f08fc5a")]
unsafe trait ITest: windows_core::IUnknown {
unsafe fn Test(&self) -> windows_core::HRESULT;
}

#[windows_core::implement(ITest)]
struct Test;

impl ITest_Impl for Test {
unsafe fn Test(&self) -> windows_core::HRESULT {
windows_core::HRESULT(123)
}
}

#[test]
fn test() {
unsafe {
let test: ITest = Test.into();
assert_eq!(test.Test(), windows_core::HRESULT(123));
}
}

0 comments on commit bedd359

Please sign in to comment.