@@ -8,6 +8,7 @@ use tokens::*;
8
8
pub fn implement ( attributes : proc_macro:: TokenStream , original_type : proc_macro:: TokenStream ) -> proc_macro:: TokenStream {
9
9
let attributes = syn:: parse_macro_input!( attributes as ImplementAttributes ) ;
10
10
let generics = attributes. generics ( ) ;
11
+ let interfaces_len = Literal :: usize_unsuffixed ( attributes. implement . len ( ) ) ;
11
12
12
13
let constraints = quote ! {
13
14
#( #generics: :: windows:: core:: RuntimeType + ' static , ) *
@@ -144,6 +145,7 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro:
144
145
}
145
146
}
146
147
impl <#constraints> #original_ident:: <#( #generics, ) * > {
148
+ /// Box and pin `self` and then try to cast it as the supplied interface
147
149
fn alloc<I : :: windows:: core:: Interface >( self ) -> :: windows:: core:: Result <I > {
148
150
let this = #impl_ident:: <#( #generics, ) * >:: new( self ) ;
149
151
let boxed = :: core:: mem:: ManuallyDrop :: new( :: std:: boxed:: Box :: new( this) ) ;
@@ -157,6 +159,18 @@ pub fn implement(attributes: proc_macro::TokenStream, original_type: proc_macro:
157
159
}
158
160
result
159
161
}
162
+
163
+ /// Try casting as the provided interface
164
+ ///
165
+ /// # Safety
166
+ ///
167
+ /// This function can only be safely called if `self` has been heap allocated and pinned using
168
+ /// the mechanisms provided by `implement` macro.
169
+ unsafe fn cast<I : :: windows:: core:: Interface >( & self ) -> :: windows:: core:: Result <I > {
170
+ let boxed = ( self as * const _ as * const :: windows:: core:: RawPtr ) . sub( 2 + #interfaces_len) as * mut #impl_ident:: <#( #generics, ) * >;
171
+ let mut result = None ;
172
+ <#impl_ident:: <#( #generics, ) * > as :: windows:: core:: IUnknownImpl >:: QueryInterface ( & * boxed, & I :: IID , & mut result as * mut _ as _) . and_some( result)
173
+ }
160
174
}
161
175
impl <#constraints> :: windows:: core:: Compose for #original_ident:: <#( #generics, ) * > {
162
176
unsafe fn compose<' a>( implementation: Self ) -> ( :: windows:: core:: IInspectable , & ' a mut :: core:: option:: Option <:: windows:: core:: IInspectable >) {
0 commit comments