Skip to content

Commit

Permalink
Reintroduces handle types for the windows crate (#1423)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr committed Jan 11, 2022
1 parent 4832678 commit e8f2eac
Show file tree
Hide file tree
Showing 89 changed files with 7,944 additions and 340 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Expand Up @@ -11,5 +11,7 @@ members = [
"crates/tests/debug",
"crates/tests/enums",
"crates/tests/sys",
"crates/tests/handles",
"crates/tests/agile",
]
exclude = ["crates/tests/component"]
88 changes: 88 additions & 0 deletions crates/libs/bindgen/src/handles.rs
@@ -0,0 +1,88 @@
use super::*;

pub fn gen(def: &TypeDef, gen: &Gen) -> TokenStream {
if gen.sys {
gen_sys_handle(def, gen)
} else {
gen_win_handle(def, gen)
}
}

pub fn gen_sys_handle(def: &TypeDef, gen: &Gen) -> TokenStream {
let ident = gen_ident(def.name());
let signature = gen_signature(def, gen);

quote! {
pub type #ident = #signature;
}
}

pub fn gen_win_handle(def: &TypeDef, gen: &Gen) -> TokenStream {
let name = def.name();
let ident = gen_ident(def.name());
let signature = gen_signature(def, gen);

let mut tokens = quote! {
#[repr(transparent)]
// Unfortunately, Rust requires these to be derived to allow constant patterns.
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq)]
pub struct #ident(pub #signature);
impl #ident {
pub fn is_invalid(&self) -> bool {
*self == unsafe { ::core::mem::zeroed() }
}

pub fn ok(self) -> ::windows::core::Result<Self> {
if !self.is_invalid() {
Ok(self)
} else {
Err(::windows::core::Error::from_win32())
}
}
}
impl ::core::default::Default for #ident {
fn default() -> Self {
unsafe { ::core::mem::zeroed() }
}
}
impl ::core::clone::Clone for #ident {
fn clone(&self) -> Self {
*self
}
}
impl ::core::marker::Copy for #ident {}
impl ::core::fmt::Debug for #ident {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
f.debug_tuple(#name).field(&self.0).finish()
}
}
unsafe impl ::windows::core::Abi for #ident {
type Abi = Self;
}
};

if let Some(dependency) = def.is_convertible_to() {
let type_name = dependency.type_name();
let mut dependency = gen.namespace(type_name.namespace());
dependency.push_str(type_name.name());

tokens.combine(&quote! {
impl<'a> ::windows::core::IntoParam<'a, #dependency> for #ident {
fn into_param(self) -> ::windows::core::Param<'a, #dependency> {
::windows::core::Param::Owned(#dependency(self.0))
}
}
});
}

tokens
}

fn gen_signature(def: &TypeDef, gen: &Gen) -> TokenStream {
if def.type_name() == TypeName::HANDLE {
quote! { *mut ::core::ffi::c_void }
} else {
let signature = def.fields().next().map(|field| field.signature(Some(def))).unwrap();
gen_sig(&signature, gen)
}
}
7 changes: 4 additions & 3 deletions crates/libs/bindgen/src/interfaces.rs
Expand Up @@ -181,11 +181,12 @@ fn gen_conversions(def: &TypeDef, cfg: &Cfg, gen: &Gen) -> TokenStream {
}

fn gen_agile(def: &TypeDef, gen: &Gen) -> TokenStream {
if def.type_name() == TypeName::IRestrictedErrorInfo {
if def.type_name() == TypeName::IRestrictedErrorInfo || def.async_kind() != AsyncKind::None {
let name = gen_type_ident(def, gen);
let constraints = gen_type_constraints(def, gen);
quote! {
unsafe impl ::core::marker::Send for #name {}
unsafe impl ::core::marker::Sync for #name {}
unsafe impl<#(#constraints)*> ::core::marker::Send for #name {}
unsafe impl<#(#constraints)*> ::core::marker::Sync for #name {}
}
} else {
TokenStream::new()
Expand Down
1 change: 1 addition & 0 deletions crates/libs/bindgen/src/lib.rs
Expand Up @@ -8,6 +8,7 @@ mod enums;
mod extensions;
mod functions;
mod gen;
mod handles;
mod helpers;
mod interfaces;
mod iterator;
Expand Down
23 changes: 7 additions & 16 deletions crates/libs/bindgen/src/structs.rs
Expand Up @@ -5,31 +5,22 @@ pub fn gen(def: &TypeDef, gen: &Gen) -> TokenStream {
return quote! {};
}

gen_struct_with_name(def, def.name(), &Cfg::new(), gen)
}

fn gen_struct_with_name(def: &TypeDef, struct_name: &str, cfg: &Cfg, gen: &Gen) -> TokenStream {
if !gen.sys {
if let Some(replacement) = replacements::gen(def) {
return replacement;
}
}

let name = gen_ident(struct_name);

if def.is_handle() {
let signature = if def.type_name() == TypeName::HANDLE {
quote! { *mut ::core::ffi::c_void }
} else {
let signature = def.fields().next().map(|field| field.signature(Some(def))).unwrap();
gen_sig(&signature, gen)
};

return quote! {
pub type #name = #signature;
};
return handles::gen(def, gen);
}

gen_struct_with_name(def, def.name(), &Cfg::new(), gen)
}

fn gen_struct_with_name(def: &TypeDef, struct_name: &str, cfg: &Cfg, gen: &Gen) -> TokenStream {
let name = gen_ident(struct_name);

if def.fields().next().is_none() {
if let Some(guid) = GUID::from_attributes(def.attributes()) {
let value = gen_guid(&guid, gen);
Expand Down
1 change: 1 addition & 0 deletions crates/libs/quote/src/token_stream.rs
Expand Up @@ -33,6 +33,7 @@ impl TokenStream {
self.0.push_str(&other.0)
}

#[must_use]
pub fn join(&self, value: &str) -> Self {
Self(format!("{}{}", self.0, value))
}
Expand Down
1 change: 1 addition & 0 deletions crates/libs/reader/src/constant_value.rs
Expand Up @@ -45,6 +45,7 @@ impl ConstantValue {
}
}

#[must_use]
pub fn next(&self) -> Self {
match self {
Self::U32(value) => Self::U32(value + 1),
Expand Down
3 changes: 2 additions & 1 deletion crates/libs/reader/src/element_type.rs
Expand Up @@ -232,6 +232,7 @@ impl ElementType {
}
}

#[must_use]
pub fn underlying_type(&self) -> ElementType {
match self {
Self::TypeDef(def) => def.underlying_type(),
Expand All @@ -243,7 +244,7 @@ impl ElementType {
pub fn has_replacement(&self) -> bool {
match self {
Self::HRESULT => true,
Self::TypeDef(def) => matches!(def.type_name(), TypeName::BOOL | TypeName::BSTR | TypeName::HANDLE | TypeName::NTSTATUS | TypeName::PSTR | TypeName::PWSTR),
Self::TypeDef(def) => def.is_handle(),
_ => false,
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/libs/reader/src/tables/type_def.rs
Expand Up @@ -14,6 +14,7 @@ impl From<Row> for TypeDef {
}

impl TypeDef {
#[must_use]
pub fn with_generics(mut self) -> Self {
self.generics = self.generic_params().map(|generic| ElementType::GenericParam(generic.name().to_string())).collect();
self
Expand Down
8 changes: 8 additions & 0 deletions crates/libs/windows/src/Windows/Foundation/mod.rs
Expand Up @@ -1119,6 +1119,8 @@ impl ::std::future::Future for IAsyncAction {
}
}
}
unsafe impl ::core::marker::Send for IAsyncAction {}
unsafe impl ::core::marker::Sync for IAsyncAction {}
unsafe impl ::windows::core::Interface for IAsyncAction {
type Vtable = IAsyncActionVtbl;
const IID: ::windows::core::GUID = ::windows::core::GUID::from_u128(0x5a648006_843a_4da9_865b_9d26e5dfad7b);
Expand Down Expand Up @@ -1320,6 +1322,8 @@ impl<TProgress: ::windows::core::RuntimeType + 'static> ::std::future::Future fo
}
}
}
unsafe impl<TProgress: ::windows::core::RuntimeType + 'static> ::core::marker::Send for IAsyncActionWithProgress<TProgress> {}
unsafe impl<TProgress: ::windows::core::RuntimeType + 'static> ::core::marker::Sync for IAsyncActionWithProgress<TProgress> {}
unsafe impl<TProgress: ::windows::core::RuntimeType + 'static> ::windows::core::Interface for IAsyncActionWithProgress<TProgress> {
type Vtable = IAsyncActionWithProgressVtbl<TProgress>;
const IID: ::windows::core::GUID = ::windows::core::GUID::from_signature(<Self as ::windows::core::RuntimeType>::SIGNATURE);
Expand Down Expand Up @@ -1633,6 +1637,8 @@ impl<TResult: ::windows::core::RuntimeType + 'static> ::std::future::Future for
}
}
}
unsafe impl<TResult: ::windows::core::RuntimeType + 'static> ::core::marker::Send for IAsyncOperation<TResult> {}
unsafe impl<TResult: ::windows::core::RuntimeType + 'static> ::core::marker::Sync for IAsyncOperation<TResult> {}
unsafe impl<TResult: ::windows::core::RuntimeType + 'static> ::windows::core::Interface for IAsyncOperation<TResult> {
type Vtable = IAsyncOperationVtbl<TResult>;
const IID: ::windows::core::GUID = ::windows::core::GUID::from_signature(<Self as ::windows::core::RuntimeType>::SIGNATURE);
Expand Down Expand Up @@ -1841,6 +1847,8 @@ impl<TResult: ::windows::core::RuntimeType + 'static, TProgress: ::windows::core
}
}
}
unsafe impl<TResult: ::windows::core::RuntimeType + 'static, TProgress: ::windows::core::RuntimeType + 'static> ::core::marker::Send for IAsyncOperationWithProgress<TResult, TProgress> {}
unsafe impl<TResult: ::windows::core::RuntimeType + 'static, TProgress: ::windows::core::RuntimeType + 'static> ::core::marker::Sync for IAsyncOperationWithProgress<TResult, TProgress> {}
unsafe impl<TResult: ::windows::core::RuntimeType + 'static, TProgress: ::windows::core::RuntimeType + 'static> ::windows::core::Interface for IAsyncOperationWithProgress<TResult, TProgress> {
type Vtable = IAsyncOperationWithProgressVtbl<TResult, TProgress>;
const IID: ::windows::core::GUID = ::windows::core::GUID::from_signature(<Self as ::windows::core::RuntimeType>::SIGNATURE);
Expand Down

0 comments on commit e8f2eac

Please sign in to comment.