Skip to content

Commit

Permalink
Add back cast but make it unsafe
Browse files Browse the repository at this point in the history
  • Loading branch information
rylev committed May 11, 2022
1 parent 92caf84 commit efdbbc8
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 3 deletions.
14 changes: 14 additions & 0 deletions crates/libs/implement/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use tokens::*;
pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro::TokenStream) -> proc_macro::TokenStream {
let attributes = syn::parse_macro_input!(attributes as ImplementAttributes);
let generics = attributes.generics();
let interfaces_len = Literal::usize_unsuffixed(attributes.implement.len());

let constraints = quote! {
#(#generics: ::windows::core::RuntimeType + 'static,)*
Expand Down Expand Up @@ -144,6 +145,7 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro:
}
}
impl <#constraints> #original_ident::<#(#generics,)*> {
/// Box and pin `self` and then try to cast it as the supplied interface
fn alloc<I: ::windows::core::Interface>(self) -> ::windows::core::Result<I> {
let this = #impl_ident::<#(#generics,)*>::new(self);
let boxed = ::core::mem::ManuallyDrop::new(::std::boxed::Box::new(this));
Expand All @@ -157,6 +159,18 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro:
}
result
}

/// Try casting as the provided interface
///
/// # Safety
///
/// This function can only be safely called if `self` has been heap allocated and pinned using
/// the mechanisms provided by `implement` macro.
unsafe fn cast<I: ::windows::core::Interface>(&self) -> ::windows::core::Result<I> {
let boxed = (self as *const _ as *const ::windows::core::RawPtr).sub(2 + #interfaces_len) as *mut #impl_ident::<#(#generics,)*>;
let mut result = None;
<#impl_ident::<#(#generics,)*> as ::windows::core::IUnknownImpl>::QueryInterface(&*boxed, &I::IID, &mut result as *mut _ as _).and_some(result)
}
}
impl <#constraints> ::windows::core::Compose for #original_ident::<#(#generics,)*> {
unsafe fn compose<'a>(implementation: Self) -> (::windows::core::IInspectable, &'a mut ::core::option::Option<::windows::core::IInspectable>) {
Expand Down
2 changes: 1 addition & 1 deletion crates/tests/nightly_implement/tests/cast_self.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ struct App;
#[allow(non_snake_case)]
impl IApplicationOverrides_Impl for App {
fn OnLaunched(&self, _: &Option<LaunchActivatedEventArgs>) -> Result<()> {
let app: Application = self.cast()?;
let app: Application = unsafe { self.cast()? };
assert!(app.FocusVisualKind()? == FocusVisualKind::DottedLine);
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion crates/tests/nightly_implement/tests/into_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ where
#[allow(non_snake_case)]
impl<T: RuntimeType + 'static> IIterable_Impl<T> for Iterable<T> {
fn First(&self) -> Result<IIterator<T>> {
Ok(Iterator::<T>((self.cast()?, 0).into()).into())
Ok(Iterator::<T>((unsafe { self.cast()? }, 0).into()).into())
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/tests/nightly_vector/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl<T: ::windows::core::RuntimeType + 'static> IVector_Impl<T> for Vector<T> {
self.Size()
}
fn GetView(&self) -> Result<windows::Foundation::Collections::IVectorView<T>> {
self.cast()
unsafe { self.cast() }
}
fn IndexOf(&self, value: &T::DefaultType, result: &mut u32) -> Result<bool> {
self.IndexOf(value, result)
Expand Down

0 comments on commit efdbbc8

Please sign in to comment.