Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
791 changed files
with
967,156 additions
and
917,807 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
use super::*; | ||
|
||
pub fn gen_async(def: &TypeDef, cfg: &TokenStream, gen: &Gen) -> TokenStream { | ||
let kind = def.async_kind(); | ||
|
||
if kind != AsyncKind::None { | ||
return gen_async_kind(kind, def, def, gen, cfg); | ||
} | ||
|
||
let interfaces = if def.kind() == TypeKind::Class { def.class_interfaces().iter().map(|(def, _)| def.clone()).collect() } else { def.required_interfaces() }; | ||
|
||
for interface in interfaces { | ||
let kind = interface.async_kind(); | ||
|
||
if kind != AsyncKind::None { | ||
return gen_async_kind(kind, &interface, def, gen, cfg); | ||
} | ||
} | ||
|
||
quote! {} | ||
} | ||
|
||
fn gen_async_kind(kind: AsyncKind, name: &TypeDef, self_name: &TypeDef, gen: &Gen, cfg: &TokenStream) -> TokenStream { | ||
let return_sig = match kind { | ||
AsyncKind::Operation | AsyncKind::OperationWithProgress => gen_element_name(&name.generics[0], gen), | ||
_ => quote! { () }, | ||
}; | ||
|
||
let handler = match kind { | ||
AsyncKind::Action => quote! { AsyncActionCompletedHandler }, | ||
AsyncKind::ActionWithProgress => quote! { AsyncActionWithProgressCompletedHandler }, | ||
AsyncKind::Operation => quote! { AsyncOperationCompletedHandler }, | ||
AsyncKind::OperationWithProgress => quote! { AsyncOperationWithProgressCompletedHandler }, | ||
_ => unimplemented!(), | ||
}; | ||
|
||
let constraints = gen_type_constraints(self_name, gen); | ||
let name = gen_type_name(self_name, gen); | ||
let namespace = gen.namespace("Windows.Foundation"); | ||
|
||
quote! { | ||
#cfg | ||
impl<#(#constraints)*> #name { | ||
pub fn get(&self) -> ::windows::core::Result<#return_sig> { | ||
if self.Status()? == #namespace AsyncStatus::Started { | ||
let (_waiter, signaler) = ::windows::core::Waiter::new(); | ||
self.SetCompleted(#namespace #handler::new(move |_sender, _args| { | ||
// Safe because the waiter will only be dropped after being signaled. | ||
unsafe { signaler.signal(); } | ||
Ok(()) | ||
}))?; | ||
} | ||
self.GetResults() | ||
} | ||
} | ||
#cfg | ||
#[cfg(feature = "std")] | ||
impl<#(#constraints)*> ::std::future::Future for #name { | ||
type Output = ::windows::core::Result<#return_sig>; | ||
|
||
fn poll(self: ::std::pin::Pin<&mut Self>, context: &mut ::std::task::Context) -> ::std::task::Poll<Self::Output> { | ||
if self.Status()? == #namespace AsyncStatus::Started { | ||
let waker = context.waker().clone(); | ||
|
||
let _ = self.SetCompleted(#namespace #handler::new(move |_sender, _args| { | ||
waker.wake_by_ref(); | ||
Ok(()) | ||
})); | ||
|
||
::std::task::Poll::Pending | ||
} else { | ||
::std::task::Poll::Ready(self.GetResults()) | ||
} | ||
} | ||
} | ||
} | ||
} |
9 changes: 5 additions & 4 deletions
9
crates/deps/gen2/src/callback.rs → crates/deps/bindgen/src/callbacks.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,255 @@ | ||
use super::*; | ||
|
||
pub fn gen(def: &TypeDef, gen: &Gen) -> TokenStream { | ||
if gen.sys { | ||
if def.default_interface().is_some() { | ||
let name = gen_type_ident(def, gen); | ||
quote! { | ||
pub type #name = *mut ::core::ffi::c_void; | ||
} | ||
} else { | ||
quote! {} | ||
} | ||
} else { | ||
gen_class(def, gen) | ||
} | ||
} | ||
|
||
fn gen_class(def: &TypeDef, gen: &Gen) -> TokenStream { | ||
let name = gen_type_ident(def, gen); | ||
let has_default = def.default_interface().is_some(); | ||
let interfaces = def.class_interfaces(); | ||
let mut methods = quote! {}; | ||
let mut method_names = BTreeMap::<String, u32>::new(); | ||
|
||
for (def, kind) in &interfaces { | ||
if gen.min_xaml && *kind == InterfaceKind::Base && gen.namespace.starts_with("Windows.UI.Xaml") && !def.namespace().starts_with("Windows.Foundation") { | ||
continue; | ||
} | ||
|
||
let mut vtable_offset = 6; | ||
for method in def.methods() { | ||
methods.combine(&gen_winrt_method(def, *kind, &method, vtable_offset, &mut method_names, gen)); | ||
vtable_offset += 1; | ||
} | ||
} | ||
|
||
let factories = interfaces.iter().filter_map(|(def, kind)| match kind { | ||
InterfaceKind::Static | InterfaceKind::Composable => { | ||
if def.methods().next().is_some() { | ||
let interface_name = format_token!("{}", def.name()); | ||
let interface_type = gen_type_name(def, gen); | ||
|
||
Some(quote! { | ||
pub fn #interface_name<R, F: FnOnce(&#interface_type) -> ::windows::core::Result<R>>( | ||
callback: F, | ||
) -> ::windows::core::Result<R> { | ||
static mut SHARED: ::windows::core::FactoryCache<#name, #interface_type> = | ||
::windows::core::FactoryCache::new(); | ||
unsafe { SHARED.call(callback) } | ||
} | ||
}) | ||
} else { | ||
None | ||
} | ||
} | ||
_ => None, | ||
}); | ||
|
||
if has_default { | ||
let new = if def.has_default_constructor() { | ||
quote! { | ||
pub fn new() -> ::windows::core::Result<Self> { | ||
Self::IActivationFactory(|f| f.activate_instance::<Self>()) | ||
} | ||
fn IActivationFactory<R, F: FnOnce(&::windows::core::IActivationFactory) -> ::windows::core::Result<R>>( | ||
callback: F, | ||
) -> ::windows::core::Result<R> { | ||
static mut SHARED: ::windows::core::FactoryCache<#name, ::windows::core::IActivationFactory> = | ||
::windows::core::FactoryCache::new(); | ||
unsafe { SHARED.call(callback) } | ||
} | ||
} | ||
} else { | ||
quote! {} | ||
}; | ||
|
||
let cfg = gen.type_cfg(def); | ||
|
||
let mut tokens = quote! { | ||
#cfg | ||
#[repr(transparent)] | ||
pub struct #name(::windows::core::IUnknown); | ||
#cfg | ||
impl #name { | ||
#new | ||
#methods | ||
#(#factories)* | ||
} | ||
}; | ||
|
||
tokens.combine(&gen_std_traits(def, &cfg, gen)); | ||
tokens.combine(&gen_runtime_trait(def, &cfg, gen)); | ||
tokens.combine(&gen_interface_trait(def, &cfg, gen)); | ||
tokens.combine(&gen_runtime_name(def, &cfg, gen)); | ||
tokens.combine(&gen_async(def, &cfg, gen)); | ||
tokens.combine(&gen_iterator(def, &cfg, gen)); | ||
tokens.combine(&gen_conversions(def, &cfg, gen)); | ||
tokens.combine(&gen_agile(def, &cfg, gen)); | ||
tokens | ||
} else { | ||
let mut tokens = quote! { | ||
pub struct #name {} | ||
impl #name { | ||
#methods | ||
#(#factories)* | ||
} | ||
}; | ||
|
||
tokens.combine(&gen_runtime_name(def, "e! {}, gen)); | ||
tokens | ||
} | ||
} | ||
|
||
fn gen_agile(def: &TypeDef, cfg: &TokenStream, gen: &Gen) -> TokenStream { | ||
if def.is_agile() { | ||
let name = gen_type_ident(def, gen); | ||
quote! { | ||
#cfg | ||
unsafe impl ::core::marker::Send for #name {} | ||
#cfg | ||
unsafe impl ::core::marker::Sync for #name {} | ||
} | ||
} else { | ||
TokenStream::new() | ||
} | ||
} | ||
|
||
fn gen_runtime_name(def: &TypeDef, cfg: &TokenStream, gen: &Gen) -> TokenStream { | ||
let name = gen_type_ident(def, gen); | ||
let runtime_name = format!("{}", def.type_name()); | ||
|
||
quote! { | ||
#cfg | ||
impl ::windows::core::RuntimeName for #name { | ||
const NAME: &'static str = #runtime_name; | ||
} | ||
} | ||
} | ||
|
||
fn gen_conversions(def: &TypeDef, cfg: &TokenStream, gen: &Gen) -> TokenStream { | ||
let name = gen_type_ident(def, gen); | ||
let mut tokens = quote! {}; | ||
|
||
for def in &[ElementType::IUnknown, ElementType::IInspectable] { | ||
let into = gen_element_name(def, gen); | ||
tokens.combine("e! { | ||
#cfg | ||
impl ::core::convert::From<#name> for #into { | ||
fn from(value: #name) -> Self { | ||
unsafe { ::core::mem::transmute(value) } | ||
} | ||
} | ||
#cfg | ||
impl ::core::convert::From<&#name> for #into { | ||
fn from(value: &#name) -> Self { | ||
::core::convert::From::from(::core::clone::Clone::clone(value)) | ||
} | ||
} | ||
#cfg | ||
impl<'a> ::windows::core::IntoParam<'a, #into> for #name { | ||
fn into_param(self) -> ::windows::core::Param<'a, #into> { | ||
::windows::core::Param::Owned(unsafe { ::core::mem::transmute(self) }) | ||
} | ||
} | ||
#cfg | ||
impl<'a> ::windows::core::IntoParam<'a, #into> for &#name { | ||
fn into_param(self) -> ::windows::core::Param<'a, #into> { | ||
::windows::core::Param::Borrowed(unsafe { ::core::mem::transmute(self) }) | ||
} | ||
} | ||
}); | ||
} | ||
|
||
for (def, kind) in def.class_interfaces() { | ||
if def.is_exclusive() { | ||
continue; | ||
} | ||
|
||
if kind != InterfaceKind::Default && kind != InterfaceKind::NonDefault && kind != InterfaceKind::Base { | ||
continue; | ||
} | ||
|
||
let into = gen_type_name(&def, gen); | ||
let mut cfg = cfg.clone(); | ||
cfg.combine(&gen.type_cfg(&def)); | ||
|
||
tokens.combine("e! { | ||
#cfg | ||
impl ::core::convert::TryFrom<#name> for #into { | ||
type Error = ::windows::core::Error; | ||
fn try_from(value: #name) -> ::windows::core::Result<Self> { | ||
::core::convert::TryFrom::try_from(&value) | ||
} | ||
} | ||
#cfg | ||
impl ::core::convert::TryFrom<&#name> for #into { | ||
type Error = ::windows::core::Error; | ||
fn try_from(value: &#name) -> ::windows::core::Result<Self> { | ||
::windows::core::Interface::cast(value) | ||
} | ||
} | ||
#cfg | ||
impl<'a> ::windows::core::IntoParam<'a, #into> for #name { | ||
fn into_param(self) -> ::windows::core::Param<'a, #into> { | ||
::windows::core::IntoParam::into_param(&self) | ||
} | ||
} | ||
#cfg | ||
impl<'a> ::windows::core::IntoParam<'a, #into> for &#name { | ||
fn into_param(self) -> ::windows::core::Param<'a, #into> { | ||
::core::convert::TryInto::<#into>::try_into(self) | ||
.map(::windows::core::Param::Owned) | ||
.unwrap_or(::windows::core::Param::None) | ||
} | ||
} | ||
}); | ||
} | ||
|
||
for def in def.bases() { | ||
let into = gen_type_name(&def, gen); | ||
let mut cfg = cfg.clone(); | ||
cfg.combine(&gen.type_cfg(&def)); | ||
|
||
tokens.combine("e! { | ||
#cfg | ||
impl ::core::convert::From<#name> for #into { | ||
fn from(value: #name) -> Self { | ||
::core::convert::From::from(&value) | ||
} | ||
} | ||
#cfg | ||
impl ::core::convert::From<&#name> for #into { | ||
fn from(value: &#name) -> Self { | ||
// This unwrap is legitimate because conversion to base can never fail because | ||
// the base can never change across versions. | ||
::windows::core::Interface::cast(value).unwrap() | ||
} | ||
} | ||
#cfg | ||
impl<'a> ::windows::core::IntoParam<'a, #into> for #name { | ||
fn into_param(self) -> ::windows::core::Param<'a, #into> { | ||
::windows::core::IntoParam::into_param(&self) | ||
} | ||
} | ||
#cfg | ||
impl<'a> ::windows::core::IntoParam<'a, #into> for &#name { | ||
fn into_param(self) -> ::windows::core::Param<'a, #into> { | ||
::windows::core::Param::Owned(::core::convert::Into::<#into>::into(self)) | ||
} | ||
} | ||
}); | ||
} | ||
|
||
tokens | ||
} |
Oops, something went wrong.