diff options
Diffstat (limited to 'vendor/windows-bindgen/src')
40 files changed, 6441 insertions, 0 deletions
diff --git a/vendor/windows-bindgen/src/classes.rs b/vendor/windows-bindgen/src/classes.rs new file mode 100644 index 000000000..3cdf50006 --- /dev/null +++ b/vendor/windows-bindgen/src/classes.rs @@ -0,0 +1,215 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.sys { + if gen.reader.type_def_has_default_interface(def) { + let name = to_ident(gen.reader.type_def_name(def)); + quote! { + pub type #name = *mut ::core::ffi::c_void; + } + } else { + quote! {} + } + } else { + gen_class(gen, def) + } +} + +fn gen_class(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.reader.type_def_extends(def) == TypeName::Attribute { + return TokenStream::new(); + } + + let name = to_ident(gen.reader.type_def_name(def)); + let interfaces = gen + .reader + .type_interfaces(&Type::TypeDef((def, Vec::new()))); + let mut methods = quote! {}; + let mut method_names = MethodNames::new(); + + let cfg = gen.reader.type_def_cfg(def, &[]); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + + for interface in &interfaces { + if let Type::TypeDef((def, generics)) = &interface.ty { + let mut virtual_names = MethodNames::new(); + + for method in gen.reader.type_def_methods(*def) { + methods.combine(&winrt_methods::gen( + gen, + *def, + generics, + interface.kind, + method, + &mut method_names, + &mut virtual_names, + )); + } + } + } + + let factories = interfaces.iter().filter_map(|interface| match interface.kind { + InterfaceKind::Static => { + if let Type::TypeDef((def, generics)) = &interface.ty { + if gen.reader.type_def_methods(*def).next().is_some() { + let interface_type = gen.type_name(&interface.ty); + let features = gen.cfg_features(&gen.reader.type_def_cfg(*def, generics)); + + let hidden = if gen.doc { + quote! { #[doc(hidden)] } + } else { + quote! {} + }; + + return Some(quote! { + #hidden + #features + pub fn #interface_type<R, F: FnOnce(&#interface_type) -> ::windows::core::Result<R>>( + callback: F, + ) -> ::windows::core::Result<R> { + static SHARED: ::windows::imp::FactoryCache<#name, #interface_type> = + ::windows::imp::FactoryCache::new(); + SHARED.call(callback) + } + }); + } + } + None + } + _ => None, + }); + + if gen.reader.type_def_has_default_interface(def) { + let new = if gen.reader.type_def_has_default_constructor(def) { + quote! { + pub fn new() -> ::windows::core::Result<Self> { + Self::IActivationFactory(|f| f.ActivateInstance::<Self>()) + } + fn IActivationFactory<R, F: FnOnce(&::windows::imp::IGenericFactory) -> ::windows::core::Result<R>>( + callback: F, + ) -> ::windows::core::Result<R> { + static SHARED: ::windows::imp::FactoryCache<#name, ::windows::imp::IGenericFactory> = + ::windows::imp::FactoryCache::new(); + SHARED.call(callback) + } + } + } else { + quote! {} + }; + + let mut tokens = quote! { + #doc + #features + #[repr(transparent)] + pub struct #name(::windows::core::IUnknown); + #features + impl #name { + #new + #methods + #(#factories)* + } + }; + + tokens.combine(&gen.interface_core_traits( + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &features, + )); + tokens.combine(&gen.interface_winrt_trait( + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &features, + )); + tokens.combine(&gen.interface_trait(def, &[], &name, &TokenStream::new(), &features, true)); + tokens.combine(&gen.runtime_name_trait(def, &[], &name, &TokenStream::new(), &features)); + tokens.combine(&gen.async_get( + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &features, + )); + tokens.combine(&iterators::gen( + gen, + def, + &[], + &name, + &TokenStream::new(), + &TokenStream::new(), + &cfg, + )); + tokens.combine(&gen_conversions(gen, def, &name, &interfaces, &cfg)); + tokens.combine(&gen.agile(def, &name, &TokenStream::new(), &features)); + tokens + } else { + let mut tokens = quote! { + #doc + #features + pub struct #name; + #features + impl #name { + #methods + #(#factories)* + } + }; + + tokens.combine(&gen.runtime_name_trait(def, &[], &name, &TokenStream::new(), &features)); + tokens + } +} + +fn gen_conversions( + gen: &Gen, + def: TypeDef, + name: &TokenStream, + interfaces: &[Interface], + cfg: &Cfg, +) -> TokenStream { + let features = gen.cfg_features(cfg); + let mut tokens = quote! { + #features + ::windows::imp::interface_hierarchy!(#name, ::windows::core::IUnknown, ::windows::core::IInspectable); + }; + + for interface in interfaces { + if gen.reader.type_is_exclusive(&interface.ty) { + continue; + } + + if interface.kind != InterfaceKind::Default + && interface.kind != InterfaceKind::None + && interface.kind != InterfaceKind::Base + { + continue; + } + + let into = gen.type_name(&interface.ty); + // TODO: simplify - maybe provide + operator? + let features = gen.cfg_features(&cfg.union(&gen.reader.type_cfg(&interface.ty))); + + tokens.combine("e! { + #features + impl ::windows::core::CanTryInto<#into> for #name {} + }); + } + + for def in gen.reader.type_def_bases(def) { + let into = gen.type_def_name(def, &[]); + let features = gen.cfg_features(&cfg.union(&gen.reader.type_def_cfg(def, &[]))); + + tokens.combine("e! { + #features + impl ::windows::core::CanTryInto<#into> for #name {} + }); + } + + tokens +} diff --git a/vendor/windows-bindgen/src/com_methods.rs b/vendor/windows-bindgen/src/com_methods.rs new file mode 100644 index 000000000..cb59b9d64 --- /dev/null +++ b/vendor/windows-bindgen/src/com_methods.rs @@ -0,0 +1,238 @@ +use super::*; + +pub fn gen( + gen: &Gen, + def: TypeDef, + kind: InterfaceKind, + method: MethodDef, + method_names: &mut MethodNames, + virtual_names: &mut MethodNames, + base_count: usize, +) -> TokenStream { + let signature = gen.reader.method_def_signature(method, &[]); + let name = method_names.add(gen, method); + let vname = virtual_names.add(gen, method); + let generics = gen.constraint_generics(&signature.params); + let where_clause = gen.where_clause(&signature.params); + let mut cfg = gen.reader.signature_cfg(&signature); + cfg.add_feature(gen.reader.type_def_namespace(def)); + let doc = gen.cfg_method_doc(&cfg); + let features = gen.cfg_features(&cfg); + + if kind == InterfaceKind::None { + return quote! {}; + } + + let mut bases = quote! {}; + + for _ in 0..base_count { + bases.combine("e! { .base__ }); + } + + let kind = gen.reader.signature_kind(&signature); + match kind { + SignatureKind::Query(_) => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let generics = expand_generics(generics, quote!(T)); + let where_clause = + expand_where_clause(where_clause, quote!(T: ::windows::core::ComInterface)); + + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) -> ::windows::core::Result<T> #where_clause { + let mut result__ = ::std::ptr::null_mut(); + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args).from_abi(result__) + } + } + } + SignatureKind::QueryOptional(_) => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let generics = expand_generics(generics, quote!(T)); + let where_clause = + expand_where_clause(where_clause, quote!(T: ::windows::core::ComInterface)); + + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params result__: *mut ::core::option::Option<T>) -> ::windows::core::Result<()> #where_clause { + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args).ok() + } + } + } + SignatureKind::ResultValue => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let return_type = signature.params[signature.params.len() - 1].ty.deref(); + let return_type = gen.type_name(&return_type); + + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) -> ::windows::core::Result<#return_type> #where_clause { + let mut result__ = ::windows::core::zeroed::<#return_type>(); + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args).from_abi(result__) + } + } + } + SignatureKind::ResultVoid => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) -> ::windows::core::Result<()> #where_clause { + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args).ok() + } + } + } + SignatureKind::ReturnValue => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let return_type = signature.params[signature.params.len() - 1].ty.deref(); + let is_nullable = gen.reader.type_is_nullable(&return_type); + let return_type = gen.type_name(&return_type); + + if is_nullable { + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) -> ::windows::core::Result<#return_type> #where_clause { + let mut result__ = ::windows::core::zeroed::<#return_type>(); + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args); + ::windows::core::from_abi(result__) + } + } + } else { + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) -> #return_type #where_clause { + let mut result__ = ::windows::core::zeroed::<#return_type>(); + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args); + ::std::mem::transmute(result__) + } + } + } + } + SignatureKind::ReturnStruct => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let return_type = gen.type_name(&signature.return_type.unwrap()); + + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) -> #return_type #where_clause { + let mut result__: #return_type = ::core::mem::zeroed(); + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), &mut result__, #args); + result__ + } + } + } + SignatureKind::PreserveSig => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let return_type = gen.return_sig(&signature); + + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) #return_type #where_clause { + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args) + } + } + } + SignatureKind::ReturnVoid => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + + quote! { + #doc + #features + pub unsafe fn #name<#generics>(&self, #params) #where_clause { + (::windows::core::Interface::vtable(self)#bases.#vname)(::windows::core::Interface::as_raw(self), #args) + } + } + } + } +} + +pub fn gen_upcall(gen: &Gen, sig: &Signature, inner: TokenStream) -> TokenStream { + match gen.reader.signature_kind(sig) { + SignatureKind::ResultValue => { + let invoke_args = sig.params[..sig.params.len() - 1] + .iter() + .map(|param| gen_win32_invoke_arg(gen, param)); + + let result = gen.param_name(sig.params[sig.params.len() - 1].def); + + quote! { + match #inner(#(#invoke_args,)*) { + ::core::result::Result::Ok(ok__) => { + // use `core::ptr::write` since the result could be uninitialized + ::core::ptr::write(#result, ::core::mem::transmute(ok__)); + ::windows::core::HRESULT(0) + } + ::core::result::Result::Err(err) => err.into() + } + } + } + SignatureKind::Query(_) | SignatureKind::QueryOptional(_) | SignatureKind::ResultVoid => { + let invoke_args = sig + .params + .iter() + .map(|param| gen_win32_invoke_arg(gen, param)); + + quote! { + #inner(#(#invoke_args,)*).into() + } + } + SignatureKind::ReturnStruct => { + let invoke_args = sig + .params + .iter() + .map(|param| gen_win32_invoke_arg(gen, param)); + + quote! { + *result__ = #inner(#(#invoke_args,)*) + } + } + _ => { + let invoke_args = sig + .params + .iter() + .map(|param| gen_win32_invoke_arg(gen, param)); + + quote! { + #inner(#(#invoke_args,)*) + } + } + } +} + +fn gen_win32_invoke_arg(gen: &Gen, param: &SignatureParam) -> TokenStream { + let name = gen.param_name(param.def); + + if gen + .reader + .param_flags(param.def) + .contains(ParamAttributes::INPUT) + && gen.reader.type_is_nullable(¶m.ty) + { + quote! { ::windows::core::from_raw_borrowed(&#name) } + } else if (!param.ty.is_pointer() && gen.reader.type_is_nullable(¶m.ty)) + || (gen + .reader + .param_flags(param.def) + .contains(ParamAttributes::INPUT) + && !gen.reader.type_is_primitive(¶m.ty)) + { + quote! { ::core::mem::transmute(&#name) } + } else { + quote! { ::core::mem::transmute_copy(&#name) } + } +} diff --git a/vendor/windows-bindgen/src/constants.rs b/vendor/windows-bindgen/src/constants.rs new file mode 100644 index 000000000..1a08db0ae --- /dev/null +++ b/vendor/windows-bindgen/src/constants.rs @@ -0,0 +1,188 @@ +use super::*; + +pub fn gen(gen: &Gen, def: Field) -> TokenStream { + let name = to_ident(gen.reader.field_name(def)); + let ty = gen.reader.field_type(def, None).to_const_type(); + let cfg = gen.reader.field_cfg(def); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + + if let Some(constant) = gen.reader.field_constant(def) { + let constant_type = gen.reader.constant_type(constant); + + if ty == constant_type { + if ty == Type::String { + let crate_name = gen.crate_name(); + if gen.reader.field_is_ansi(def) { + let value = gen.value(&gen.reader.constant_value(constant)); + quote! { + #doc + #features + pub const #name: #crate_name PCSTR = #crate_name s!(#value); + } + } else { + let value = gen.value(&gen.reader.constant_value(constant)); + quote! { + #doc + #features + pub const #name: #crate_name PCWSTR = #crate_name w!(#value); + } + } + } else { + let value = gen.typed_value(&gen.reader.constant_value(constant)); + quote! { + #doc + #features + pub const #name: #value; + } + } + } else { + let kind = gen.type_default_name(&ty); + let value = gen.value(&gen.reader.constant_value(constant)); + let underlying_type = gen.reader.type_underlying_type(&ty); + + let value = if underlying_type == constant_type { + value + } else if gen.std && underlying_type == Type::ISize { + quote! { ::core::ptr::invalid_mut(#value as _) } + } else { + quote! { #value as _ } + }; + + if !gen.sys && gen.reader.type_has_replacement(&ty) { + quote! { + #doc + #features + pub const #name: #kind = #kind(#value); + } + } else { + quote! { + #doc + #features + pub const #name: #kind = #value; + } + } + } + } else if let Some(guid) = gen.reader.field_guid(def) { + let value = gen.guid(&guid); + let guid = gen.type_name(&Type::GUID); + quote! { + #doc + pub const #name: #guid = #value; + } + } else if let Some(value) = initializer(gen, def) { + let kind = gen.type_default_name(&ty); + + quote! { + #doc + #features + pub const #name: #kind = #kind { #value }; + } + } else { + quote! {} + } +} + +fn initializer(gen: &Gen, def: Field) -> Option<TokenStream> { + let Some(value) = constant(gen, def) else { + return None; + }; + + let mut input = value.as_str(); + + let Type::TypeDef((def, _)) = gen.reader.field_type(def, None) else { + unimplemented!(); + }; + + let mut result = quote! {}; + + for field in gen.reader.type_def_fields(def) { + let (value, rest) = field_initializer(gen, field, input); + input = rest; + result.combine(&value); + } + + Some(result) +} + +fn field_initializer<'a>(gen: &Gen, field: Field, input: &'a str) -> (TokenStream, &'a str) { + let name = to_ident(gen.reader.field_name(field)); + + match gen.reader.field_type(field, None) { + Type::GUID => { + let (literals, rest) = read_literal_array(input, 11); + let value = gen.guid(&GUID::from_string_args(&literals)); + (quote! { #name: #value, }, rest) + } + Type::Win32Array((_, len)) => { + let (literals, rest) = read_literal_array(input, len); + let literals = literals.iter().map(|literal| TokenStream::from(*literal)); + (quote! { #name: [#(#literals,)*], }, rest) + } + _ => { + let (literal, rest) = read_literal(input); + let literal: TokenStream = literal.into(); + (quote! { #name: #literal, }, rest) + } + } +} + +fn constant(gen: &Gen, def: Field) -> Option<String> { + gen.reader + .field_attributes(def) + .find(|attribute| gen.reader.attribute_name(*attribute) == "ConstantAttribute") + .map(|attribute| { + let args = gen.reader.attribute_args(attribute); + match &args[0].1 { + Value::String(value) => value.clone(), + _ => unimplemented!(), + } + }) +} + +fn read_literal(input: &str) -> (&str, &str) { + let mut start = None; + let mut end = 0; + + for (pos, c) in input.bytes().enumerate() { + if start.is_none() { + if c != b' ' && c != b',' { + start = Some(pos); + } + } else if c == b' ' || c == b',' || c == b'}' { + break; + } + end += 1; + } + + let Some(start) = start else { + unimplemented!(); + }; + + (&input[start..end], &input[end..]) +} + +fn read_token(input: &str, token: u8) -> &str { + for (pos, c) in input.bytes().enumerate() { + if c == token { + return &input[pos + 1..]; + } else if c != b' ' && c != b',' { + break; + } + } + + panic!("`{}` expected", token.escape_ascii()); +} + +fn read_literal_array(input: &str, len: usize) -> (Vec<&str>, &str) { + let mut input = read_token(input, b'{'); + let mut result = vec![]; + + for _ in 0..len { + let (literal, rest) = read_literal(input); + result.push(literal); + input = rest; + } + + (result, read_token(input, b'}')) +} diff --git a/vendor/windows-bindgen/src/delegates.rs b/vendor/windows-bindgen/src/delegates.rs new file mode 100644 index 000000000..a68719c81 --- /dev/null +++ b/vendor/windows-bindgen/src/delegates.rs @@ -0,0 +1,181 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + gen_delegate(gen, def) + } else { + gen_callback(gen, def) + } +} + +fn gen_callback(gen: &Gen, def: TypeDef) -> TokenStream { + let name = to_ident(gen.reader.type_def_name(def)); + + let method = gen.reader.type_def_invoke_method(def); + let signature = gen.reader.method_def_signature(method, &[]); + let return_type = gen.return_sig(&signature); + let cfg = gen.reader.type_def_cfg(def, &[]); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + + let params = signature.params.iter().map(|p| { + let name = gen.param_name(p.def); + let tokens = gen.type_default_name(&p.ty); + quote! { #name: #tokens } + }); + + quote! { + #doc + #features + pub type #name = ::core::option::Option<unsafe extern "system" fn(#(#params),*) #return_type>; + } +} + +fn gen_delegate(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.sys { + let name = to_ident(gen.reader.type_def_name(def)); + quote! { + pub type #name = *mut ::core::ffi::c_void; + } + } else { + gen_win_delegate(gen, def) + } +} + +fn gen_win_delegate(gen: &Gen, def: TypeDef) -> TokenStream { + let name = to_ident(gen.reader.type_def_name(def)); + let vtbl = name.join("_Vtbl"); + let boxed = name.join("Box"); + + let generics: &Vec<Type> = &gen.reader.type_def_generics(def).collect(); + let phantoms = gen.generic_phantoms(generics); + let named_phantoms = gen.generic_named_phantoms(generics); + let constraints = gen.generic_constraints(generics); + let generic_names = gen.generic_names(generics); + + let ident = gen.type_def_name(def, generics); + + let method = gen.reader.type_def_invoke_method(def); + let signature = gen.reader.method_def_signature(method, generics); + let fn_constraint = gen_fn_constraint(gen, def, &signature); + + let cfg = gen.reader.type_def_cfg(def, generics); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + + let vtbl_signature = gen.vtbl_signature(def, generics, &signature); + let invoke = winrt_methods::gen( + gen, + def, + generics, + InterfaceKind::Default, + method, + &mut MethodNames::new(), + &mut MethodNames::new(), + ); + let invoke_upcall = winrt_methods::gen_upcall(gen, &signature, quote! { ((*this).invoke) }); + + let mut tokens = quote! { + #doc + #features + #[repr(transparent)] + pub struct #ident(pub ::windows::core::IUnknown, #phantoms) where #constraints; + #features + impl<#constraints> #ident { + pub fn new<#fn_constraint>(invoke: F) -> Self { + let com = #boxed::<#generic_names F> { + vtable: &#boxed::<#generic_names F>::VTABLE, + count: ::windows::imp::RefCount::new(1), + invoke, + }; + unsafe { + ::core::mem::transmute(::std::boxed::Box::new(com)) + } + } + #invoke + } + #features + #[repr(C)] + struct #boxed<#generic_names #fn_constraint> where #constraints { + vtable: *const #vtbl<#generic_names>, + invoke: F, + count: ::windows::imp::RefCount, + } + #features + impl<#constraints #fn_constraint> #boxed<#generic_names F> { + const VTABLE: #vtbl<#generic_names> = #vtbl::<#generic_names>{ + base__: ::windows::core::IUnknown_Vtbl{QueryInterface: Self::QueryInterface, AddRef: Self::AddRef, Release: Self::Release}, + Invoke: Self::Invoke, + #(#named_phantoms)* + }; + unsafe extern "system" fn QueryInterface(this: *mut ::core::ffi::c_void, iid: &::windows::core::GUID, interface: *mut *const ::core::ffi::c_void) -> ::windows::core::HRESULT { + let this = this as *mut *mut ::core::ffi::c_void as *mut Self; + + *interface = if iid == &<#ident as ::windows::core::ComInterface>::IID || + iid == &<::windows::core::IUnknown as ::windows::core::ComInterface>::IID || + iid == &<::windows::imp::IAgileObject as ::windows::core::ComInterface>::IID { + &mut (*this).vtable as *mut _ as _ + } else { + ::core::ptr::null_mut() + }; + + // TODO: implement IMarshal + + if (*interface).is_null() { + ::windows::core::HRESULT(-2147467262) // E_NOINTERFACE + } else { + (*this).count.add_ref(); + ::windows::core::HRESULT(0) + } + } + unsafe extern "system" fn AddRef(this: *mut ::core::ffi::c_void) -> u32 { + let this = this as *mut *mut ::core::ffi::c_void as *mut Self; + (*this).count.add_ref() + } + unsafe extern "system" fn Release(this: *mut ::core::ffi::c_void) -> u32 { + let this = this as *mut *mut ::core::ffi::c_void as *mut Self; + let remaining = (*this).count.release(); + + if remaining == 0 { + let _ = ::std::boxed::Box::from_raw(this); + } + + remaining + } + unsafe extern "system" fn Invoke #vtbl_signature { + let this = this as *mut *mut ::core::ffi::c_void as *mut Self; + #invoke_upcall + } + } + }; + + tokens.combine(&gen.interface_core_traits( + def, + generics, + &ident, + &constraints, + &phantoms, + &features, + )); + tokens.combine(&gen.interface_trait(def, generics, &ident, &constraints, &features, true)); + tokens.combine(&gen.interface_winrt_trait( + def, + generics, + &ident, + &constraints, + &phantoms, + &features, + )); + tokens.combine(&gen.interface_vtbl(def, generics, &ident, &constraints, &features)); + tokens +} + +fn gen_fn_constraint(gen: &Gen, def: TypeDef, signature: &Signature) -> TokenStream { + let signature = gen.impl_signature(def, signature); + + quote! { F: FnMut #signature + ::core::marker::Send + 'static } +} diff --git a/vendor/windows-bindgen/src/enums.rs b/vendor/windows-bindgen/src/enums.rs new file mode 100644 index 000000000..ee7616fda --- /dev/null +++ b/vendor/windows-bindgen/src/enums.rs @@ -0,0 +1,203 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + let type_name = gen.reader.type_def_type_name(def); + let ident = to_ident(type_name.name); + let underlying_type = gen.reader.type_def_underlying_type(def); + let underlying_type = gen.type_name(&underlying_type); + let is_scoped = gen.reader.type_def_is_scoped(def); + let cfg = gen.reader.type_def_cfg(def, &[]); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + + let fields: Vec<(TokenStream, TokenStream)> = gen + .reader + .type_def_fields(def) + .filter_map(|field| { + if gen + .reader + .field_flags(field) + .contains(FieldAttributes::LITERAL) + { + let field_name = to_ident(gen.reader.field_name(field)); + let constant = gen.reader.field_constant(field).unwrap(); + let value = gen.value(&gen.reader.constant_value(constant)); + + Some((field_name, value)) + } else { + None + } + }) + .collect(); + + let eq = if gen.sys { + quote! {} + } else { + quote! { + // Unfortunately, Rust requires these to be derived to allow constant patterns. + #[derive(::core::cmp::PartialEq, ::core::cmp::Eq)] + } + }; + + let mut tokens = if is_scoped || !gen.sys { + quote! { + #doc + #features + #[repr(transparent)] + #eq + pub struct #ident(pub #underlying_type); + } + } else { + quote! { + #doc + #features + pub type #ident = #underlying_type; + } + }; + + tokens.combine(&if is_scoped { + let fields = fields.iter().map(|(field_name, value)| { + quote! { + pub const #field_name: Self = Self(#value); + } + }); + + quote! { + #features + impl #ident { + #(#fields)* + } + } + } else if !gen.sys { + let fields = fields.iter().map(|(field_name, value)| { + quote! { + #doc + #features + pub const #field_name: #ident = #ident(#value); + } + }); + + quote! { + #(#fields)* + } + } else if !gen.standalone { + let fields = fields.iter().map(|(field_name, value)| { + quote! { + #doc + #features + pub const #field_name: #ident = #value; + } + }); + + quote! { + #(#fields)* + } + } else { + quote! {} + }); + + if is_scoped || !gen.sys { + tokens.combine("e! { + #features + impl ::core::marker::Copy for #ident {} + #features + impl ::core::clone::Clone for #ident { + fn clone(&self) -> Self { + *self + } + } + }); + } + + if !gen.sys { + tokens.combine("e! { + #features + impl ::core::default::Default for #ident { + fn default() -> Self { + Self(0) + } + } + }); + } + + if !gen.sys { + let name = type_name.name; + tokens.combine("e! { + #features + impl ::windows::core::TypeKind for #ident { + type TypeKind = ::windows::core::CopyType; + } + #features + 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() + } + } + }); + + if gen.reader.type_def_is_flags(def) { + tokens.combine("e! { + #features + impl #ident { + pub const fn contains(&self, other: Self) -> bool { + self.0 & other.0 == other.0 + } + } + #features + impl ::core::ops::BitOr for #ident { + type Output = Self; + + fn bitor(self, other: Self) -> Self { + Self(self.0 | other.0) + } + } + #features + impl ::core::ops::BitAnd for #ident { + type Output = Self; + + fn bitand(self, other: Self) -> Self { + Self(self.0 & other.0) + } + } + #features + impl ::core::ops::BitOrAssign for #ident { + fn bitor_assign(&mut self, other: Self) { + self.0.bitor_assign(other.0) + } + } + #features + impl ::core::ops::BitAndAssign for #ident { + fn bitand_assign(&mut self, other: Self) { + self.0.bitand_assign(other.0) + } + } + #features + impl ::core::ops::Not for #ident { + type Output = Self; + + fn not(self) -> Self { + Self(self.0.not()) + } + } + }); + } + + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + let signature = + Literal::byte_string(gen.reader.type_def_signature(def, &[]).as_bytes()); + + tokens.combine("e! { + #features + impl ::windows::core::RuntimeType for #ident { + const SIGNATURE: ::windows::imp::ConstBuffer = ::windows::imp::ConstBuffer::from_slice(#signature); + } + }); + } + } + + tokens +} diff --git a/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/Iterable.rs b/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/Iterable.rs new file mode 100644 index 000000000..7d379fdf6 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/Iterable.rs @@ -0,0 +1,96 @@ +#[::windows::core::implement(IIterable<T>)] +struct StockIterable<T> +where + T: ::windows::core::RuntimeType + 'static, + <T as ::windows::core::Type<T>>::Default: ::std::clone::Clone, +{ + values: std::vec::Vec<T::Default>, +} + +impl<T> IIterable_Impl<T> for StockIterable<T> +where + T: ::windows::core::RuntimeType, + <T as ::windows::core::Type<T>>::Default: ::std::clone::Clone, +{ + fn First(&self) -> ::windows::core::Result<IIterator<T>> { + unsafe { + // TODO: ideally we can do an AddRef rather than a QI here (via cast)... + // and then we can get rid of the unsafe as well. + Ok(StockIterator { + owner: self.cast()?, + current: 0.into(), + } + .into()) + } + } +} + +#[::windows::core::implement(IIterator<T>)] +struct StockIterator<T> +where + T: ::windows::core::RuntimeType + 'static, + <T as ::windows::core::Type<T>>::Default: ::std::clone::Clone, +{ + owner: IIterable<T>, + current: ::std::sync::atomic::AtomicUsize, +} + +impl<T> IIterator_Impl<T> for StockIterator<T> +where + T: ::windows::core::RuntimeType, + <T as ::windows::core::Type<T>>::Default: ::std::clone::Clone, +{ + fn Current(&self) -> ::windows::core::Result<T> { + let owner: &StockIterable<T> = ::windows::core::AsImpl::as_impl(&self.owner); + let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); + + if owner.values.len() > current { + T::from_default(&owner.values[current]) + } else { + Err(::windows::imp::E_BOUNDS.into()) + } + } + + fn HasCurrent(&self) -> ::windows::core::Result<bool> { + let owner: &StockIterable<T> = ::windows::core::AsImpl::as_impl(&self.owner); + let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); + + Ok(owner.values.len() > current) + } + + fn MoveNext(&self) -> ::windows::core::Result<bool> { + let owner: &StockIterable<T> = ::windows::core::AsImpl::as_impl(&self.owner); + let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); + + if current < owner.values.len() { + self.current + .fetch_add(1, ::std::sync::atomic::Ordering::Relaxed); + } + + Ok(owner.values.len() > current + 1) + } + + fn GetMany(&self, values: &mut [T::Default]) -> ::windows::core::Result<u32> { + let owner: &StockIterable<T> = ::windows::core::AsImpl::as_impl(&self.owner); + let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); + + let actual = std::cmp::min(owner.values.len() - current, values.len()); + let (values, _) = values.split_at_mut(actual); + values.clone_from_slice(&owner.values[current..current + actual]); + self.current + .fetch_add(actual, ::std::sync::atomic::Ordering::Relaxed); + Ok(actual as _) + } +} + +impl<T> ::core::convert::TryFrom<::std::vec::Vec<T::Default>> for IIterable<T> +where + T: ::windows::core::RuntimeType, + <T as ::windows::core::Type<T>>::Default: ::std::clone::Clone, +{ + type Error = ::windows::core::Error; + fn try_from(values: ::std::vec::Vec<T::Default>) -> ::windows::core::Result<Self> { + // TODO: should provide a fallible try_into or more explicit allocator + Ok(StockIterable { values }.into()) + } +} diff --git a/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/MapView.rs b/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/MapView.rs new file mode 100644 index 000000000..e8980e4d2 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/MapView.rs @@ -0,0 +1,174 @@ +#[windows::core::implement(IMapView<K, V>, IIterable<IKeyValuePair<K, V>>)] +struct StockMapView<K, V> +where + K: windows::core::RuntimeType + 'static, + V: windows::core::RuntimeType + 'static, + <K as windows::core::Type<K>>::Default: std::clone::Clone + std::cmp::Ord, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + map: std::collections::BTreeMap<K::Default, V::Default>, +} + +impl<K, V> IIterable_Impl<IKeyValuePair<K, V>> for StockMapView<K, V> +where + K: windows::core::RuntimeType, + V: windows::core::RuntimeType, + <K as windows::core::Type<K>>::Default: std::clone::Clone + std::cmp::Ord, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + fn First(&self) -> windows::core::Result<IIterator<IKeyValuePair<K, V>>> { + unsafe { + // TODO: ideally we can do an AddRef rather than a QI here (via cast)... + // and then we can get rid of the unsafe as well. + Ok(StockMapViewIterator::<K, V> { + _owner: self.cast()?, + current: std::sync::RwLock::new(self.map.iter()), + } + .into()) + } + } +} + +impl<K, V> IMapView_Impl<K, V> for StockMapView<K, V> +where + K: windows::core::RuntimeType, + V: windows::core::RuntimeType, + <K as windows::core::Type<K>>::Default: std::clone::Clone + std::cmp::Ord, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + fn Lookup(&self, key: &K::Default) -> windows::core::Result<V> { + let value = self + .map + .get(key) + .ok_or_else(|| windows::core::Error::from(windows::imp::E_BOUNDS))?; + V::from_default(value) + } + fn Size(&self) -> windows::core::Result<u32> { + Ok(self.map.len() as _) + } + fn HasKey(&self, key: &K::Default) -> windows::core::Result<bool> { + Ok(self.map.contains_key(key)) + } + fn Split( + &self, + first: &mut std::option::Option<IMapView<K, V>>, + second: &mut std::option::Option<IMapView<K, V>>, + ) -> windows::core::Result<()> { + *first = None; + *second = None; + Ok(()) + } +} + +#[::windows::core::implement(IIterator<IKeyValuePair<K, V>>)] +struct StockMapViewIterator<'a, K, V> +where + K: windows::core::RuntimeType + 'static, + V: windows::core::RuntimeType + 'static, + <K as windows::core::Type<K>>::Default: std::clone::Clone + std::cmp::Ord, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + _owner: IIterable<IKeyValuePair<K, V>>, + current: ::std::sync::RwLock<std::collections::btree_map::Iter<'a, K::Default, V::Default>>, +} + +impl<'a, K, V> IIterator_Impl<IKeyValuePair<K, V>> for StockMapViewIterator<'a, K, V> +where + K: windows::core::RuntimeType, + V: windows::core::RuntimeType, + <K as windows::core::Type<K>>::Default: std::clone::Clone + std::cmp::Ord, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + fn Current(&self) -> ::windows::core::Result<IKeyValuePair<K, V>> { + let mut current = self.current.read().unwrap().clone().peekable(); + + if let Some((key, value)) = current.peek() { + Ok(StockKeyValuePair { + key: (*key).clone(), + value: (*value).clone(), + } + .into()) + } else { + Err(windows::core::Error::from(windows::imp::E_BOUNDS)) + } + } + + fn HasCurrent(&self) -> ::windows::core::Result<bool> { + let mut current = self.current.read().unwrap().clone().peekable(); + + Ok(current.peek().is_some()) + } + + fn MoveNext(&self) -> ::windows::core::Result<bool> { + let mut current = self.current.write().unwrap(); + + current.next(); + Ok(current.clone().peekable().peek().is_some()) + } + + fn GetMany(&self, pairs: &mut [Option<IKeyValuePair<K, V>>]) -> ::windows::core::Result<u32> { + let mut current = self.current.write().unwrap(); + let mut actual = 0; + + for pair in pairs { + if let Some((key, value)) = current.next() { + *pair = Some( + StockKeyValuePair { + key: (*key).clone(), + value: (*value).clone(), + } + .into(), + ); + actual += 1; + } else { + break; + } + } + + Ok(actual as _) + } +} + +#[windows::core::implement(IKeyValuePair<K, V>)] +struct StockKeyValuePair<K, V> +where + K: windows::core::RuntimeType + 'static, + V: windows::core::RuntimeType + 'static, + <K as windows::core::Type<K>>::Default: std::clone::Clone, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + key: K::Default, + value: V::Default, +} + +impl<K, V> IKeyValuePair_Impl<K, V> for StockKeyValuePair<K, V> +where + K: windows::core::RuntimeType, + V: windows::core::RuntimeType, + <K as windows::core::Type<K>>::Default: std::clone::Clone, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + fn Key(&self) -> windows::core::Result<K> { + K::from_default(&self.key) + } + fn Value(&self) -> windows::core::Result<V> { + V::from_default(&self.value) + } +} + +impl<K, V> ::core::convert::TryFrom<std::collections::BTreeMap<K::Default, V::Default>> + for IMapView<K, V> +where + K: windows::core::RuntimeType, + V: windows::core::RuntimeType, + <K as windows::core::Type<K>>::Default: std::clone::Clone + std::cmp::Ord, + <V as windows::core::Type<V>>::Default: std::clone::Clone, +{ + type Error = ::windows::core::Error; + fn try_from( + map: std::collections::BTreeMap<K::Default, V::Default>, + ) -> windows::core::Result<Self> { + // TODO: should provide a fallible try_into or more explicit allocator + Ok(StockMapView { map }.into()) + } +} diff --git a/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/VectorView.rs b/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/VectorView.rs new file mode 100644 index 000000000..c51dc0c8c --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/impl/Foundation/Collections/VectorView.rs @@ -0,0 +1,132 @@ +#[windows::core::implement(IVectorView<T>, IIterable<T>)] +struct StockVectorView<T> +where + T: windows::core::RuntimeType + 'static, + <T as windows::core::Type<T>>::Default: std::clone::Clone + std::cmp::PartialEq, +{ + values: std::vec::Vec<T::Default>, +} + +impl<T> IIterable_Impl<T> for StockVectorView<T> +where + T: windows::core::RuntimeType, + <T as windows::core::Type<T>>::Default: std::clone::Clone + std::cmp::PartialEq, +{ + fn First(&self) -> windows::core::Result<IIterator<T>> { + unsafe { + // TODO: ideally we can do an AddRef rather than a QI here (via cast)... + // and then we can get rid of the unsafe as well. + Ok(StockVectorViewIterator { + owner: self.cast()?, + current: 0.into(), + } + .into()) + } + } +} + +impl<T> IVectorView_Impl<T> for StockVectorView<T> +where + T: windows::core::RuntimeType, + <T as windows::core::Type<T>>::Default: std::clone::Clone + std::cmp::PartialEq, +{ + fn GetAt(&self, index: u32) -> windows::core::Result<T> { + let item = self + .values + .get(index as usize) + .ok_or_else(|| windows::core::Error::from(windows::imp::E_BOUNDS))?; + T::from_default(item) + } + fn Size(&self) -> windows::core::Result<u32> { + Ok(self.values.len() as _) + } + fn IndexOf(&self, value: &T::Default, result: &mut u32) -> windows::core::Result<bool> { + match self.values.iter().position(|element| element == value) { + Some(index) => { + *result = index as _; + Ok(true) + } + None => Ok(false), + } + } + fn GetMany(&self, current: u32, values: &mut [T::Default]) -> windows::core::Result<u32> { + let current = current as usize; + if current >= self.values.len() { + return Ok(0); + } + let actual = std::cmp::min(self.values.len() - current, values.len()); + let (values, _) = values.split_at_mut(actual); + values.clone_from_slice(&self.values[current..current + actual]); + Ok(actual as _) + } +} + +#[::windows::core::implement(IIterator<T>)] +struct StockVectorViewIterator<T> +where + T: ::windows::core::RuntimeType + 'static, + <T as ::windows::core::Type<T>>::Default: std::clone::Clone + std::cmp::PartialEq, +{ + owner: IIterable<T>, + current: ::std::sync::atomic::AtomicUsize, +} + +impl<T> IIterator_Impl<T> for StockVectorViewIterator<T> +where + T: ::windows::core::RuntimeType, + <T as ::windows::core::Type<T>>::Default: std::clone::Clone + std::cmp::PartialEq, +{ + fn Current(&self) -> ::windows::core::Result<T> { + let owner: &StockVectorView<T> = ::windows::core::AsImpl::as_impl(&self.owner); + let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); + + if owner.values.len() > current { + T::from_default(&owner.values[current]) + } else { + Err(windows::core::Error::from(windows::imp::E_BOUNDS)) + } + } + + fn HasCurrent(&self) -> ::windows::core::Result<bool> { + let owner: &StockVectorView<T> = ::windows::core::AsImpl::as_impl(&self.owner); + let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); + + Ok(owner.values.len() > current) + } + + fn MoveNext(&self) -> ::windows::core::Result<bool> { + let owner: &StockVectorView<T> = ::windows::core::AsImpl::as_impl(&self.owner); + let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); + + if current < owner.values.len() { + self.current + .fetch_add(1, ::std::sync::atomic::Ordering::Relaxed); + } + + Ok(owner.values.len() > current + 1) + } + + fn GetMany(&self, values: &mut [T::Default]) -> ::windows::core::Result<u32> { + let owner: &StockVectorView<T> = ::windows::core::AsImpl::as_impl(&self.owner); + let current = self.current.load(::std::sync::atomic::Ordering::Relaxed); + + let actual = std::cmp::min(owner.values.len() - current, values.len()); + let (values, _) = values.split_at_mut(actual); + values.clone_from_slice(&owner.values[current..current + actual]); + self.current + .fetch_add(actual, ::std::sync::atomic::Ordering::Relaxed); + Ok(actual as _) + } +} + +impl<T> ::core::convert::TryFrom<::std::vec::Vec<T::Default>> for IVectorView<T> +where + T: ::windows::core::RuntimeType, + <T as ::windows::core::Type<T>>::Default: std::clone::Clone + std::cmp::PartialEq, +{ + type Error = ::windows::core::Error; + fn try_from(values: ::std::vec::Vec<T::Default>) -> ::windows::core::Result<Self> { + // TODO: should provide a fallible try_into or more explicit allocator + Ok(StockVectorView { values }.into()) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod.rs b/vendor/windows-bindgen/src/extensions/mod.rs new file mode 100644 index 000000000..9b0b6942e --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod.rs @@ -0,0 +1,57 @@ +use super::*; + +pub fn gen_mod(gen: &Gen, namespace: &str) -> TokenStream { + if namespace == "Windows.Win32.UI.WindowsAndMessaging" { + return include_str!("mod/Win32/UI/WindowsAndMessaging/WindowLong.rs").into(); + } + + if gen.sys { + return "".into(); + } + + match namespace { + "Windows.Foundation.Numerics" => concat!( + include_str!("mod/Foundation/Numerics/Matrix3x2.rs"), + include_str!("mod/Foundation/Numerics/Matrix4x4.rs"), + include_str!("mod/Foundation/Numerics/Vector2.rs"), + include_str!("mod/Foundation/Numerics/Vector3.rs"), + include_str!("mod/Foundation/Numerics/Vector4.rs"), + ), + "Windows.Foundation" => concat!( + include_str!("mod/Foundation/IInspectable.rs"), + include_str!("mod/Foundation/PropertyValue.rs"), + include_str!("mod/Foundation/TimeSpan.rs"), + ), + "Windows.Win32.Foundation" => concat!( + include_str!("mod/Win32/Foundation/BOOL.rs"), + include_str!("mod/Win32/Foundation/BOOLEAN.rs"), + include_str!("mod/Win32/Foundation/NTSTATUS.rs"), + include_str!("mod/Win32/Foundation/VARIANT_BOOL.rs"), + include_str!("mod/Win32/Foundation/WIN32_ERROR.rs"), + ), + "Windows.Win32.Networking.WinSock" => concat!( + include_str!("mod/Win32/Networking/WinSock/IN_ADDR.rs"), + include_str!("mod/Win32/Networking/WinSock/IN6_ADDR.rs"), + include_str!("mod/Win32/Networking/WinSock/SOCKADDR_IN.rs"), + include_str!("mod/Win32/Networking/WinSock/SOCKADDR_IN6.rs"), + include_str!("mod/Win32/Networking/WinSock/SOCKADDR_INET.rs"), + ), + "Windows.Win32.UI.WindowsAndMessaging" => { + include_str!("mod/Win32/UI/WindowsAndMessaging/WindowLong.rs") + } + _ => "", + } + .into() +} + +pub fn gen_impl(namespace: &str) -> TokenStream { + match namespace { + "Windows.Foundation.Collections" => concat!( + include_str!("impl/Foundation/Collections/Iterable.rs"), + include_str!("impl/Foundation/Collections/MapView.rs"), + include_str!("impl/Foundation/Collections/VectorView.rs"), + ), + _ => "", + } + .into() +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/IInspectable.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/IInspectable.rs new file mode 100644 index 000000000..c8ddabdbb --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/IInspectable.rs @@ -0,0 +1,13 @@ +impl std::fmt::Debug for windows::core::IInspectable { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // Attempts to retrieve the string representation of the object via the + // IStringable interface. If that fails, it will use the canonical type + // name to give some idea of what the object represents. + let name = + <windows::core::IInspectable as windows::core::ComInterface>::cast::<IStringable>(self) + .and_then(|s| s.ToString()) + .or_else(|_| self.GetRuntimeClassName()) + .unwrap_or_default(); + write!(f, "\"{}\"", name) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Matrix3x2.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Matrix3x2.rs new file mode 100644 index 000000000..98be80636 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Matrix3x2.rs @@ -0,0 +1,139 @@ +impl Matrix3x2 { + pub const fn identity() -> Self { + Self { M11: 1.0, M12: 0.0, M21: 0.0, M22: 1.0, M31: 0.0, M32: 0.0 } + } + pub const fn translation(x: f32, y: f32) -> Self { + Self { M11: 1.0, M12: 0.0, M21: 0.0, M22: 1.0, M31: x, M32: y } + } + pub fn rotation(angle: f32, x: f32, y: f32) -> Self { + #[repr(C)] + pub struct D2D_POINT_2F { + pub x: f32, + pub y: f32, + } + ::windows_targets::link!("d2d1.dll" "system" fn D2D1MakeRotateMatrix(angle: f32, center: D2D_POINT_2F, matrix: *mut Matrix3x2) -> ()); + let mut matrix = Self::default(); + unsafe { + D2D1MakeRotateMatrix(angle, D2D_POINT_2F { x, y }, &mut matrix); + } + matrix + } + fn impl_add(&self, rhs: &Self) -> Self { + Self { + M11: self.M11 + rhs.M11, + M12: self.M12 + rhs.M12, + M21: self.M21 + rhs.M21, + M22: self.M22 + rhs.M22, + M31: self.M31 + rhs.M31, + M32: self.M32 + rhs.M32, + } + } + fn impl_sub(&self, rhs: &Self) -> Self { + Self { + M11: self.M11 - rhs.M11, + M12: self.M12 - rhs.M12, + M21: self.M21 - rhs.M21, + M22: self.M22 - rhs.M22, + M31: self.M31 - rhs.M31, + M32: self.M32 - rhs.M32, + } + } + fn impl_mul(&self, rhs: &Self) -> Self { + Self { + M11: self.M11 * rhs.M11 + self.M12 * rhs.M21, + M12: self.M11 * rhs.M12 + self.M12 * rhs.M22, + M21: self.M21 * rhs.M11 + self.M22 * rhs.M21, + M22: self.M21 * rhs.M12 + self.M22 * rhs.M22, + M31: self.M31 * rhs.M11 + self.M32 * rhs.M21 + rhs.M31, + M32: self.M31 * rhs.M12 + self.M32 * rhs.M22 + rhs.M32, + } + } + fn impl_mul_f32(&self, rhs: f32) -> Self { + Self { M11: self.M11 * rhs, M12: self.M12 * rhs, M21: self.M21 * rhs, M22: self.M22 * rhs, M31: self.M31 * rhs, M32: self.M32 * rhs } + } +} + +impl ::core::ops::Add<Matrix3x2> for Matrix3x2 { + type Output = Matrix3x2; + fn add(self, rhs: Matrix3x2) -> Matrix3x2 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Matrix3x2> for Matrix3x2 { + type Output = Matrix3x2; + fn add(self, rhs: &Matrix3x2) -> Matrix3x2 { + self.impl_add(rhs) + } +} +impl ::core::ops::Add<Matrix3x2> for &Matrix3x2 { + type Output = Matrix3x2; + fn add(self, rhs: Matrix3x2) -> Matrix3x2 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Matrix3x2> for &Matrix3x2 { + type Output = Matrix3x2; + fn add(self, rhs: &Matrix3x2) -> Matrix3x2 { + self.impl_add(rhs) + } +} +impl ::core::ops::Sub<Matrix3x2> for Matrix3x2 { + type Output = Matrix3x2; + fn sub(self, rhs: Matrix3x2) -> Matrix3x2 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Matrix3x2> for Matrix3x2 { + type Output = Matrix3x2; + fn sub(self, rhs: &Matrix3x2) -> Matrix3x2 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Sub<Matrix3x2> for &Matrix3x2 { + type Output = Matrix3x2; + fn sub(self, rhs: Matrix3x2) -> Matrix3x2 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Matrix3x2> for &Matrix3x2 { + type Output = Matrix3x2; + fn sub(self, rhs: &Matrix3x2) -> Matrix3x2 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Mul<Matrix3x2> for Matrix3x2 { + type Output = Matrix3x2; + fn mul(self, rhs: Matrix3x2) -> Matrix3x2 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Matrix3x2> for Matrix3x2 { + type Output = Matrix3x2; + fn mul(self, rhs: &Matrix3x2) -> Matrix3x2 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<Matrix3x2> for &Matrix3x2 { + type Output = Matrix3x2; + fn mul(self, rhs: Matrix3x2) -> Matrix3x2 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Matrix3x2> for &Matrix3x2 { + type Output = Matrix3x2; + fn mul(self, rhs: &Matrix3x2) -> Matrix3x2 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<f32> for Matrix3x2 { + type Output = Matrix3x2; + fn mul(self, rhs: f32) -> Matrix3x2 { + self.impl_mul_f32(rhs) + } +} +impl ::core::ops::Mul<f32> for &Matrix3x2 { + type Output = Matrix3x2; + fn mul(self, rhs: f32) -> Matrix3x2 { + self.impl_mul_f32(rhs) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Matrix4x4.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Matrix4x4.rs new file mode 100644 index 000000000..fb5d60866 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Matrix4x4.rs @@ -0,0 +1,235 @@ +impl Matrix4x4 { + pub const fn translation(x: f32, y: f32, z: f32) -> Self { + Self { + M11: 1.0, + M12: 0.0, + M13: 0.0, + M14: 0.0, + M21: 0.0, + M22: 1.0, + M23: 0.0, + M24: 0.0, + M31: 0.0, + M32: 0.0, + M33: 1.0, + M34: 0.0, + M41: x, + M42: y, + M43: z, + M44: 1.0, + } + } + pub fn rotation_y(degree: f32) -> Self { + ::windows_targets::link!("d2d1.dll" "system" fn D2D1SinCos(angle: f32, sin: *mut f32, cos: *mut f32) -> ()); + let angle = degree * (3.141592654 / 180.0); + let mut sin = 0.0; + let mut cos = 0.0; + unsafe { + D2D1SinCos(angle, &mut sin, &mut cos); + } + Self { + M11: cos, + M12: 0.0, + M13: -sin, + M14: 0.0, + M21: 0.0, + M22: 1.0, + M23: 0.0, + M24: 0.0, + M31: sin, + M32: 0.0, + M33: cos, + M34: 0.0, + M41: 0.0, + M42: 0.0, + M43: 0.0, + M44: 1.0, + } + } + pub fn perspective_projection(depth: f32) -> Self { + let projection = if depth > 0.0 { -1.0 / depth } else { 0.0 }; + Self { + M11: 1.0, + M12: 0.0, + M13: 0.0, + M14: 0.0, + M21: 0.0, + M22: 1.0, + M23: 0.0, + M24: 0.0, + M31: 0.0, + M32: 0.0, + M33: 1.0, + M34: projection, + M41: 0.0, + M42: 0.0, + M43: 0.0, + M44: 1.0, + } + } + fn impl_add(&self, rhs: &Self) -> Self { + Self { + M11: self.M11 + rhs.M11, + M12: self.M12 + rhs.M12, + M13: self.M13 + rhs.M13, + M14: self.M14 + rhs.M14, + M21: self.M21 + rhs.M21, + M22: self.M22 + rhs.M22, + M23: self.M23 + rhs.M23, + M24: self.M24 + rhs.M24, + M31: self.M31 + rhs.M31, + M32: self.M32 + rhs.M32, + M33: self.M33 + rhs.M33, + M34: self.M34 + rhs.M34, + M41: self.M41 + rhs.M41, + M42: self.M42 + rhs.M42, + M43: self.M43 + rhs.M43, + M44: self.M44 + rhs.M44, + } + } + fn impl_sub(&self, rhs: &Self) -> Self { + Self { + M11: self.M11 - rhs.M11, + M12: self.M12 - rhs.M12, + M13: self.M13 - rhs.M13, + M14: self.M14 - rhs.M14, + M21: self.M21 - rhs.M21, + M22: self.M22 - rhs.M22, + M23: self.M23 - rhs.M23, + M24: self.M24 - rhs.M24, + M31: self.M31 - rhs.M31, + M32: self.M32 - rhs.M32, + M33: self.M33 - rhs.M33, + M34: self.M34 - rhs.M34, + M41: self.M41 - rhs.M41, + M42: self.M42 - rhs.M42, + M43: self.M43 - rhs.M43, + M44: self.M44 - rhs.M44, + } + } + fn impl_mul(&self, rhs: &Self) -> Self { + Self { + M11: self.M11 * rhs.M11 + self.M12 * rhs.M21 + self.M13 * rhs.M31 + self.M14 * rhs.M41, + M12: self.M11 * rhs.M12 + self.M12 * rhs.M22 + self.M13 * rhs.M32 + self.M14 * rhs.M42, + M13: self.M11 * rhs.M13 + self.M12 * rhs.M23 + self.M13 * rhs.M33 + self.M14 * rhs.M43, + M14: self.M11 * rhs.M14 + self.M12 * rhs.M24 + self.M13 * rhs.M34 + self.M14 * rhs.M44, + M21: self.M21 * rhs.M11 + self.M22 * rhs.M21 + self.M23 * rhs.M31 + self.M24 * rhs.M41, + M22: self.M21 * rhs.M12 + self.M22 * rhs.M22 + self.M23 * rhs.M32 + self.M24 * rhs.M42, + M23: self.M21 * rhs.M13 + self.M22 * rhs.M23 + self.M23 * rhs.M33 + self.M24 * rhs.M43, + M24: self.M21 * rhs.M14 + self.M22 * rhs.M24 + self.M23 * rhs.M34 + self.M24 * rhs.M44, + M31: self.M31 * rhs.M11 + self.M32 * rhs.M21 + self.M33 * rhs.M31 + self.M34 * rhs.M41, + M32: self.M31 * rhs.M12 + self.M32 * rhs.M22 + self.M33 * rhs.M32 + self.M34 * rhs.M42, + M33: self.M31 * rhs.M13 + self.M32 * rhs.M23 + self.M33 * rhs.M33 + self.M34 * rhs.M43, + M34: self.M31 * rhs.M14 + self.M32 * rhs.M24 + self.M33 * rhs.M34 + self.M34 * rhs.M44, + M41: self.M41 * rhs.M11 + self.M42 * rhs.M21 + self.M43 * rhs.M31 + self.M44 * rhs.M41, + M42: self.M41 * rhs.M12 + self.M42 * rhs.M22 + self.M43 * rhs.M32 + self.M44 * rhs.M42, + M43: self.M41 * rhs.M13 + self.M42 * rhs.M23 + self.M43 * rhs.M33 + self.M44 * rhs.M43, + M44: self.M41 * rhs.M14 + self.M42 * rhs.M24 + self.M43 * rhs.M34 + self.M44 * rhs.M44, + } + } + fn impl_mul_f32(&self, rhs: f32) -> Self { + Self { + M11: self.M11 * rhs, + M12: self.M12 * rhs, + M13: self.M13 * rhs, + M14: self.M14 * rhs, + M21: self.M21 * rhs, + M22: self.M22 * rhs, + M23: self.M23 * rhs, + M24: self.M24 * rhs, + M31: self.M31 * rhs, + M32: self.M32 * rhs, + M33: self.M33 * rhs, + M34: self.M34 * rhs, + M41: self.M41 * rhs, + M42: self.M42 * rhs, + M43: self.M43 * rhs, + M44: self.M44 * rhs, + } + } +} + +impl ::core::ops::Add<Matrix4x4> for Matrix4x4 { + type Output = Matrix4x4; + fn add(self, rhs: Matrix4x4) -> Matrix4x4 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Matrix4x4> for Matrix4x4 { + type Output = Matrix4x4; + fn add(self, rhs: &Matrix4x4) -> Matrix4x4 { + self.impl_add(rhs) + } +} +impl ::core::ops::Add<Matrix4x4> for &Matrix4x4 { + type Output = Matrix4x4; + fn add(self, rhs: Matrix4x4) -> Matrix4x4 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Matrix4x4> for &Matrix4x4 { + type Output = Matrix4x4; + fn add(self, rhs: &Matrix4x4) -> Matrix4x4 { + self.impl_add(rhs) + } +} +impl ::core::ops::Sub<Matrix4x4> for Matrix4x4 { + type Output = Matrix4x4; + fn sub(self, rhs: Matrix4x4) -> Matrix4x4 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Matrix4x4> for Matrix4x4 { + type Output = Matrix4x4; + fn sub(self, rhs: &Matrix4x4) -> Matrix4x4 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Sub<Matrix4x4> for &Matrix4x4 { + type Output = Matrix4x4; + fn sub(self, rhs: Matrix4x4) -> Matrix4x4 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Matrix4x4> for &Matrix4x4 { + type Output = Matrix4x4; + fn sub(self, rhs: &Matrix4x4) -> Matrix4x4 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Mul<Matrix4x4> for Matrix4x4 { + type Output = Matrix4x4; + fn mul(self, rhs: Matrix4x4) -> Matrix4x4 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Matrix4x4> for Matrix4x4 { + type Output = Matrix4x4; + fn mul(self, rhs: &Matrix4x4) -> Matrix4x4 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<Matrix4x4> for &Matrix4x4 { + type Output = Matrix4x4; + fn mul(self, rhs: Matrix4x4) -> Matrix4x4 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Matrix4x4> for &Matrix4x4 { + type Output = Matrix4x4; + fn mul(self, rhs: &Matrix4x4) -> Matrix4x4 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<f32> for Matrix4x4 { + type Output = Matrix4x4; + fn mul(self, rhs: f32) -> Matrix4x4 { + self.impl_mul_f32(rhs) + } +} +impl ::core::ops::Mul<f32> for &Matrix4x4 { + type Output = Matrix4x4; + fn mul(self, rhs: f32) -> Matrix4x4 { + self.impl_mul_f32(rhs) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector2.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector2.rs new file mode 100644 index 000000000..f37b4620b --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector2.rs @@ -0,0 +1,175 @@ +impl Vector2 { + pub fn new(X: f32, Y: f32) -> Self { + Self { X, Y } + } + pub fn zero() -> Self { + Self { X: 0f32, Y: 0f32 } + } + pub fn one() -> Self { + Self { X: 1f32, Y: 1f32 } + } + pub fn unit_x() -> Self { + Self { X: 1.0, Y: 0.0 } + } + pub fn unit_y() -> Self { + Self { X: 0.0, Y: 1.0 } + } + pub fn dot(&self, rhs: &Self) -> f32 { + self.X * rhs.X + self.Y * rhs.Y + } + pub fn length_squared(&self) -> f32 { + self.dot(self) + } + pub fn length(&self) -> f32 { + self.length_squared().sqrt() + } + pub fn distance(&self, value: &Self) -> f32 { + (self - value).length() + } + pub fn distance_squared(&self, value: &Self) -> f32 { + (self - value).length_squared() + } + pub fn normalize(&self) -> Self { + self / self.length() + } + + fn impl_add(&self, rhs: &Self) -> Self { + Self { X: self.X + rhs.X, Y: self.Y + rhs.Y } + } + fn impl_sub(&self, rhs: &Self) -> Self { + Self { X: self.X - rhs.X, Y: self.Y - rhs.Y } + } + fn impl_div(&self, rhs: &Self) -> Self { + Self { X: self.X / rhs.X, Y: self.Y / rhs.Y } + } + fn impl_div_f32(&self, rhs: f32) -> Self { + Self { X: self.X / rhs, Y: self.Y / rhs } + } + fn impl_mul(&self, rhs: &Self) -> Self { + Self { X: self.X * rhs.X, Y: self.Y * rhs.Y } + } + fn impl_mul_f32(&self, rhs: f32) -> Self { + Self { X: self.X * rhs, Y: self.Y * rhs } + } +} + +impl ::core::ops::Add<Vector2> for Vector2 { + type Output = Vector2; + fn add(self, rhs: Vector2) -> Vector2 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Vector2> for Vector2 { + type Output = Vector2; + fn add(self, rhs: &Vector2) -> Vector2 { + self.impl_add(rhs) + } +} +impl ::core::ops::Add<Vector2> for &Vector2 { + type Output = Vector2; + fn add(self, rhs: Vector2) -> Vector2 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Vector2> for &Vector2 { + type Output = Vector2; + fn add(self, rhs: &Vector2) -> Vector2 { + self.impl_add(rhs) + } +} +impl ::core::ops::Sub<Vector2> for Vector2 { + type Output = Vector2; + fn sub(self, rhs: Vector2) -> Vector2 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Vector2> for Vector2 { + type Output = Vector2; + fn sub(self, rhs: &Vector2) -> Vector2 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Sub<Vector2> for &Vector2 { + type Output = Vector2; + fn sub(self, rhs: Vector2) -> Vector2 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Vector2> for &Vector2 { + type Output = Vector2; + fn sub(self, rhs: &Vector2) -> Vector2 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Div<Vector2> for Vector2 { + type Output = Vector2; + fn div(self, rhs: Vector2) -> Vector2 { + self.impl_div(&rhs) + } +} +impl ::core::ops::Div<&Vector2> for Vector2 { + type Output = Vector2; + fn div(self, rhs: &Vector2) -> Vector2 { + self.impl_div(rhs) + } +} +impl ::core::ops::Div<Vector2> for &Vector2 { + type Output = Vector2; + fn div(self, rhs: Vector2) -> Vector2 { + self.impl_div(&rhs) + } +} +impl ::core::ops::Div<&Vector2> for &Vector2 { + type Output = Vector2; + fn div(self, rhs: &Vector2) -> Vector2 { + self.impl_div(rhs) + } +} +impl ::core::ops::Div<f32> for Vector2 { + type Output = Vector2; + fn div(self, rhs: f32) -> Vector2 { + self.impl_div_f32(rhs) + } +} +impl ::core::ops::Div<f32> for &Vector2 { + type Output = Vector2; + fn div(self, rhs: f32) -> Vector2 { + self.impl_div_f32(rhs) + } +} +impl ::core::ops::Mul<Vector2> for Vector2 { + type Output = Vector2; + fn mul(self, rhs: Vector2) -> Vector2 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Vector2> for Vector2 { + type Output = Vector2; + fn mul(self, rhs: &Vector2) -> Vector2 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<Vector2> for &Vector2 { + type Output = Vector2; + fn mul(self, rhs: Vector2) -> Vector2 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Vector2> for &Vector2 { + type Output = Vector2; + fn mul(self, rhs: &Vector2) -> Vector2 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<f32> for Vector2 { + type Output = Vector2; + fn mul(self, rhs: f32) -> Vector2 { + self.impl_mul_f32(rhs) + } +} +impl ::core::ops::Mul<f32> for &Vector2 { + type Output = Vector2; + fn mul(self, rhs: f32) -> Vector2 { + self.impl_mul_f32(rhs) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector3.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector3.rs new file mode 100644 index 000000000..58dcf9653 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector3.rs @@ -0,0 +1,178 @@ +impl Vector3 { + pub fn new(X: f32, Y: f32, Z: f32) -> Self { + Self { X, Y, Z } + } + pub fn zero() -> Self { + Self { X: 0f32, Y: 0f32, Z: 0f32 } + } + pub fn one() -> Self { + Self { X: 1f32, Y: 1f32, Z: 1f32 } + } + pub fn unit_x() -> Self { + Self { X: 1.0, Y: 0.0, Z: 0.0 } + } + pub fn unit_y() -> Self { + Self { X: 0.0, Y: 1.0, Z: 0.0 } + } + pub fn unit_z() -> Self { + Self { X: 0.0, Y: 0.0, Z: 1.0 } + } + pub fn dot(&self, rhs: &Self) -> f32 { + self.X * rhs.X + self.Y * rhs.Y + self.Z * rhs.Z + } + pub fn length_squared(&self) -> f32 { + self.dot(self) + } + pub fn length(&self) -> f32 { + self.length_squared().sqrt() + } + pub fn distance(&self, value: &Self) -> f32 { + (self - value).length() + } + pub fn distance_squared(&self, value: &Self) -> f32 { + (self - value).length_squared() + } + pub fn normalize(&self) -> Self { + self / self.length() + } + + fn impl_add(&self, rhs: &Self) -> Self { + Self { X: self.X + rhs.X, Y: self.Y + rhs.Y, Z: self.Z + rhs.Z } + } + fn impl_sub(&self, rhs: &Self) -> Self { + Self { X: self.X - rhs.X, Y: self.Y - rhs.Y, Z: self.Z - rhs.Z } + } + fn impl_div(&self, rhs: &Self) -> Self { + Self { X: self.X / rhs.X, Y: self.Y / rhs.Y, Z: self.Z / rhs.Z } + } + fn impl_div_f32(&self, rhs: f32) -> Self { + Self { X: self.X / rhs, Y: self.Y / rhs, Z: self.Z / rhs } + } + fn impl_mul(&self, rhs: &Self) -> Self { + Self { X: self.X * rhs.X, Y: self.Y * rhs.Y, Z: self.Z * rhs.Z } + } + fn impl_mul_f32(&self, rhs: f32) -> Self { + Self { X: self.X * rhs, Y: self.Y * rhs, Z: self.Z * rhs } + } +} + +impl ::core::ops::Add<Vector3> for Vector3 { + type Output = Vector3; + fn add(self, rhs: Vector3) -> Vector3 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Vector3> for Vector3 { + type Output = Vector3; + fn add(self, rhs: &Vector3) -> Vector3 { + self.impl_add(rhs) + } +} +impl ::core::ops::Add<Vector3> for &Vector3 { + type Output = Vector3; + fn add(self, rhs: Vector3) -> Vector3 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Vector3> for &Vector3 { + type Output = Vector3; + fn add(self, rhs: &Vector3) -> Vector3 { + self.impl_add(rhs) + } +} +impl ::core::ops::Sub<Vector3> for Vector3 { + type Output = Vector3; + fn sub(self, rhs: Vector3) -> Vector3 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Vector3> for Vector3 { + type Output = Vector3; + fn sub(self, rhs: &Vector3) -> Vector3 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Sub<Vector3> for &Vector3 { + type Output = Vector3; + fn sub(self, rhs: Vector3) -> Vector3 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Vector3> for &Vector3 { + type Output = Vector3; + fn sub(self, rhs: &Vector3) -> Vector3 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Div<Vector3> for Vector3 { + type Output = Vector3; + fn div(self, rhs: Vector3) -> Vector3 { + self.impl_div(&rhs) + } +} +impl ::core::ops::Div<&Vector3> for Vector3 { + type Output = Vector3; + fn div(self, rhs: &Vector3) -> Vector3 { + self.impl_div(rhs) + } +} +impl ::core::ops::Div<Vector3> for &Vector3 { + type Output = Vector3; + fn div(self, rhs: Vector3) -> Vector3 { + self.impl_div(&rhs) + } +} +impl ::core::ops::Div<&Vector3> for &Vector3 { + type Output = Vector3; + fn div(self, rhs: &Vector3) -> Vector3 { + self.impl_div(rhs) + } +} +impl ::core::ops::Div<f32> for Vector3 { + type Output = Vector3; + fn div(self, rhs: f32) -> Vector3 { + self.impl_div_f32(rhs) + } +} +impl ::core::ops::Div<f32> for &Vector3 { + type Output = Vector3; + fn div(self, rhs: f32) -> Vector3 { + self.impl_div_f32(rhs) + } +} +impl ::core::ops::Mul<Vector3> for Vector3 { + type Output = Vector3; + fn mul(self, rhs: Vector3) -> Vector3 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Vector3> for Vector3 { + type Output = Vector3; + fn mul(self, rhs: &Vector3) -> Vector3 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<Vector3> for &Vector3 { + type Output = Vector3; + fn mul(self, rhs: Vector3) -> Vector3 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Vector3> for &Vector3 { + type Output = Vector3; + fn mul(self, rhs: &Vector3) -> Vector3 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<f32> for Vector3 { + type Output = Vector3; + fn mul(self, rhs: f32) -> Vector3 { + self.impl_mul_f32(rhs) + } +} +impl ::core::ops::Mul<f32> for &Vector3 { + type Output = Vector3; + fn mul(self, rhs: f32) -> Vector3 { + self.impl_mul_f32(rhs) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector4.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector4.rs new file mode 100644 index 000000000..69609d906 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/Numerics/Vector4.rs @@ -0,0 +1,181 @@ +impl Vector4 { + pub fn new(X: f32, Y: f32, Z: f32, W: f32) -> Self { + Self { X, Y, Z, W } + } + pub fn zero() -> Self { + Self { X: 0f32, Y: 0f32, Z: 0f32, W: 0f32 } + } + pub fn one() -> Self { + Self { X: 1f32, Y: 1f32, Z: 1f32, W: 1f32 } + } + pub fn unit_x() -> Self { + Self { X: 1.0, Y: 0.0, Z: 0.0, W: 0.0 } + } + pub fn unit_y() -> Self { + Self { X: 0.0, Y: 1.0, Z: 0.0, W: 0.0 } + } + pub fn unit_z() -> Self { + Self { X: 0.0, Y: 0.0, Z: 1.0, W: 0.0 } + } + pub fn unit_w() -> Self { + Self { X: 0.0, Y: 0.0, Z: 0.0, W: 1.0 } + } + pub fn dot(&self, rhs: &Self) -> f32 { + self.X * rhs.X + self.Y * rhs.Y + self.Z * rhs.Z + self.W * rhs.W + } + pub fn length_squared(&self) -> f32 { + self.dot(self) + } + pub fn length(&self) -> f32 { + self.length_squared().sqrt() + } + pub fn distance(&self, value: &Self) -> f32 { + (self - value).length() + } + pub fn distance_squared(&self, value: &Self) -> f32 { + (self - value).length_squared() + } + pub fn normalize(&self) -> Self { + self / self.length() + } + + fn impl_add(&self, rhs: &Self) -> Self { + Self { X: self.X + rhs.X, Y: self.Y + rhs.Y, Z: self.Z + rhs.Z, W: self.W + rhs.W } + } + fn impl_sub(&self, rhs: &Self) -> Self { + Self { X: self.X - rhs.X, Y: self.Y - rhs.Y, Z: self.Z - rhs.Z, W: self.W - rhs.W } + } + fn impl_div(&self, rhs: &Self) -> Self { + Self { X: self.X / rhs.X, Y: self.Y / rhs.Y, Z: self.Z / rhs.Z, W: self.W / rhs.W } + } + fn impl_div_f32(&self, rhs: f32) -> Self { + Self { X: self.X / rhs, Y: self.Y / rhs, Z: self.Z / rhs, W: self.W / rhs } + } + fn impl_mul(&self, rhs: &Self) -> Self { + Self { X: self.X * rhs.X, Y: self.Y * rhs.Y, Z: self.Z * rhs.Z, W: self.W * rhs.W } + } + fn impl_mul_f32(&self, rhs: f32) -> Self { + Self { X: self.X * rhs, Y: self.Y * rhs, Z: self.Z * rhs, W: self.W * rhs } + } +} + +impl ::core::ops::Add<Vector4> for Vector4 { + type Output = Vector4; + fn add(self, rhs: Vector4) -> Vector4 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Vector4> for Vector4 { + type Output = Vector4; + fn add(self, rhs: &Vector4) -> Vector4 { + self.impl_add(rhs) + } +} +impl ::core::ops::Add<Vector4> for &Vector4 { + type Output = Vector4; + fn add(self, rhs: Vector4) -> Vector4 { + self.impl_add(&rhs) + } +} +impl ::core::ops::Add<&Vector4> for &Vector4 { + type Output = Vector4; + fn add(self, rhs: &Vector4) -> Vector4 { + self.impl_add(rhs) + } +} +impl ::core::ops::Sub<Vector4> for Vector4 { + type Output = Vector4; + fn sub(self, rhs: Vector4) -> Vector4 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Vector4> for Vector4 { + type Output = Vector4; + fn sub(self, rhs: &Vector4) -> Vector4 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Sub<Vector4> for &Vector4 { + type Output = Vector4; + fn sub(self, rhs: Vector4) -> Vector4 { + self.impl_sub(&rhs) + } +} +impl ::core::ops::Sub<&Vector4> for &Vector4 { + type Output = Vector4; + fn sub(self, rhs: &Vector4) -> Vector4 { + self.impl_sub(rhs) + } +} +impl ::core::ops::Div<Vector4> for Vector4 { + type Output = Vector4; + fn div(self, rhs: Vector4) -> Vector4 { + self.impl_div(&rhs) + } +} +impl ::core::ops::Div<&Vector4> for Vector4 { + type Output = Vector4; + fn div(self, rhs: &Vector4) -> Vector4 { + self.impl_div(rhs) + } +} +impl ::core::ops::Div<Vector4> for &Vector4 { + type Output = Vector4; + fn div(self, rhs: Vector4) -> Vector4 { + self.impl_div(&rhs) + } +} +impl ::core::ops::Div<&Vector4> for &Vector4 { + type Output = Vector4; + fn div(self, rhs: &Vector4) -> Vector4 { + self.impl_div(rhs) + } +} +impl ::core::ops::Div<f32> for Vector4 { + type Output = Vector4; + fn div(self, rhs: f32) -> Vector4 { + self.impl_div_f32(rhs) + } +} +impl ::core::ops::Div<f32> for &Vector4 { + type Output = Vector4; + fn div(self, rhs: f32) -> Vector4 { + self.impl_div_f32(rhs) + } +} +impl ::core::ops::Mul<Vector4> for Vector4 { + type Output = Vector4; + fn mul(self, rhs: Vector4) -> Vector4 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Vector4> for Vector4 { + type Output = Vector4; + fn mul(self, rhs: &Vector4) -> Vector4 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<Vector4> for &Vector4 { + type Output = Vector4; + fn mul(self, rhs: Vector4) -> Vector4 { + self.impl_mul(&rhs) + } +} +impl ::core::ops::Mul<&Vector4> for &Vector4 { + type Output = Vector4; + fn mul(self, rhs: &Vector4) -> Vector4 { + self.impl_mul(rhs) + } +} +impl ::core::ops::Mul<f32> for Vector4 { + type Output = Vector4; + fn mul(self, rhs: f32) -> Vector4 { + self.impl_mul_f32(rhs) + } +} +impl ::core::ops::Mul<f32> for &Vector4 { + type Output = Vector4; + fn mul(self, rhs: f32) -> Vector4 { + self.impl_mul_f32(rhs) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/PropertyValue.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/PropertyValue.rs new file mode 100644 index 000000000..d9a1f113e --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/PropertyValue.rs @@ -0,0 +1,71 @@ +macro_rules! primitive_boxed_type { + ($(($t:ty, $m:ident)),+) => { + $(impl std::convert::TryFrom<$t> for windows::core::IInspectable { + type Error = windows::core::Error; + fn try_from(value: $t) -> windows::core::Result<Self> { + PropertyValue::$m(value) + } + } + impl std::convert::TryFrom<windows::core::IInspectable> for $t { + type Error = windows::core::Error; + fn try_from(value: windows::core::IInspectable) -> windows::core::Result<Self> { + <windows::core::IInspectable as windows::core::ComInterface>::cast::<IReference<$t>>(&value)?.Value() + } + } + impl std::convert::TryFrom<&windows::core::IInspectable> for $t { + type Error = windows::core::Error; + fn try_from(value: &windows::core::IInspectable) -> windows::core::Result<Self> { + <windows::core::IInspectable as windows::core::ComInterface>::cast::<IReference<$t>>(value)?.Value() + } + })* + }; +} +primitive_boxed_type! { + (bool, CreateBoolean), + (u8, CreateUInt8), + (i16, CreateInt16), + (u16, CreateUInt16), + (i32, CreateInt32), + (u32, CreateUInt32), + (i64, CreateInt64), + (u64, CreateUInt64), + (f32, CreateSingle), + (f64, CreateDouble) +} +impl std::convert::TryFrom<&str> for windows::core::IInspectable { + type Error = windows::core::Error; + fn try_from(value: &str) -> windows::core::Result<Self> { + let value: windows::core::HSTRING = value.into(); + PropertyValue::CreateString(&value) + } +} +impl std::convert::TryFrom<windows::core::HSTRING> for windows::core::IInspectable { + type Error = windows::core::Error; + fn try_from(value: windows::core::HSTRING) -> windows::core::Result<Self> { + PropertyValue::CreateString(&value) + } +} +impl std::convert::TryFrom<&windows::core::HSTRING> for windows::core::IInspectable { + type Error = windows::core::Error; + fn try_from(value: &windows::core::HSTRING) -> windows::core::Result<Self> { + PropertyValue::CreateString(value) + } +} +impl std::convert::TryFrom<windows::core::IInspectable> for windows::core::HSTRING { + type Error = windows::core::Error; + fn try_from(value: windows::core::IInspectable) -> windows::core::Result<Self> { + <windows::core::IInspectable as windows::core::ComInterface>::cast::< + IReference<windows::core::HSTRING>, + >(&value)? + .Value() + } +} +impl std::convert::TryFrom<&windows::core::IInspectable> for windows::core::HSTRING { + type Error = windows::core::Error; + fn try_from(value: &windows::core::IInspectable) -> windows::core::Result<Self> { + <windows::core::IInspectable as windows::core::ComInterface>::cast::< + IReference<windows::core::HSTRING>, + >(value)? + .Value() + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Foundation/TimeSpan.rs b/vendor/windows-bindgen/src/extensions/mod/Foundation/TimeSpan.rs new file mode 100644 index 000000000..814b3d45b --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Foundation/TimeSpan.rs @@ -0,0 +1,10 @@ +impl ::core::convert::From<::core::time::Duration> for TimeSpan { + fn from(value: ::core::time::Duration) -> Self { + Self { Duration: (value.as_nanos() / 100) as i64 } + } +} +impl ::core::convert::From<TimeSpan> for ::core::time::Duration { + fn from(value: TimeSpan) -> Self { + ::core::time::Duration::from_nanos((value.Duration * 100) as u64) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/BOOL.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/BOOL.rs new file mode 100644 index 000000000..f09ae9111 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/BOOL.rs @@ -0,0 +1,73 @@ +impl BOOL { + #[inline] + pub fn as_bool(self) -> bool { + self.0 != 0 + } + #[inline] + pub fn ok(self) -> ::windows::core::Result<()> { + if self.as_bool() { + Ok(()) + } else { + Err(::windows::core::Error::from_win32()) + } + } + #[inline] + #[track_caller] + pub fn unwrap(self) { + self.ok().unwrap(); + } + #[inline] + #[track_caller] + pub fn expect(self, msg: &str) { + self.ok().expect(msg); + } +} +impl ::core::convert::From<BOOL> for bool { + fn from(value: BOOL) -> Self { + value.as_bool() + } +} +impl ::core::convert::From<&BOOL> for bool { + fn from(value: &BOOL) -> Self { + value.as_bool() + } +} +impl ::core::convert::From<bool> for BOOL { + fn from(value: bool) -> Self { + if value { + Self(1) + } else { + Self(0) + } + } +} +impl ::core::convert::From<&bool> for BOOL { + fn from(value: &bool) -> Self { + (*value).into() + } +} +impl ::core::cmp::PartialEq<bool> for BOOL { + fn eq(&self, other: &bool) -> bool { + self.as_bool() == *other + } +} +impl ::core::cmp::PartialEq<BOOL> for bool { + fn eq(&self, other: &BOOL) -> bool { + *self == other.as_bool() + } +} +impl ::core::ops::Not for BOOL { + type Output = Self; + fn not(self) -> Self::Output { + if self.as_bool() { + Self(0) + } else { + Self(1) + } + } +} +impl windows::core::IntoParam<BOOL> for bool { + fn into_param(self) -> windows::core::Param<BOOL> { + windows::core::Param::Owned(self.into()) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/BOOLEAN.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/BOOLEAN.rs new file mode 100644 index 000000000..44afc65c2 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/BOOLEAN.rs @@ -0,0 +1,68 @@ +impl BOOLEAN { + #[inline] + pub fn as_bool(self) -> bool { + self.0 != 0 + } + #[inline] + pub fn ok(self) -> ::windows::core::Result<()> { + if self.as_bool() { + Ok(()) + } else { + Err(::windows::core::Error::from_win32()) + } + } + #[inline] + #[track_caller] + pub fn unwrap(self) { + self.ok().unwrap(); + } + #[inline] + #[track_caller] + pub fn expect(self, msg: &str) { + self.ok().expect(msg); + } +} +impl ::core::convert::From<BOOLEAN> for bool { + fn from(value: BOOLEAN) -> Self { + value.as_bool() + } +} +impl ::core::convert::From<&BOOLEAN> for bool { + fn from(value: &BOOLEAN) -> Self { + value.as_bool() + } +} +impl ::core::convert::From<bool> for BOOLEAN { + fn from(value: bool) -> Self { + if value { + Self(1) + } else { + Self(0) + } + } +} +impl ::core::convert::From<&bool> for BOOLEAN { + fn from(value: &bool) -> Self { + (*value).into() + } +} +impl ::core::cmp::PartialEq<bool> for BOOLEAN { + fn eq(&self, other: &bool) -> bool { + self.as_bool() == *other + } +} +impl ::core::cmp::PartialEq<BOOLEAN> for bool { + fn eq(&self, other: &BOOLEAN) -> bool { + *self == other.as_bool() + } +} +impl ::core::ops::Not for BOOLEAN { + type Output = Self; + fn not(self) -> Self::Output { + if self.as_bool() { + Self(0) + } else { + Self(1) + } + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/NTSTATUS.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/NTSTATUS.rs new file mode 100644 index 000000000..66d77db19 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/NTSTATUS.rs @@ -0,0 +1,32 @@ +impl NTSTATUS { + #[inline] + pub const fn is_ok(self) -> bool { + self.0 >= 0 + } + #[inline] + pub const fn is_err(self) -> bool { + !self.is_ok() + } + #[inline] + pub const fn to_hresult(self) -> ::windows::core::HRESULT { + ::windows::core::HRESULT(self.0 | 0x1000_0000) + } + #[inline] + pub const fn ok(self) -> ::windows::core::Result<()> { + if self.is_ok() { + Ok(()) + } else { + Err(::windows::core::Error { code: self.to_hresult(), info: None }) + } + } +} +impl ::core::convert::From<NTSTATUS> for ::windows::core::HRESULT { + fn from(value: NTSTATUS) -> Self { + value.to_hresult() + } +} +impl ::core::convert::From<NTSTATUS> for ::windows::core::Error { + fn from(value: NTSTATUS) -> Self { + Self { code: value.to_hresult(), info: None } + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/VARIANT_BOOL.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/VARIANT_BOOL.rs new file mode 100644 index 000000000..3015224ef --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/VARIANT_BOOL.rs @@ -0,0 +1,68 @@ +impl VARIANT_BOOL { + #[inline] + pub fn as_bool(self) -> bool { + self.0 != 0 + } + #[inline] + pub fn ok(self) -> ::windows::core::Result<()> { + if self.as_bool() { + Ok(()) + } else { + Err(::windows::core::Error::from_win32()) + } + } + #[inline] + #[track_caller] + pub fn unwrap(self) { + self.ok().unwrap(); + } + #[inline] + #[track_caller] + pub fn expect(self, msg: &str) { + self.ok().expect(msg); + } +} +impl ::core::convert::From<VARIANT_BOOL> for bool { + fn from(value: VARIANT_BOOL) -> Self { + value.as_bool() + } +} +impl ::core::convert::From<&VARIANT_BOOL> for bool { + fn from(value: &VARIANT_BOOL) -> Self { + value.as_bool() + } +} +impl ::core::convert::From<bool> for VARIANT_BOOL { + fn from(value: bool) -> Self { + if value { + VARIANT_TRUE + } else { + VARIANT_FALSE + } + } +} +impl ::core::convert::From<&bool> for VARIANT_BOOL { + fn from(value: &bool) -> Self { + (*value).into() + } +} +impl ::core::cmp::PartialEq<bool> for VARIANT_BOOL { + fn eq(&self, other: &bool) -> bool { + self.as_bool() == *other + } +} +impl ::core::cmp::PartialEq<VARIANT_BOOL> for bool { + fn eq(&self, other: &VARIANT_BOOL) -> bool { + *self == other.as_bool() + } +} +impl ::core::ops::Not for VARIANT_BOOL { + type Output = Self; + fn not(self) -> Self::Output { + if self.as_bool() { + VARIANT_FALSE + } else { + VARIANT_TRUE + } + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/WIN32_ERROR.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/WIN32_ERROR.rs new file mode 100644 index 000000000..d875953b2 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Foundation/WIN32_ERROR.rs @@ -0,0 +1,41 @@ +impl WIN32_ERROR { + #[inline] + pub const fn is_ok(self) -> bool { + self.0 == 0 + } + #[inline] + pub const fn is_err(self) -> bool { + !self.is_ok() + } + #[inline] + pub const fn to_hresult(self) -> ::windows::core::HRESULT { + ::windows::core::HRESULT(if self.0 == 0 { self.0 } else { (self.0 & 0x0000_FFFF) | (7 << 16) | 0x8000_0000 } as _) + } + #[inline] + pub fn from_error(error: &::windows::core::Error) -> ::core::option::Option<Self> { + let hresult = error.code().0 as u32; + if ((hresult >> 16) & 0x7FF) == 7 { + Some(Self(hresult & 0xFFFF)) + } else { + None + } + } + #[inline] + pub const fn ok(self) -> ::windows::core::Result<()> { + if self.is_ok() { + Ok(()) + } else { + Err(::windows::core::Error { code: self.to_hresult(), info: None }) + } + } +} +impl ::core::convert::From<WIN32_ERROR> for ::windows::core::HRESULT { + fn from(value: WIN32_ERROR) -> Self { + value.to_hresult() + } +} +impl ::core::convert::From<WIN32_ERROR> for ::windows::core::Error { + fn from(value: WIN32_ERROR) -> Self { + Self { code: value.to_hresult(), info: None } + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/IN6_ADDR.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/IN6_ADDR.rs new file mode 100644 index 000000000..f4290fba6 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/IN6_ADDR.rs @@ -0,0 +1,11 @@ +impl ::core::convert::From<::std::net::Ipv6Addr> for IN6_ADDR { + fn from(addr: ::std::net::Ipv6Addr) -> Self { + Self { u: IN6_ADDR_0 { Byte: addr.octets() } } + } +} +impl ::core::convert::From<IN6_ADDR> for ::std::net::Ipv6Addr { + fn from(in6_addr: IN6_ADDR) -> Self { + // SAFETY: this is safe because the union variants are just views of the same exact data + Self::from(unsafe { in6_addr.u.Byte }) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/IN_ADDR.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/IN_ADDR.rs new file mode 100644 index 000000000..d12af968b --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/IN_ADDR.rs @@ -0,0 +1,15 @@ +impl ::core::convert::From<::std::net::Ipv4Addr> for IN_ADDR { + fn from(addr: ::std::net::Ipv4Addr) -> Self { + // u32::from(addr) is in host byte order + // S_addr must be big-endian, network byte order + Self { S_un: IN_ADDR_0 { S_addr: u32::from(addr).to_be() } } + } +} +impl ::core::convert::From<IN_ADDR> for ::std::net::Ipv4Addr { + fn from(in_addr: IN_ADDR) -> Self { + // SAFETY: this is safe because the union variants are just views of the same exact data + // in_addr.S_un.S_addr is big-endian, network byte order + // Ipv4Addr::new() expects the parameter in host byte order + Self::from(u32::from_be(unsafe { in_addr.S_un.S_addr })) + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN.rs new file mode 100644 index 000000000..68bfdc76d --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN.rs @@ -0,0 +1,7 @@ +impl ::core::convert::From<::std::net::SocketAddrV4> for SOCKADDR_IN { + fn from(addr: ::std::net::SocketAddrV4) -> Self { + // addr.port() is in host byte order + // sin_port must be big-endian, network byte order + SOCKADDR_IN { sin_family: AF_INET, sin_port: addr.port().to_be(), sin_addr: (*addr.ip()).into(), ..Default::default() } + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN6.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN6.rs new file mode 100644 index 000000000..7b76f2f7d --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_IN6.rs @@ -0,0 +1,15 @@ +impl ::core::convert::From<::std::net::SocketAddrV6> for SOCKADDR_IN6 { + fn from(addr: ::std::net::SocketAddrV6) -> Self { + // addr.port() and addr.flowinfo() are in host byte order + // sin6_port and sin6_flowinfo must be big-endian, network byte order + // sin6_scope_id is a bitfield without endianness + SOCKADDR_IN6 { + sin6_family: AF_INET6, + sin6_port: addr.port().to_be(), + sin6_flowinfo: addr.flowinfo().to_be(), + sin6_addr: (*addr.ip()).into(), + Anonymous: SOCKADDR_IN6_0 { sin6_scope_id: addr.scope_id() }, + ..Default::default() + } + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_INET.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_INET.rs new file mode 100644 index 000000000..ccaf570c0 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/Networking/WinSock/SOCKADDR_INET.rs @@ -0,0 +1,19 @@ + +impl ::core::convert::From<::std::net::SocketAddrV4> for SOCKADDR_INET { + fn from(addr: ::std::net::SocketAddrV4) -> Self { + SOCKADDR_INET { Ipv4: addr.into() } + } +} +impl ::core::convert::From<::std::net::SocketAddrV6> for SOCKADDR_INET { + fn from(addr: ::std::net::SocketAddrV6) -> Self { + SOCKADDR_INET { Ipv6: addr.into() } + } +} +impl ::core::convert::From<::std::net::SocketAddr> for SOCKADDR_INET { + fn from(addr: ::std::net::SocketAddr) -> Self { + match addr { + ::std::net::SocketAddr::V4(socket_addr_v4) => socket_addr_v4.into(), + ::std::net::SocketAddr::V6(socket_addr_v6) => socket_addr_v6.into(), + } + } +} diff --git a/vendor/windows-bindgen/src/extensions/mod/Win32/UI/WindowsAndMessaging/WindowLong.rs b/vendor/windows-bindgen/src/extensions/mod/Win32/UI/WindowsAndMessaging/WindowLong.rs new file mode 100644 index 000000000..cf1cc08d9 --- /dev/null +++ b/vendor/windows-bindgen/src/extensions/mod/Win32/UI/WindowsAndMessaging/WindowLong.rs @@ -0,0 +1,12 @@ +#[cfg(target_pointer_width = "32")] +#[cfg(feature = "Win32_Foundation")] +pub use GetWindowLongA as GetWindowLongPtrA; +#[cfg(target_pointer_width = "32")] +#[cfg(feature = "Win32_Foundation")] +pub use GetWindowLongW as GetWindowLongPtrW; +#[cfg(target_pointer_width = "32")] +#[cfg(feature = "Win32_Foundation")] +pub use SetWindowLongA as SetWindowLongPtrA; +#[cfg(target_pointer_width = "32")] +#[cfg(feature = "Win32_Foundation")] +pub use SetWindowLongW as SetWindowLongPtrW; diff --git a/vendor/windows-bindgen/src/functions.rs b/vendor/windows-bindgen/src/functions.rs new file mode 100644 index 000000000..f5ec866bb --- /dev/null +++ b/vendor/windows-bindgen/src/functions.rs @@ -0,0 +1,285 @@ +use super::*; + +pub fn gen(gen: &Gen, def: MethodDef) -> TokenStream { + if gen.sys { + gen_sys_function(gen, def) + } else { + gen_win_function(gen, def) + } +} + +fn gen_sys_function(gen: &Gen, def: MethodDef) -> TokenStream { + let signature = gen.reader.method_def_signature(def, &[]); + let cfg = gen.reader.signature_cfg(&signature); + let mut tokens = gen.cfg_features(&cfg); + tokens.combine(&gen_link(gen, &signature, &cfg)); + tokens +} + +fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream { + let name = to_ident(gen.reader.method_def_name(def)); + let signature = gen.reader.method_def_signature(def, &[]); + let generics = gen.constraint_generics(&signature.params); + let where_clause = gen.where_clause(&signature.params); + let abi_return_type = gen.return_sig(&signature); + let cfg = gen.reader.signature_cfg(&signature); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + let link = gen_link(gen, &signature, &cfg); + + let kind = gen.reader.signature_kind(&signature); + match kind { + SignatureKind::Query(_) => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let generics = expand_generics(generics, quote!(T)); + let where_clause = + expand_where_clause(where_clause, quote!(T: ::windows::core::ComInterface)); + + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<T> #where_clause { + #link + let mut result__ = ::std::ptr::null_mut(); + #name(#args).from_abi(result__) + } + } + } + SignatureKind::QueryOptional(_) => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let generics = expand_generics(generics, quote!(T)); + let where_clause = + expand_where_clause(where_clause, quote!(T: ::windows::core::ComInterface)); + + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params result__: *mut ::core::option::Option<T>) -> ::windows::core::Result<()> #where_clause { + #link + #name(#args).ok() + } + } + } + SignatureKind::ResultValue => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let return_type = signature.params[signature.params.len() - 1].ty.deref(); + let return_type = gen.type_name(&return_type); + + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<#return_type> #where_clause { + #link + let mut result__ = ::windows::core::zeroed::<#return_type>(); + #name(#args).from_abi(result__) + } + } + } + SignatureKind::ResultVoid => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<()> #where_clause { + #link + #name(#args).ok() + } + } + } + SignatureKind::ReturnValue => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let return_type = signature.params[signature.params.len() - 1].ty.deref(); + let is_nullable = gen.reader.type_is_nullable(&return_type); + let return_type = gen.type_name(&return_type); + + if is_nullable { + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<#return_type> #where_clause { + #link + let mut result__ = ::windows::core::zeroed::<#return_type>(); + #name(#args); + ::windows::core::from_abi(result__.assume_init()) + } + } + } else { + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) -> #return_type #where_clause { + #link + let mut result__ = ::windows::core::zeroed::<#return_type>(); + #name(#args); + ::std::mem::transmute(result__) + } + } + } + } + SignatureKind::ReturnStruct | SignatureKind::PreserveSig => { + if handle_last_error(gen, def, &signature) { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let return_type = gen.type_name(&signature.return_type.unwrap()); + + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<#return_type> #where_clause { + #link + let result__ = #name(#args); + ::windows::imp::then(!result__.is_invalid(), ||result__).ok_or_else(::windows::core::Error::from_win32) + } + } + } else { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) #abi_return_type #where_clause { + #link + #name(#args) + } + } + } + } + SignatureKind::ReturnVoid => { + let args = gen.win32_args(&signature.params, kind); + let params = gen.win32_params(&signature.params, kind); + let does_not_return = does_not_return(gen, def); + + quote! { + #doc + #features + #[inline] + pub unsafe fn #name<#generics>(#params) #does_not_return #where_clause { + #link + #name(#args) + } + } + } + } +} + +fn gen_link(gen: &Gen, signature: &Signature, cfg: &Cfg) -> TokenStream { + let name = gen.reader.method_def_name(signature.def); + let ident = to_ident(name); + let library = gen.reader.method_def_module_name(signature.def); + let abi = gen.reader.method_def_extern_abi(signature.def); + + let symbol = if let Some(impl_map) = gen.reader.method_def_impl_map(signature.def) { + gen.reader.impl_map_import_name(impl_map) + } else { + name + }; + + let link_name = if symbol != name { + quote! { #[link_name = #symbol] } + } else { + quote! {} + }; + + let params = signature.params.iter().map(|p| { + let name = gen.param_name(p.def); + let tokens = if p.kind == SignatureParamKind::ValueType { + gen.type_default_name(&p.ty) + } else { + gen.type_abi_name(&p.ty) + }; + quote! { #name: #tokens } + }); + + let return_type = gen.return_sig(signature); + + if gen.std || !gen.namespace.starts_with("Windows.") { + let library = library.trim_end_matches(".dll"); + + quote! { + #[link(name = #library)] + extern #abi { + #link_name + pub fn #ident(#(#params),*) #return_type; + } + } + } else if let Some(library) = gen.reader.method_def_static_lib(signature.def) { + quote! { + #[link(name = #library, kind = "static")] + extern #abi { + #link_name + pub fn #ident(#(#params),*) #return_type; + } + } + } else { + let symbol = if symbol != name { + format!(" \"{symbol}\"") + } else { + String::new() + }; + + let doc = if gen.sys { + gen.cfg_doc(cfg).0 + } else { + String::new() + }; + + let mut tokens = String::new(); + for param in params { + tokens.push_str(&format!("{}, ", param.as_str())); + } + let tokens = tokens.trim_end_matches(", "); + format!( + r#"::windows_targets::link!("{library}" "{abi}"{symbol}{doc} fn {name}({tokens}){return_type});"# + ) + .into() + } +} + +fn does_not_return(gen: &Gen, def: MethodDef) -> TokenStream { + if gen.reader.method_def_does_not_return(def) { + quote! { -> ! } + } else { + quote! {} + } +} + +fn handle_last_error(gen: &Gen, def: MethodDef, signature: &Signature) -> bool { + if let Some(map) = gen.reader.method_def_impl_map(def) { + if gen + .reader + .impl_map_flags(map) + .contains(PInvokeAttributes::LAST_ERROR) + { + if let Some(Type::TypeDef((return_type, _))) = &signature.return_type { + if gen.reader.type_def_is_handle(*return_type) { + if gen + .reader + .type_def_underlying_type(*return_type) + .is_pointer() + { + return true; + } + if !gen.reader.type_def_invalid_values(*return_type).is_empty() { + return true; + } + } + } + } + } + false +} diff --git a/vendor/windows-bindgen/src/gen.rs b/vendor/windows-bindgen/src/gen.rs new file mode 100644 index 000000000..30d4150e6 --- /dev/null +++ b/vendor/windows-bindgen/src/gen.rs @@ -0,0 +1,1400 @@ +use super::*; + +pub struct Gen<'a> { + pub reader: &'a Reader<'a>, + pub namespace: &'a str, + pub sys: bool, + pub cfg: bool, + pub doc: bool, + pub component: bool, + pub standalone: bool, + pub std: bool, +} + +impl<'a> Gen<'a> { + pub fn new(reader: &'a Reader) -> Self { + Self { + reader, + namespace: "", + sys: false, + cfg: false, + doc: false, + component: false, + standalone: false, + std: false, + } + } + + // + // TypeDef + // + + pub fn type_def_name(&self, def: TypeDef, generics: &[Type]) -> TokenStream { + self.type_def_name_imp(def, generics, "") + } + pub fn type_def_vtbl_name(&self, def: TypeDef, generics: &[Type]) -> TokenStream { + self.type_def_name_imp(def, generics, "_Vtbl") + } + pub fn type_def_name_imp(&self, def: TypeDef, generics: &[Type], suffix: &str) -> TokenStream { + let type_name = self.reader.type_def_type_name(def); + + if type_name.namespace.is_empty() { + to_ident(&self.scoped_name(def)) + } else { + let mut namespace = self.namespace(type_name.namespace); + let mut name = to_ident(type_name.name); + name.push_str(suffix); + + if generics.is_empty() || self.sys { + namespace.combine(&name); + namespace + } else { + let colon_separated = if !namespace.as_str().is_empty() { + quote! { :: } + } else { + quote! {} + }; + + let generics = generics.iter().map(|ty| self.type_name(ty)); + quote! { #namespace #name #colon_separated<#(#generics),*> } + } + } + } + + // + // Type + // + + pub fn type_default_name(&self, ty: &Type) -> TokenStream { + if let Type::WinrtArray(ty) = ty { + self.type_default_name(ty) + } else { + let kind = self.type_name(ty); + + if ty.is_generic() { + quote! { <#kind as ::windows::core::Type<#kind>>::Default } + } else if self.reader.type_is_nullable(ty) && !self.sys { + quote! { ::core::option::Option<#kind> } + } else { + kind + } + } + } + + pub(crate) fn type_name(&self, ty: &Type) -> TokenStream { + match ty { + Type::Void => quote! { ::core::ffi::c_void }, + Type::Bool => quote! { bool }, + Type::Char => quote! { u16 }, + Type::I8 => quote! { i8 }, + Type::U8 => quote! { u8 }, + Type::I16 => quote! { i16 }, + Type::U16 => quote! { u16 }, + Type::I32 => quote! { i32 }, + Type::U32 => quote! { u32 }, + Type::I64 => quote! { i64 }, + Type::U64 => quote! { u64 }, + Type::F32 => quote! { f32 }, + Type::F64 => quote! { f64 }, + Type::ISize => quote! { isize }, + Type::USize => quote! { usize }, + Type::String => { + let crate_name = self.crate_name(); + quote! { #crate_name HSTRING } + } + Type::BSTR => { + let crate_name = self.crate_name(); + quote! { #crate_name BSTR } + } + Type::IInspectable => { + let crate_name = self.crate_name(); + quote! { #crate_name IInspectable } + } + Type::GUID => { + let crate_name = self.crate_name(); + quote! { #crate_name GUID } + } + Type::IUnknown => { + let crate_name = self.crate_name(); + quote! { #crate_name IUnknown } + } + Type::HRESULT => { + let crate_name = self.crate_name(); + quote! { #crate_name HRESULT } + } + Type::PSTR => { + let crate_name = self.crate_name(); + quote! { #crate_name PSTR } + } + Type::PWSTR => { + let crate_name = self.crate_name(); + quote! { #crate_name PWSTR } + } + Type::PCSTR => { + let crate_name = self.crate_name(); + quote! { #crate_name PCSTR } + } + Type::PCWSTR => { + let crate_name = self.crate_name(); + quote! { #crate_name PCWSTR } + } + Type::Win32Array((ty, len)) => { + let name = self.type_default_name(ty); + let len = Literal::usize_unsuffixed(*len); + quote! { [#name; #len] } + } + Type::GenericParam(generic) => self.reader.generic_param_name(*generic).into(), + Type::TypeDef((def, generics)) => self.type_def_name(*def, generics), + Type::MutPtr((ty, pointers)) => { + let pointers = mut_ptrs(*pointers); + let ty = self.type_default_name(ty); + quote! { #pointers #ty } + } + Type::ConstPtr((ty, pointers)) => { + let pointers = const_ptrs(*pointers); + let ty = self.type_default_name(ty); + quote! { #pointers #ty } + } + Type::WinrtArray(ty) => self.type_name(ty), + Type::WinrtArrayRef(ty) => self.type_name(ty), + Type::WinrtConstRef(ty) => self.type_name(ty), + _ => unimplemented!(), + } + } + pub fn type_vtbl_name(&self, ty: &Type) -> TokenStream { + match ty { + Type::TypeDef((def, generics)) => self.type_def_vtbl_name(*def, generics), + _ => unimplemented!(), + } + } + pub fn type_abi_name(&self, ty: &Type) -> TokenStream { + if self.sys { + return self.type_default_name(ty); + } + + match ty { + Type::IUnknown | Type::IInspectable => { + quote! { *mut ::core::ffi::c_void } + } + Type::String => { + quote! { ::std::mem::MaybeUninit<::windows::core::HSTRING> } + } + Type::BSTR => { + quote! { ::std::mem::MaybeUninit<::windows::core::BSTR> } + } + Type::Win32Array((kind, len)) => { + let name = self.type_abi_name(kind); + let len = Literal::usize_unsuffixed(*len); + quote! { [#name; #len] } + } + Type::GenericParam(generic) => { + let name = to_ident(self.reader.generic_param_name(*generic)); + quote! { ::windows::core::AbiType<#name> } + } + Type::TypeDef((def, _)) => match self.reader.type_def_kind(*def) { + TypeKind::Enum => self.type_def_name(*def, &[]), + TypeKind::Struct => { + let tokens = self.type_def_name(*def, &[]); + if self.reader.type_def_is_blittable(*def) { + tokens + } else { + quote! { ::std::mem::MaybeUninit<#tokens> } + } + } + TypeKind::Delegate => { + if self + .reader + .type_def_flags(*def) + .contains(TypeAttributes::WINRT) + { + quote! { *mut ::core::ffi::c_void } + } else { + self.type_def_name(*def, &[]) + } + } + _ => quote! { *mut ::core::ffi::c_void }, + }, + Type::MutPtr((kind, pointers)) => { + let pointers_tokens = gen_mut_ptrs(*pointers); + let kind = if *pointers > 1 { + self.type_name(kind) + } else { + self.type_abi_name(kind) + }; + quote! { #pointers_tokens #kind } + } + Type::ConstPtr((kind, pointers)) => { + let pointers_tokens = gen_const_ptrs(*pointers); + let kind = if *pointers > 1 { + self.type_name(kind) + } else { + self.type_abi_name(kind) + }; + quote! { #pointers_tokens #kind } + } + Type::WinrtArray(kind) => self.type_abi_name(kind), + Type::WinrtArrayRef(kind) => self.type_abi_name(kind), + _ => self.type_name(ty), + } + } + + // + // Constraints + // + + pub fn generic_phantoms(&self, generics: &[Type]) -> TokenStream { + let mut tokens = TokenStream::new(); + for generic in generics { + let generic = self.type_name(generic); + tokens.combine("e! { ::core::marker::PhantomData::<#generic>, }); + } + tokens + } + pub fn generic_named_phantoms(&self, generics: &[Type]) -> Vec<TokenStream> { + generics + .iter() + .map(|generic| { + let generic = self.type_name(generic); + quote! { #generic: ::core::marker::PhantomData::<#generic>, } + }) + .collect() + } + pub fn generic_constraints(&self, generics: &[Type]) -> TokenStream { + let mut tokens = TokenStream::new(); + for generic in generics { + let generic = self.type_name(generic); + tokens.combine("e! { #generic: ::windows::core::RuntimeType + 'static, }); + } + tokens + } + pub fn generic_names(&self, generics: &[Type]) -> TokenStream { + let mut tokens = TokenStream::new(); + for generic in generics { + let generic = self.type_name(generic); + tokens.combine("e! { #generic, }); + } + tokens + } + /// The signature params which are generic (along with their relative index) + pub fn generic_params<'b>( + &'b self, + params: &'b [SignatureParam], + ) -> impl Iterator<Item = (usize, &SignatureParam)> + 'b { + params + .iter() + .filter(move |param| self.reader.signature_param_is_convertible(param)) + .enumerate() + } + /// The generic param names (i.e., `T` in `fn foo<T>()`) + pub fn constraint_generics(&self, params: &[SignatureParam]) -> TokenStream { + let mut generics = self + .generic_params(params) + .map(|(position, _)| -> TokenStream { format!("P{position}").into() }) + .peekable(); + + if generics.peek().is_some() { + quote!(#(#generics),*) + } else { + TokenStream::new() + } + } + /// A `where` clause for some constrained generic params + pub fn where_clause(&self, params: &[SignatureParam]) -> TokenStream { + let constraints = self.param_constraints(params); + + if !constraints.is_empty() { + quote!(where #constraints) + } else { + quote!() + } + } + fn param_constraints(&self, params: &[SignatureParam]) -> TokenStream { + let mut tokens = TokenStream::new(); + let gen_name = |position| { + let name: TokenStream = format!("P{position}").into(); + name + }; + for (position, param) in self.generic_params(params) { + match param.kind { + SignatureParamKind::TryInto => { + let name: TokenStream = gen_name(position); + let into = self.type_name(¶m.ty); + tokens.combine("e! { #name: ::windows::core::TryIntoParam<#into>, }); + } + SignatureParamKind::IntoParam => { + let name: TokenStream = gen_name(position); + let into = self.type_name(¶m.ty); + tokens.combine("e! { #name: ::windows::core::IntoParam<#into>, }); + } + _ => {} + } + } + tokens + } + + // + // Cfg + // + + /// Generates doc comments for types, free functions, and constants. + pub(crate) fn cfg_doc(&self, cfg: &Cfg) -> TokenStream { + if !self.doc { + quote! {} + } else { + let mut tokens = format!(r#"`\"{}\"`"#, to_feature(self.namespace)); + let features = self.cfg_features_imp(cfg, self.namespace); + + for features in features { + write!(tokens, r#", `\"{}\"`"#, to_feature(features)).unwrap(); + } + + if cfg.implement { + tokens.push_str(r#", `\"implement\"`"#) + } + + format!(r#" #[doc = "*Required features: {tokens}*"]"#).into() + } + } + + /// Generates doc comments for member functions (methods) and avoids redundantly declaring the + /// enclosing module feature required by the method's type. + pub(crate) fn cfg_method_doc(&self, cfg: &Cfg) -> TokenStream { + if !self.doc { + quote! {} + } else { + let features = self.cfg_features_imp(cfg, self.namespace); + if features.is_empty() { + quote! {} + } else { + let mut tokens = String::new(); + for features in features { + write!(tokens, r#"`\"{}\"`, "#, to_feature(features)).unwrap(); + } + tokens.truncate(tokens.len() - 2); + format!(r#"#[doc = "*Required features: {tokens}*"]"#).into() + } + } + } + + pub(crate) fn cfg_features(&self, cfg: &Cfg) -> TokenStream { + let arches = &cfg.arches; + let arch = match arches.len() { + 0 => quote! {}, + 1 => { + quote! { #[cfg(#(target_arch = #arches),*)] } + } + _ => { + quote! { #[cfg(any(#(target_arch = #arches),*))] } + } + }; + + let features = self.cfg_features_imp(cfg, self.namespace); + + let features = match features.len() { + 0 => quote! {}, + 1 => { + let features = features.iter().cloned().map(to_feature); + quote! { #[cfg(#(feature = #features)*)] } + } + _ => { + let features = features.iter().cloned().map(to_feature); + quote! { #[cfg(all( #(feature = #features),* ))] } + } + }; + + quote! { #arch #features } + } + + fn cfg_features_imp(&self, cfg: &'a Cfg, namespace: &'a str) -> Vec<&'a str> { + let mut compact = Vec::<&'static str>::new(); + if !self.standalone && !self.component { + for feature in cfg.types.keys() { + if !feature.is_empty() && !starts_with(namespace, feature) { + for pos in 0..compact.len() { + if starts_with(feature, unsafe { compact.get_unchecked(pos) }) { + compact.remove(pos); + break; + } + } + compact.push(feature); + } + } + } + compact + } + + fn cfg_not_features(&self, cfg: &Cfg) -> TokenStream { + let features = self.cfg_features_imp(cfg, self.namespace); + if features.is_empty() { + quote! {} + } else { + match features.len() { + 0 => quote! {}, + 1 => { + let features = features.iter().cloned().map(to_feature); + quote! { #[cfg(not(#(feature = #features)*))] } + } + _ => { + let features = features.iter().cloned().map(to_feature); + quote! { #[cfg(not(all( #(feature = #features),* )))] } + } + } + } + } + + // + // Other helpers + // + + pub(crate) fn namespace(&self, namespace: &str) -> TokenStream { + if self.standalone || namespace == self.namespace { + quote! {} + } else { + let is_external = + namespace.starts_with("Windows.") && !self.namespace.starts_with("Windows"); + let mut relative = self.namespace.split('.').peekable(); + let mut namespace = namespace.split('.').peekable(); + + while relative.peek() == namespace.peek() { + if relative.next().is_none() { + break; + } + + namespace.next(); + } + + let mut tokens = TokenStream::new(); + + if is_external { + tokens.push_str("::windows::"); + namespace.next(); + } else { + for _ in 0..relative.count() { + tokens.push_str("super::"); + } + } + + for namespace in namespace { + tokens.push_str(namespace); + tokens.push_str("::"); + } + + tokens + } + } + pub fn crate_name(&self) -> TokenStream { + if self.standalone { + TokenStream::new() + } else if self.sys { + "::windows_sys::core::".into() + } else { + "::windows::core::".into() + } + } + fn scoped_name(&self, def: TypeDef) -> String { + if let Some(enclosing_type) = self.reader.type_def_enclosing_type(def) { + for (index, nested_type) in self.reader.nested_types(enclosing_type).enumerate() { + if self.reader.type_def_name(nested_type) == self.reader.type_def_name(def) { + return format!("{}_{index}", &self.scoped_name(enclosing_type)); + } + } + } + self.reader.type_def_name(def).to_string() + } + pub fn value(&self, value: &Value) -> TokenStream { + match value { + Value::Bool(value) => quote! { #value }, + Value::U8(value) => quote! { #value }, + Value::I8(value) => quote! { #value }, + Value::U16(value) => quote! { #value }, + Value::I16(value) => quote! { #value }, + Value::U32(value) => quote! { #value }, + Value::I32(value) => quote! { #value }, + Value::U64(value) => quote! { #value }, + Value::I64(value) => quote! { #value }, + Value::F32(value) => quote! { #value }, + Value::F64(value) => quote! { #value }, + Value::String(value) => { + let mut tokens = "\"".to_string(); + + for u in value.chars() { + write!(tokens, "{}", u.escape_default()).unwrap(); + } + + tokens.push('\"'); + tokens.into() + } + _ => unimplemented!(), + } + } + pub fn typed_value(&self, value: &Value) -> TokenStream { + let literal = self.value(value); + match value { + Value::Bool(_) => quote! { bool = #literal }, + Value::U8(_) => quote! { u8 = #literal }, + Value::I8(_) => quote! { i8 = #literal }, + Value::U16(_) => quote! { u16 = #literal }, + Value::I16(_) => quote! { i16 = #literal }, + Value::U32(_) => quote! { u32 = #literal }, + Value::I32(_) => quote! { i32 = #literal }, + Value::U64(_) => quote! { u64 = #literal }, + Value::I64(_) => quote! { i64 = #literal }, + Value::F32(_) => quote! { f32 = #literal }, + Value::F64(_) => quote! { f64 = #literal }, + Value::String(_) => { + quote! { &str = #literal } + } + _ => unimplemented!(), + } + } + + pub fn guid(&self, value: &GUID) -> TokenStream { + let guid = self.type_name(&Type::GUID); + format!("{}::from_u128(0x{:08x?}_{:04x?}_{:04x?}_{:02x?}{:02x?}_{:02x?}{:02x?}{:02x?}{:02x?}{:02x?}{:02x?})", guid.into_string(), value.0, value.1, value.2, value.3, value.4, value.5, value.6, value.7, value.8, value.9, value.10).into() + } + pub fn interface_core_traits( + &self, + def: TypeDef, + _generics: &[Type], + ident: &TokenStream, + constraints: &TokenStream, + _phantoms: &TokenStream, + features: &TokenStream, + ) -> TokenStream { + let name = trim_tick(self.reader.type_def_name(def)); + quote! { + #features + impl<#constraints> ::core::cmp::PartialEq for #ident { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } + } + #features + impl<#constraints> ::core::cmp::Eq for #ident {} + #features + impl<#constraints> ::core::fmt::Debug for #ident { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple(#name).field(&self.0).finish() + } + } + } + } + pub fn agile( + &self, + def: TypeDef, + ident: &TokenStream, + constraints: &TokenStream, + features: &TokenStream, + ) -> TokenStream { + if self.reader.type_def_is_agile(def) { + quote! { + #features + unsafe impl<#constraints> ::core::marker::Send for #ident {} + #features + unsafe impl<#constraints> ::core::marker::Sync for #ident {} + } + } else { + quote! {} + } + } + pub fn async_get( + &self, + def: TypeDef, + generics: &[Type], + ident: &TokenStream, + constraints: &TokenStream, + _phantoms: &TokenStream, + features: &TokenStream, + ) -> TokenStream { + let mut kind = self.reader.type_def_async_kind(def); + let mut async_generics = generics.to_vec(); + + if kind == AsyncKind::None { + for interface in self.reader.type_def_interfaces(def, generics) { + if let Type::TypeDef((interface_def, interface_generics)) = &interface.ty { + kind = self.reader.type_def_async_kind(*interface_def); + if kind != AsyncKind::None { + async_generics = interface_generics.to_vec(); + break; + } + } + } + } + + if kind == AsyncKind::None { + quote! {} + } else { + let return_type = match kind { + AsyncKind::Operation | AsyncKind::OperationWithProgress => { + self.type_name(&async_generics[0]) + } + _ => quote! { () }, + }; + + let handler = match kind { + AsyncKind::Action => quote! { AsyncActionCompletedHandler }, + AsyncKind::ActionWithProgress => quote! { AsyncActionWithProgressCompletedHandler }, + AsyncKind::Operation => quote! { AsyncOperationCompletedHandler }, + AsyncKind::OperationWithProgress => { + quote! { AsyncOperationWithProgressCompletedHandler } + } + _ => unimplemented!(), + }; + + let namespace = self.namespace("Windows.Foundation"); + + quote! { + #features + impl<#constraints> #ident { + pub fn get(&self) -> ::windows::core::Result<#return_type> { + if self.Status()? == #namespace AsyncStatus::Started { + let (_waiter, signaler) = ::windows::imp::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() + } + } + #features + impl<#constraints> ::std::future::Future for #ident { + type Output = ::windows::core::Result<#return_type>; + + 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()) + } + } + } + } + } + } + pub fn interface_winrt_trait( + &self, + def: TypeDef, + generics: &[Type], + ident: &TokenStream, + constraints: &TokenStream, + _phantoms: &TokenStream, + features: &TokenStream, + ) -> TokenStream { + if self + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + let type_signature = if self.reader.type_def_kind(def) == TypeKind::Class { + let type_signature = + Literal::byte_string(self.reader.type_def_signature(def, generics).as_bytes()); + quote! { ::windows::imp::ConstBuffer::from_slice(#type_signature) } + } else { + let signature = Literal::byte_string( + format!("{{{:#?}}}", self.reader.type_def_guid(def).unwrap()).as_bytes(), + ); + + if generics.is_empty() { + quote! { ::windows::imp::ConstBuffer::from_slice(#signature) } + } else { + let generics = generics.iter().enumerate().map(|(index, g)| { + let g = self.type_name(g); + let semi = if index != generics.len() - 1 { + Some(quote! { + .push_slice(b";") + }) + } else { + None + }; + + quote! { + .push_other(<#g as ::windows::core::RuntimeType>::SIGNATURE) + #semi + } + }); + + quote! { + { + ::windows::imp::ConstBuffer::new() + .push_slice(b"pinterface(") + .push_slice(#signature) + .push_slice(b";") + #(#generics)* + .push_slice(b")") + } + } + } + }; + + quote! { + #features + impl<#constraints> ::windows::core::RuntimeType for #ident { + const SIGNATURE: ::windows::imp::ConstBuffer = #type_signature; + } + } + } else { + quote! {} + } + } + pub fn runtime_name_trait( + &self, + def: TypeDef, + _generics: &[Type], + name: &TokenStream, + constraints: &TokenStream, + features: &TokenStream, + ) -> TokenStream { + if self + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + // TODO: this needs to use a ConstBuffer-like facility to accomodate generics + let runtime_name = format!("{}", self.reader.type_def_type_name(def)); + + quote! { + #features + impl<#constraints> ::windows::core::RuntimeName for #name { + const NAME: &'static str = #runtime_name; + } + } + } else { + quote! { + #features + impl ::windows::core::RuntimeName for #name {} + } + } + } + + pub fn interface_trait( + &self, + def: TypeDef, + generics: &[Type], + ident: &TokenStream, + constraints: &TokenStream, + features: &TokenStream, + has_unknown_base: bool, + ) -> TokenStream { + if let Some(default) = self.reader.type_def_default_interface(def) { + let default_name = self.type_name(&default); + let vtbl = self.type_vtbl_name(&default); + quote! { + #features + impl<#constraints> ::core::clone::Clone for #ident { + fn clone(&self) -> Self { + Self(self.0.clone()) + } + } + #features + unsafe impl ::windows::core::Interface for #ident { + type Vtable = #vtbl; + } + #features + unsafe impl ::windows::core::ComInterface for #ident { + const IID: ::windows::core::GUID = <#default_name as ::windows::core::ComInterface>::IID; + } + } + } else { + let vtbl = self.type_def_vtbl_name(def, generics); + let guid = if generics.is_empty() { + match self.reader.type_def_guid(def) { + Some(guid) => self.guid(&guid), + None => { + quote! { + ::windows::core::GUID::zeroed() + } + } + } + } else { + quote! { + ::windows::core::GUID::from_signature(<Self as ::windows::core::RuntimeType>::SIGNATURE) + } + }; + + let phantoms = self.generic_phantoms(generics); + + let mut tokens = quote! { + #features + unsafe impl<#constraints> ::windows::core::Interface for #ident { + type Vtable = #vtbl; + } + #features + impl<#constraints> ::core::clone::Clone for #ident { + fn clone(&self) -> Self { + Self(self.0.clone(), #phantoms) + } + } + }; + + if has_unknown_base { + tokens.combine("e! { + #features + unsafe impl<#constraints> ::windows::core::ComInterface for #ident { + const IID: ::windows::core::GUID = #guid; + } + }); + } + + tokens + } + } + pub fn interface_vtbl( + &self, + def: TypeDef, + generics: &[Type], + _ident: &TokenStream, + constraints: &TokenStream, + features: &TokenStream, + ) -> TokenStream { + let vtbl = self.type_def_vtbl_name(def, generics); + let mut methods = quote! {}; + let mut method_names = MethodNames::new(); + method_names.add_vtable_types(self, def); + let phantoms = self.generic_named_phantoms(generics); + + match self.reader.type_def_vtables(def).last() { + Some(Type::IUnknown) => { + methods.combine("e! { pub base__: ::windows::core::IUnknown_Vtbl, }) + } + Some(Type::IInspectable) => { + methods.combine("e! { pub base__: ::windows::core::IInspectable_Vtbl, }) + } + Some(Type::TypeDef((def, _))) => { + let vtbl = self.type_def_vtbl_name(*def, &[]); + methods.combine("e! { pub base__: #vtbl, }); + } + _ => {} + } + + for method in self.reader.type_def_methods(def) { + if self.reader.method_def_name(method) == ".ctor" { + continue; + } + let name = method_names.add(self, method); + let signature = self.reader.method_def_signature(method, generics); + let mut cfg = self.reader.signature_cfg(&signature); + let signature = self.vtbl_signature(def, generics, &signature); + cfg.add_feature(self.reader.type_def_namespace(def)); + let cfg_all = self.cfg_features(&cfg); + let cfg_not = self.cfg_not_features(&cfg); + + let signature = quote! { pub #name: unsafe extern "system" fn #signature, }; + + if cfg_all.is_empty() { + methods.combine(&signature); + } else { + methods.combine("e! { + #cfg_all + #signature + #cfg_not + #name: usize, + }); + } + } + + quote! { + #features + #[repr(C)] #[doc(hidden)] pub struct #vtbl where #constraints { + #methods + #(pub #phantoms)* + } + } + } + pub fn vtbl_signature( + &self, + def: TypeDef, + _generics: &[Type], + signature: &Signature, + ) -> TokenStream { + let is_winrt = self + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT); + let hresult = self.type_name(&Type::HRESULT); + + let (trailing_return_type, return_type, udt_return_type) = if is_winrt { + if let Some(return_type) = &signature.return_type { + if let Type::WinrtArray(kind) = return_type { + let tokens = self.type_abi_name(kind); + ( + quote! { result_size__: *mut u32, result__: *mut *mut #tokens }, + quote! { -> #hresult }, + quote! {}, + ) + } else { + let tokens = self.type_abi_name(return_type); + ( + quote! { result__: *mut #tokens }, + quote! { -> #hresult }, + quote! {}, + ) + } + } else { + (quote! {}, quote! { -> #hresult }, quote! {}) + } + } else if let Some(return_type) = &signature.return_type { + if self.reader.type_is_struct(return_type) { + let tokens = self.type_abi_name(return_type); + (quote! {}, quote! {}, quote! { result__: *mut #tokens, }) + } else { + let tokens = self.type_default_name(return_type); + (quote! {}, quote! { -> #tokens }, quote! {}) + } + } else { + (quote! {}, quote! {}, quote! {}) + }; + + let params = signature.params.iter().map(|p| { + let name = self.param_name(p.def); + if is_winrt { + let abi = self.type_abi_name(&p.ty); + let abi_size_name: TokenStream = + format!("{}_array_size", self.reader.param_name(p.def)).into(); + + if self + .reader + .param_flags(p.def) + .contains(ParamAttributes::INPUT) + { + if p.ty.is_winrt_array() { + quote! { #abi_size_name: u32, #name: *const #abi, } + } else if p.ty.is_winrt_const_ref() { + quote! { #name: &#abi, } + } else { + quote! { #name: #abi, } + } + } else if p.ty.is_winrt_array() { + quote! { #abi_size_name: u32, #name: *mut #abi, } + } else if p.ty.is_winrt_array_ref() { + quote! { #abi_size_name: *mut u32, #name: *mut *mut #abi, } + } else { + quote! { #name: *mut #abi, } + } + } else { + match p.kind { + SignatureParamKind::ValueType => { + let abi = self.type_default_name(&p.ty); + quote! { #name: #abi, } + } + _ => { + let abi = self.type_abi_name(&p.ty); + quote! { #name: #abi, } + } + } + } + }); + + quote! { (this: *mut ::core::ffi::c_void, #udt_return_type #(#params)* #trailing_return_type) #return_type } + } + pub fn param_name(&self, param: Param) -> TokenStream { + // In Rust, function parameters cannot be named the same as structs. This avoids some collisions that occur in the win32 metadata. + // See Icmp6SendEcho2 for an example. + to_ident(&self.reader.param_name(param).to_lowercase()) + } + pub fn return_sig(&self, signature: &Signature) -> TokenStream { + if let Some(return_type) = &signature.return_type { + let tokens = self.type_default_name(return_type); + format!(" -> {}", tokens.as_str()).into() + } else if self.reader.method_def_does_not_return(signature.def) { + " -> !".into() + } else { + " -> ()".into() + } + } + pub fn win32_args(&self, params: &[SignatureParam], kind: SignatureKind) -> TokenStream { + let mut tokens = quote! {}; + + for (position, param) in params.iter().enumerate() { + let new = match kind { + SignatureKind::Query(query) if query.object == position => { + quote! { &mut result__, } + } + SignatureKind::ReturnValue | SignatureKind::ResultValue + if params.len() - 1 == position => + { + quote! { &mut result__, } + } + SignatureKind::QueryOptional(query) if query.object == position => { + quote! { result__ as *mut _ as *mut _, } + } + SignatureKind::Query(query) | SignatureKind::QueryOptional(query) + if query.guid == position => + { + quote! { &<T as ::windows::core::ComInterface>::IID, } + } + _ => { + let name = self.param_name(param.def); + let flags = self.reader.param_flags(param.def); + match param.kind { + SignatureParamKind::ArrayFixed(_) + | SignatureParamKind::ArrayRelativeLen(_) + | SignatureParamKind::ArrayRelativeByteLen(_) => { + let map = if flags.contains(ParamAttributes::OPTIONAL) { + quote! { #name.as_deref().map_or(::core::ptr::null(), |slice|slice.as_ptr()) } + } else { + quote! { #name.as_ptr() } + }; + quote! { ::core::mem::transmute(#map), } + } + SignatureParamKind::ArrayRelativePtr(relative) => { + let name = self.param_name(params[relative].def); + let flags = self.reader.param_flags(params[relative].def); + if flags.contains(ParamAttributes::OPTIONAL) { + quote! { #name.as_deref().map_or(0, |slice|slice.len() as _), } + } else { + quote! { #name.len() as _, } + } + } + SignatureParamKind::TryInto => { + quote! { #name.try_into_param()?.abi(), } + } + SignatureParamKind::IntoParam => { + quote! { #name.into_param().abi(), } + } + SignatureParamKind::OptionalPointer => { + if flags.contains(ParamAttributes::OUTPUT) { + quote! { ::core::mem::transmute(#name.unwrap_or(::std::ptr::null_mut())), } + } else { + quote! { ::core::mem::transmute(#name.unwrap_or(::std::ptr::null())), } + } + } + SignatureParamKind::ValueType => { + quote! { #name, } + } + SignatureParamKind::Blittable => { + quote! { ::core::mem::transmute(#name), } + } + SignatureParamKind::Other => { + quote! { ::core::mem::transmute_copy(#name), } + } + } + } + }; + tokens.combine(&new) + } + + tokens + } + pub fn win32_params(&self, params: &[SignatureParam], kind: SignatureKind) -> TokenStream { + let mut tokens = quote! {}; + + let mut generic_params = self.generic_params(params); + for (position, param) in params.iter().enumerate() { + match kind { + SignatureKind::Query(query) | SignatureKind::QueryOptional(query) => { + if query.object == position || query.guid == position { + continue; + } + } + SignatureKind::ReturnValue | SignatureKind::ResultValue + if params.len() - 1 == position => + { + continue; + } + _ => {} + } + + let name = self.param_name(param.def); + + match param.kind { + SignatureParamKind::ArrayFixed(fixed) => { + let ty = param.ty.deref(); + let ty = self.type_default_name(&ty); + let len = Literal::u32_unsuffixed(fixed as _); + let ty = if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::OUTPUT) + { + quote! { &mut [#ty; #len] } + } else { + quote! { &[#ty; #len] } + }; + if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::OPTIONAL) + { + tokens.combine("e! { #name: ::core::option::Option<#ty>, }); + } else { + tokens.combine("e! { #name: #ty, }); + } + } + SignatureParamKind::ArrayRelativeLen(_) => { + let ty = param.ty.deref(); + let ty = self.type_default_name(&ty); + let ty = if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::OUTPUT) + { + quote! { &mut [#ty] } + } else { + quote! { &[#ty] } + }; + if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::OPTIONAL) + { + tokens.combine("e! { #name: ::core::option::Option<#ty>, }); + } else { + tokens.combine("e! { #name: #ty, }); + } + } + SignatureParamKind::ArrayRelativeByteLen(_) => { + let ty = if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::OUTPUT) + { + quote! { &mut [u8] } + } else { + quote! { &[u8] } + }; + if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::OPTIONAL) + { + tokens.combine("e! { #name: ::core::option::Option<#ty>, }); + } else { + tokens.combine("e! { #name: #ty, }); + } + } + SignatureParamKind::ArrayRelativePtr(_) => {} + SignatureParamKind::TryInto | SignatureParamKind::IntoParam => { + let (position, _) = generic_params.next().unwrap(); + let kind: TokenStream = format!("P{position}").into(); + tokens.combine("e! { #name: #kind, }); + } + SignatureParamKind::OptionalPointer => { + let kind = self.type_default_name(¶m.ty); + tokens.combine("e! { #name: ::core::option::Option<#kind>, }); + } + SignatureParamKind::ValueType | SignatureParamKind::Blittable => { + let kind = self.type_default_name(¶m.ty); + tokens.combine("e! { #name: #kind, }); + } + SignatureParamKind::Other => { + let kind = self.type_default_name(¶m.ty); + tokens.combine("e! { #name: &#kind, }); + } + } + } + + tokens + } + + pub fn impl_signature(&self, def: TypeDef, signature: &Signature) -> TokenStream { + if self + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + let is_delegate = self.reader.type_def_kind(def) == TypeKind::Delegate; + let params = signature + .params + .iter() + .map(|p| self.winrt_produce_type(p, !is_delegate)); + + let return_type = if let Some(return_type) = &signature.return_type { + let tokens = self.type_name(return_type); + + if return_type.is_winrt_array() { + quote! { ::windows::core::Array<#tokens> } + } else { + tokens + } + } else { + quote! { () } + }; + + let this = if is_delegate { + quote! {} + } else { + quote! { &self, } + }; + + quote! { (#this #(#params),*) -> ::windows::core::Result<#return_type> } + } else { + let signature_kind = self.reader.signature_kind(signature); + let mut params = quote! {}; + + if signature_kind == SignatureKind::ResultValue { + for param in &signature.params[..signature.params.len() - 1] { + params.combine(&self.win32_produce_type(param)); + } + } else { + for param in &signature.params { + params.combine(&self.win32_produce_type(param)); + } + } + + let return_type = match signature_kind { + SignatureKind::ReturnVoid => quote! {}, + SignatureKind::Query(_) + | SignatureKind::QueryOptional(_) + | SignatureKind::ResultVoid => quote! { -> ::windows::core::Result<()> }, + SignatureKind::ResultValue => { + let return_type = signature.params[signature.params.len() - 1].ty.deref(); + let return_type = self.type_name(&return_type); + + quote! { -> ::windows::core::Result<#return_type> } + } + _ => self.return_sig(signature), + }; + + quote! { (&self, #params) #return_type } + } + } + fn winrt_produce_type(&self, param: &SignatureParam, include_param_names: bool) -> TokenStream { + let default_type = self.type_default_name(¶m.ty); + + let sig = if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::INPUT) + { + if param.ty.is_winrt_array() { + quote! { &[#default_type] } + } else if self.reader.type_is_primitive(¶m.ty) { + quote! { #default_type } + } else if self.reader.type_is_nullable(¶m.ty) { + let type_name = self.type_name(¶m.ty); + quote! { ::core::option::Option<&#type_name> } + } else { + quote! { &#default_type } + } + } else if param.ty.is_winrt_array() { + quote! { &mut [#default_type] } + } else if param.ty.is_winrt_array_ref() { + let kind = self.type_name(¶m.ty); + quote! { &mut ::windows::core::Array<#kind> } + } else { + quote! { &mut #default_type } + }; + + if include_param_names { + let name = self.param_name(param.def); + quote! { #name: #sig } + } else { + sig + } + } + fn win32_produce_type(&self, param: &SignatureParam) -> TokenStream { + let name = self.param_name(param.def); + let kind = self.type_default_name(¶m.ty); + + if self + .reader + .param_flags(param.def) + .contains(ParamAttributes::INPUT) + { + if self.reader.type_is_primitive(¶m.ty) { + quote! { #name: #kind, } + } else if self.reader.type_is_nullable(¶m.ty) { + let kind = self.type_name(¶m.ty); + quote! { #name: ::core::option::Option<&#kind>, } + } else { + quote! { #name: &#kind, } + } + } else { + quote! { #name: #kind, } + } + } +} + +pub fn to_ident(name: &str) -> TokenStream { + // keywords list based on https://doc.rust-lang.org/reference/keywords.html + match name { + "abstract" | "as" | "become" | "box" | "break" | "const" | "continue" | "crate" | "do" + | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" | "if" | "impl" | "in" + | "let" | "loop" | "macro" | "match" | "mod" | "move" | "mut" | "override" | "priv" + | "pub" | "ref" | "return" | "static" | "struct" | "super" | "trait" | "true" | "type" + | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" | "while" | "yield" + | "try" | "async" | "await" | "dyn" => format!("r#{name}").into(), + "Self" | "self" => format!("{name}_").into(), + "_" => "unused".into(), + _ => trim_tick(name).into(), + } +} + +fn mut_ptrs(pointers: usize) -> TokenStream { + "*mut ".repeat(pointers).into() +} + +fn const_ptrs(pointers: usize) -> TokenStream { + "*const ".repeat(pointers).into() +} + +fn to_feature(name: &str) -> String { + let mut feature = String::new(); + + for name in name.split('.').skip(1) { + feature.push_str(name); + feature.push('_'); + } + + if feature.is_empty() { + feature = name.to_string(); + } else { + feature.truncate(feature.len() - 1); + } + + feature +} + +fn starts_with(namespace: &str, feature: &str) -> bool { + if namespace == feature { + return true; + } + + if namespace.len() > feature.len() && namespace.as_bytes().get(feature.len()) == Some(&b'.') { + return namespace.starts_with(feature); + } + + false +} + +fn gen_mut_ptrs(pointers: usize) -> TokenStream { + "*mut ".repeat(pointers).into() +} + +fn gen_const_ptrs(pointers: usize) -> TokenStream { + "*const ".repeat(pointers).into() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_starts_with() { + assert!(starts_with( + "Windows.Win32.Graphics.Direct3D11on12", + "Windows.Win32.Graphics.Direct3D11on12" + )); + assert!(starts_with( + "Windows.Win32.Graphics.Direct3D11on12", + "Windows.Win32.Graphics" + )); + assert!(!starts_with( + "Windows.Win32.Graphics.Direct3D11on12", + "Windows.Win32.Graphics.Direct3D11" + )); + assert!(!starts_with( + "Windows.Win32.Graphics.Direct3D", + "Windows.Win32.Graphics.Direct3D11" + )); + } +} diff --git a/vendor/windows-bindgen/src/handles.rs b/vendor/windows-bindgen/src/handles.rs new file mode 100644 index 000000000..9ace4a1b6 --- /dev/null +++ b/vendor/windows-bindgen/src/handles.rs @@ -0,0 +1,109 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.sys { + gen_sys_handle(gen, def) + } else { + gen_win_handle(gen, def) + } +} + +pub fn gen_sys_handle(gen: &Gen, def: TypeDef) -> TokenStream { + let ident = to_ident(gen.reader.type_def_name(def)); + match gen.reader.type_def_underlying_type(def) { + Type::ISize if gen.std => quote! { + pub type #ident = *mut ::core::ffi::c_void; + }, + Type::USize if gen.std => quote! { + #[cfg(target_pointer_width = "32")] + pub type #ident = u32; + #[cfg(target_pointer_width = "64")] + pub type #ident = u64; + }, + underlying_type => { + let signature = gen.type_default_name(&underlying_type); + + quote! { + pub type #ident = #signature; + } + } + } +} + +pub fn gen_win_handle(gen: &Gen, def: TypeDef) -> TokenStream { + let name = gen.reader.type_def_name(def); + let ident = to_ident(name); + let underlying_type = gen.reader.type_def_underlying_type(def); + let signature = gen.type_default_name(&underlying_type); + let check = if underlying_type.is_pointer() { + quote! { + impl #ident { + pub fn is_invalid(&self) -> bool { + self.0.is_null() + } + } + } + } else { + let invalid = gen.reader.type_def_invalid_values(def); + + if !invalid.is_empty() { + let invalid = invalid.iter().map(|value| { + let literal = Literal::i64_unsuffixed(*value); + + if *value < 0 && underlying_type.is_unsigned() { + quote! { self.0 == #literal as _ } + } else { + quote! { self.0 == #literal } + } + }); + quote! { + impl #ident { + pub fn is_invalid(&self) -> bool { + #(#invalid)||* + } + } + } + } else { + quote! {} + } + }; + + 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); + #check + 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() + } + } + impl ::windows::core::TypeKind for #ident { + type TypeKind = ::windows::core::CopyType; + } + }; + + if let Some(dependency) = gen.reader.type_def_usable_for(def) { + let type_name = gen.reader.type_def_type_name(dependency); + let mut dependency = gen.namespace(type_name.namespace); + dependency.push_str(type_name.name); + + tokens.combine("e! { + impl windows::core::CanInto<#dependency> for #ident {} + }); + } + + tokens +} diff --git a/vendor/windows-bindgen/src/implements.rs b/vendor/windows-bindgen/src/implements.rs new file mode 100644 index 000000000..3a3184b51 --- /dev/null +++ b/vendor/windows-bindgen/src/implements.rs @@ -0,0 +1,191 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.reader.type_def_kind(def) != TypeKind::Interface + || (!gen.component && !gen.reader.type_def_can_implement(def)) + { + return quote! {}; + } + + let generics: &Vec<Type> = &gen.reader.type_def_generics(def).collect(); + let type_ident = to_ident(gen.reader.type_def_name(def)); + let impl_ident = type_ident.join("_Impl"); + let vtbl_ident = type_ident.join("_Vtbl"); + let implvtbl_ident = impl_ident.join("Vtbl"); + let constraints = gen.generic_constraints(generics); + let generic_names = gen.generic_names(generics); + let named_phantoms = gen.generic_named_phantoms(generics); + let cfg = gen.reader.type_def_cfg_impl(def, generics); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + let mut requires = quote! {}; + let type_ident = quote! { #type_ident<#generic_names> }; + let vtables = gen.reader.type_def_vtables(def); + let has_unknown_base = matches!(vtables.first(), Some(Type::IUnknown)); + + fn gen_required_trait(gen: &Gen, def: TypeDef, generics: &[Type]) -> TokenStream { + let name = gen.type_def_name_imp(def, generics, "_Impl"); + quote! { + + #name + } + } + + let mut matches = quote! { iid == &<#type_ident as ::windows::core::ComInterface>::IID }; + + if let Some(Type::TypeDef((def, _))) = vtables.last() { + requires.combine(&gen_required_trait(gen, *def, &[])) + } + + for def in &vtables { + if let Type::TypeDef((def, generics)) = def { + let name = gen.type_def_name(*def, generics); + + matches.combine("e! { + || iid == &<#name as ::windows::core::ComInterface>::IID + }) + } + } + + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + // TODO: this awkward wrapping of TypeDefs needs fixing + for interface in gen + .reader + .type_interfaces(&Type::TypeDef((def, generics.to_vec()))) + { + if let Type::TypeDef((def, generics)) = interface.ty { + requires.combine(&gen_required_trait(gen, def, &generics)); + } + } + } + + let runtime_name = gen.runtime_name_trait(def, generics, &type_ident, &constraints, &features); + + let mut method_names = MethodNames::new(); + method_names.add_vtable_types(gen, def); + + let method_traits = gen.reader.type_def_methods(def).map(|method| { + let name = method_names.add(gen, method); + let signature = gen.reader.method_def_signature(method, generics); + let signature_tokens = gen.impl_signature(def, &signature); + quote! { fn #name #signature_tokens; } + }); + + let mut method_names = MethodNames::new(); + method_names.add_vtable_types(gen, def); + + let method_impls = gen.reader.type_def_methods(def).map(|method| { + let name = method_names.add(gen, method); + let signature = gen.reader.method_def_signature(method, generics); + let vtbl_signature = gen.vtbl_signature(def, generics, &signature); + + let invoke_upcall = if gen.reader.type_def_flags(def).contains(TypeAttributes::WINRT) { winrt_methods::gen_upcall(gen, &signature, quote! { this.#name }) } else { com_methods::gen_upcall(gen, &signature, quote! { this.#name }) }; + + if has_unknown_base { + quote! { + unsafe extern "system" fn #name<#constraints Identity: ::windows::core::IUnknownImpl<Impl = Impl>, Impl: #impl_ident<#generic_names>, const OFFSET: isize> #vtbl_signature { + // offset the `this` pointer by `OFFSET` times the size of a pointer and cast it as an IUnknown implementation + let this = (this as *const *const ()).offset(OFFSET) as *const Identity; + let this = (*this).get_impl(); + #invoke_upcall + } + } + } else { + quote! { + unsafe extern "system" fn #name<Impl: #impl_ident> #vtbl_signature { + let this = (this as *mut *mut ::core::ffi::c_void) as *const ::windows::core::ScopedHeap; + let this = &*((*this).this as *const Impl); + #invoke_upcall + } + } + } + }); + + let mut methods = quote! {}; + + match vtables.last() { + Some(Type::IUnknown) => methods.combine("e! { base__: ::windows::core::IUnknown_Vtbl::new::<Identity, OFFSET>(), }), + Some(Type::IInspectable) => methods.combine("e! { base__: ::windows::core::IInspectable_Vtbl::new::<Identity, #type_ident, OFFSET>(), }), + Some(Type::TypeDef((def, generics))) => { + let name = gen.type_def_name_imp(*def, generics, "_Vtbl"); + if has_unknown_base { + methods.combine("e! { base__: #name::new::<Identity, Impl, OFFSET>(), }); + } else { + methods.combine("e! { base__: #name::new::<Impl>(), }); + } + } + _ => {} + } + + let mut method_names = MethodNames::new(); + method_names.add_vtable_types(gen, def); + + for method in gen.reader.type_def_methods(def) { + let name = method_names.add(gen, method); + if has_unknown_base { + methods.combine("e! { #name: #name::<#generic_names Identity, Impl, OFFSET>, }); + } else { + methods.combine("e! { #name: #name::<Impl>, }); + } + } + + if has_unknown_base { + quote! { + #doc + #features + pub trait #impl_ident<#generic_names> : Sized #requires where #constraints { + #(#method_traits)* + } + #runtime_name + #features + impl<#constraints> #vtbl_ident<#generic_names> { + pub const fn new<Identity: ::windows::core::IUnknownImpl<Impl = Impl>, Impl: #impl_ident<#generic_names>, const OFFSET: isize>() -> #vtbl_ident<#generic_names> { + #(#method_impls)* + Self{ + #methods + #(#named_phantoms)* + } + } + pub fn matches(iid: &windows::core::GUID) -> bool { + #matches + } + } + } + } else { + quote! { + #doc + #features + pub trait #impl_ident : Sized #requires { + #(#method_traits)* + } + #features + impl #vtbl_ident { + pub const fn new<Impl: #impl_ident>() -> #vtbl_ident { + #(#method_impls)* + Self{ + #methods + #(#named_phantoms)* + } + } + } + #[doc(hidden)] + #features + struct #implvtbl_ident<T: #impl_ident> (::std::marker::PhantomData<T>); + #features + impl<T: #impl_ident> #implvtbl_ident<T> { + const VTABLE: #vtbl_ident = #vtbl_ident::new::<T>(); + } + #features + impl #type_ident { + pub fn new<'a, T: #impl_ident>(this: &'a T) -> ::windows::core::ScopedInterface<'a, Self> { + let this = ::windows::core::ScopedHeap { vtable: &#implvtbl_ident::<T>::VTABLE as *const _ as *const _, this: this as *const _ as *const _ }; + let this = ::std::mem::ManuallyDrop::new(::std::boxed::Box::new(this)); + unsafe { ::windows::core::ScopedInterface::new(::std::mem::transmute(&this.vtable)) } + } + } + } + } +} diff --git a/vendor/windows-bindgen/src/interfaces.rs b/vendor/windows-bindgen/src/interfaces.rs new file mode 100644 index 000000000..1643e7798 --- /dev/null +++ b/vendor/windows-bindgen/src/interfaces.rs @@ -0,0 +1,224 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.sys { + gen_sys_interface(gen, def) + } else { + gen_win_interface(gen, def) + } +} + +fn gen_sys_interface(gen: &Gen, def: TypeDef) -> TokenStream { + let name = gen.reader.type_def_name(def); + let ident = to_ident(name); + + if gen.reader.type_def_is_exclusive(def) { + quote! {} + } else { + quote! { + pub type #ident = *mut ::core::ffi::c_void; + } + } +} + +fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream { + let generics: &Vec<Type> = &gen.reader.type_def_generics(def).collect(); + let ident = gen.type_def_name(def, generics); + let is_exclusive = gen.reader.type_def_is_exclusive(def); + let phantoms = gen.generic_phantoms(generics); + let constraints = gen.generic_constraints(generics); + let cfg = gen.reader.type_def_cfg(def, &[]); + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + let interfaces = gen + .reader + .type_interfaces(&Type::TypeDef((def, generics.to_vec()))); + let vtables = gen.reader.type_def_vtables(def); + let has_unknown_base = matches!(vtables.first(), Some(Type::IUnknown)); + + let mut tokens = if is_exclusive { + quote! { #[doc(hidden)] } + } else { + quote! { #doc } + }; + + if has_unknown_base { + tokens.combine("e! { + #features + #[repr(transparent)] + pub struct #ident(::windows::core::IUnknown, #phantoms) where #constraints; + }); + } else { + tokens.combine("e! { + #features + #[repr(transparent)] + pub struct #ident(::std::ptr::NonNull<::std::ffi::c_void>); + }); + } + + if !is_exclusive { + let mut methods = quote! {}; + // We need to distinguish between public and virtual methods because some WinRT type hierarchies inherit colliding (overloaded) + // methods that must be distinguishable. + let method_names = &mut MethodNames::new(); + let virtual_names = &mut MethodNames::new(); + + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + for method in gen.reader.type_def_methods(def) { + methods.combine(&winrt_methods::gen( + gen, + def, + generics, + InterfaceKind::Default, + method, + method_names, + virtual_names, + )); + } + for interface in &interfaces { + if let Type::TypeDef((def, generics)) = &interface.ty { + for method in gen.reader.type_def_methods(*def) { + methods.combine(&winrt_methods::gen( + gen, + *def, + generics, + InterfaceKind::None, + method, + method_names, + virtual_names, + )); + } + } + } + } else { + let mut bases = vtables.len(); + for ty in &vtables { + match ty { + Type::IUnknown | Type::IInspectable => {} + Type::TypeDef((def, _)) => { + let kind = if gen.reader.type_def_type_name(*def) == TypeName::IDispatch { + InterfaceKind::None + } else { + InterfaceKind::Default + }; + for method in gen.reader.type_def_methods(*def) { + methods.combine(&com_methods::gen( + gen, + *def, + kind, + method, + method_names, + virtual_names, + bases, + )); + } + } + _ => unimplemented!(), + } + + bases -= 1; + } + for method in gen.reader.type_def_methods(def) { + methods.combine(&com_methods::gen( + gen, + def, + InterfaceKind::Default, + method, + method_names, + virtual_names, + 0, + )); + } + } + + tokens.combine("e! { + #features + impl<#constraints> #ident { + #methods + } + }); + + if !vtables.is_empty() && generics.is_empty() { + let mut hierarchy = format!("::windows::imp::interface_hierarchy!({ident}"); + let mut hierarchy_cfg = cfg.clone(); + + for ty in &vtables { + let into = gen.type_name(ty); + + write!(&mut hierarchy, ", {into}").unwrap(); + hierarchy_cfg = hierarchy_cfg.union(&gen.reader.type_cfg(ty)); + } + + hierarchy.push_str(");"); + tokens.combine(&gen.cfg_features(&hierarchy_cfg)); + tokens.push_str(&hierarchy); + } else { + for ty in &vtables { + let into = gen.type_name(ty); + let cfg = gen.cfg_features(&cfg.union(&gen.reader.type_cfg(ty))); + tokens.combine("e! { + #cfg + impl<#constraints> windows::core::CanInto<#into> for #ident {} + }); + } + } + + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + for interface in &interfaces { + let into = gen.type_name(&interface.ty); + let cfg = gen.cfg_features(&cfg.union(&gen.reader.type_cfg(&interface.ty))); + tokens.combine("e! { + #cfg + impl<#constraints> windows::core::CanTryInto<#into> for #ident {} + }); + } + } + + tokens.combine(&gen.interface_core_traits( + def, + generics, + &ident, + &constraints, + &phantoms, + &features, + )); + tokens.combine(&gen.interface_winrt_trait( + def, + generics, + &ident, + &constraints, + &phantoms, + &features, + )); + tokens.combine(&gen.async_get(def, generics, &ident, &constraints, &phantoms, &features)); + tokens.combine(&iterators::gen( + gen, + def, + generics, + &ident, + &constraints, + &phantoms, + &cfg, + )); + tokens.combine(&gen.agile(def, &ident, &constraints, &features)); + } + + tokens.combine(&gen.interface_trait( + def, + generics, + &ident, + &constraints, + &features, + has_unknown_base, + )); + tokens.combine(&gen.interface_vtbl(def, generics, &ident, &constraints, &features)); + tokens +} diff --git a/vendor/windows-bindgen/src/iterators.rs b/vendor/windows-bindgen/src/iterators.rs new file mode 100644 index 000000000..49a90adf2 --- /dev/null +++ b/vendor/windows-bindgen/src/iterators.rs @@ -0,0 +1,259 @@ +use super::*; + +pub fn gen( + gen: &Gen, + def: TypeDef, + generics: &[Type], + ident: &TokenStream, + constraints: &TokenStream, + _phantoms: &TokenStream, + cfg: &Cfg, +) -> TokenStream { + match gen.reader.type_def_type_name(def) { + // If the type is IIterator<T> then simply implement the Iterator trait over top. + TypeName::IIterator => { + return quote! { + impl<T: ::windows::core::RuntimeType> ::core::iter::Iterator for IIterator<T> { + type Item = T; + + fn next(&mut self) -> ::core::option::Option<Self::Item> { + let result = self.Current().ok(); + + if result.is_some() { + self.MoveNext().ok()?; + } + + result + } + } + }; + } + // If the type is IIterable<T> then implement the IntoIterator trait and rely on the resulting + // IIterator<T> returned by first() to implement the Iterator trait. + TypeName::IIterable => { + return quote! { + impl<T: ::windows::core::RuntimeType> ::core::iter::IntoIterator for IIterable<T> { + type Item = T; + type IntoIter = IIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + ::core::iter::IntoIterator::into_iter(&self) + } + } + impl<T: ::windows::core::RuntimeType> ::core::iter::IntoIterator for &IIterable<T> { + type Item = T; + type IntoIter = IIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + // TODO: not sure how to avoid this unwrap, although it should always succeed in practice. + self.First().unwrap() + } + } + }; + } + // If the type is IVectorView<T> then provide the VectorViewIterator fast iterator. + TypeName::IVectorView => { + return quote! { + pub struct VectorViewIterator<T: ::windows::core::RuntimeType + 'static> { + vector: ::core::option::Option<IVectorView<T>>, + current: u32, + } + + impl<T: ::windows::core::RuntimeType> VectorViewIterator<T> { + pub fn new(vector: ::core::option::Option<IVectorView<T>>) -> Self { + Self { vector, current: 0 } + } + } + + impl<T: ::windows::core::RuntimeType> ::core::iter::Iterator for VectorViewIterator<T> { + type Item = T; + + fn next(&mut self) -> ::core::option::Option<Self::Item> { + self.vector.as_ref() + .and_then(|vector| { + vector.GetAt(self.current).ok() + }) + .and_then(|result| { + self.current += 1; + Some(result) + }) + } + } + + impl<T: ::windows::core::RuntimeType> ::core::iter::IntoIterator for IVectorView<T> { + type Item = T; + type IntoIter = VectorViewIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + ::core::iter::IntoIterator::into_iter(&self) + } + } + impl<T: ::windows::core::RuntimeType> ::core::iter::IntoIterator for &IVectorView<T> { + type Item = T; + type IntoIter = VectorViewIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + // TODO: shouldn't need to clone - VectorViewIterator should hold a reference + VectorViewIterator::new(::core::option::Option::Some(::core::clone::Clone::clone(self))) + } + } + }; + } + TypeName::IVector => { + return quote! { + pub struct VectorIterator<T: ::windows::core::RuntimeType + 'static> { + vector: ::core::option::Option<IVector<T>>, + current: u32, + } + + impl<T: ::windows::core::RuntimeType> VectorIterator<T> { + pub fn new(vector: ::core::option::Option<IVector<T>>) -> Self { + Self { vector, current: 0 } + } + } + + impl<T: ::windows::core::RuntimeType> ::core::iter::Iterator for VectorIterator<T> { + type Item = T; + + fn next(&mut self) -> ::core::option::Option<Self::Item> { + self.vector.as_ref() + .and_then(|vector| { + vector.GetAt(self.current).ok() + }) + .and_then(|result| { + self.current += 1; + Some(result) + }) + } + } + + impl<T: ::windows::core::RuntimeType> ::core::iter::IntoIterator for IVector<T> { + type Item = T; + type IntoIter = VectorIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + ::core::iter::IntoIterator::into_iter(&self) + } + } + impl<T: ::windows::core::RuntimeType> ::core::iter::IntoIterator for &IVector<T> { + type Item = T; + type IntoIter = VectorIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + // TODO: shouldn't need to clone - VectorIterator should hold a reference + VectorIterator::new(::core::option::Option::Some(::core::clone::Clone::clone(self))) + } + } + }; + } + _ => {} + } + + let wfc = gen.namespace("Windows.Foundation.Collections"); + let mut iterable = None; + let interfaces = gen + .reader + .type_interfaces(&Type::TypeDef((def, generics.to_vec()))); + + // If the class or interface is not one of the well-known collection interfaces, we then see whether it + // implements any one of them. Here is where we favor IVectorView/IVector over IIterable. + for interface in interfaces { + if let Type::TypeDef((interface, interface_generics)) = &interface.ty { + match gen.reader.type_def_type_name(*interface) { + TypeName::IVectorView => { + let item = gen.type_name(&interface_generics[0]); + let mut cfg = cfg.clone(); + gen.reader + .type_def_cfg_combine(*interface, interface_generics, &mut cfg); + let features = gen.cfg_features(&cfg); + + return quote! { + #features + impl<#constraints> ::core::iter::IntoIterator for #ident { + type Item = #item; + type IntoIter = #wfc VectorViewIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + ::core::iter::IntoIterator::into_iter(&self) + } + } + #features + impl<#constraints> ::core::iter::IntoIterator for &#ident { + type Item = #item; + type IntoIter = #wfc VectorViewIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + #wfc VectorViewIterator::new(::windows::core::ComInterface::cast(self).ok()) + } + } + }; + } + TypeName::IVector => { + let item = gen.type_name(&interface_generics[0]); + let mut cfg = cfg.clone(); + gen.reader + .type_def_cfg_combine(*interface, interface_generics, &mut cfg); + let features = gen.cfg_features(&cfg); + + return quote! { + #features + impl<#constraints> ::core::iter::IntoIterator for #ident { + type Item = #item; + type IntoIter = #wfc VectorIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + ::core::iter::IntoIterator::into_iter(&self) + } + } + #features + impl<#constraints> ::core::iter::IntoIterator for &#ident { + type Item = #item; + type IntoIter = #wfc VectorIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + #wfc VectorIterator::new(::windows::core::ComInterface::cast(self).ok()) + } + } + }; + } + TypeName::IIterable => { + iterable = Some((*interface, interface_generics.to_vec())); + } + _ => {} + } + } + } + + match iterable { + None => TokenStream::new(), + Some((interface, interface_generics)) => { + let item = gen.type_name(&interface_generics[0]); + let mut cfg = cfg.clone(); + gen.reader + .type_def_cfg_combine(interface, &interface_generics, &mut cfg); + let features = gen.cfg_features(&cfg); + + quote! { + #features + impl<#constraints> ::core::iter::IntoIterator for #ident { + type Item = #item; + type IntoIter = #wfc IIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + ::core::iter::IntoIterator::into_iter(&self) + } + } + #features + impl<#constraints> ::core::iter::IntoIterator for &#ident { + type Item = #item; + type IntoIter = #wfc IIterator<Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + // TODO: not sure how to avoid this unwrap, although it should always succeed in practice. + self.First().unwrap() + } + } + } + } + } +} diff --git a/vendor/windows-bindgen/src/lib.rs b/vendor/windows-bindgen/src/lib.rs new file mode 100644 index 000000000..0957a4f64 --- /dev/null +++ b/vendor/windows-bindgen/src/lib.rs @@ -0,0 +1,225 @@ +/*! +Learn more about Rust for Windows here: <https://github.com/microsoft/windows-rs> +*/ + +mod classes; +mod com_methods; +mod constants; +mod delegates; +mod enums; +mod extensions; +mod functions; +mod gen; +mod handles; +mod implements; +mod interfaces; +mod iterators; +mod method_names; +mod standalone; +mod structs; +mod try_format; +mod winrt_methods; + +use metadata::reader::*; +use method_names::*; +pub use standalone::*; +use std::collections::*; +use std::fmt::Write; +use tokens::*; +use try_format::*; + +#[doc(hidden)] +pub use gen::*; + +#[doc(hidden)] +pub fn namespace(gen: &Gen, tree: &Tree) -> String { + let mut tokens = TokenStream::new(); + + if tree.namespace == "Windows" || !tree.namespace.starts_with("Windows.") { + tokens.combine(&allow()); + } + + for (name, tree) in &tree.nested { + let name = to_ident(name); + let namespace = tree.namespace[tree.namespace.find('.').unwrap() + 1..].replace('.', "_"); + if !gen.component { + tokens.combine("e! { #[cfg(feature = #namespace)] }); + } + tokens.combine("e! { pub mod #name; }); + } + + let mut functions = BTreeMap::<&str, TokenStream>::new(); + let mut types = BTreeMap::<TypeKind, BTreeMap<&str, TokenStream>>::new(); + + for method in gen.reader.namespace_functions(tree.namespace) { + let name = gen.reader.method_def_name(method); + functions + .entry(name) + .or_default() + .combine(&functions::gen(gen, method)); + } + + for field in gen.reader.namespace_constants(tree.namespace) { + let name = gen.reader.field_name(field); + types + .entry(TypeKind::Class) + .or_default() + .entry(name) + .or_default() + .combine(&constants::gen(gen, field)); + } + + for def in gen + .reader + .namespace_types(tree.namespace, &Default::default()) + { + let type_name = gen.reader.type_def_type_name(def); + if REMAP_TYPES.iter().any(|(x, _)| x == &type_name) { + continue; + } + if CORE_TYPES.iter().any(|(x, _)| x == &type_name) { + continue; + } + let name = type_name.name; + let kind = gen.reader.type_def_kind(def); + match kind { + TypeKind::Class => { + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + types + .entry(kind) + .or_default() + .insert(name, classes::gen(gen, def)); + } + } + TypeKind::Interface => types + .entry(kind) + .or_default() + .entry(name) + .or_default() + .combine(&interfaces::gen(gen, def)), + TypeKind::Enum => types + .entry(kind) + .or_default() + .entry(name) + .or_default() + .combine(&enums::gen(gen, def)), + TypeKind::Struct => { + if gen.reader.type_def_fields(def).next().is_none() { + if let Some(guid) = gen.reader.type_def_guid(def) { + let ident = to_ident(name); + let value = gen.guid(&guid); + let guid = gen.type_name(&Type::GUID); + let cfg = gen.reader.type_def_cfg(def, &[]); + let doc = gen.cfg_doc(&cfg); + let constant = quote! { + #doc + pub const #ident: #guid = #value; + }; + types + .entry(TypeKind::Class) + .or_default() + .entry(name) + .or_default() + .combine(&constant); + continue; + } + } + types + .entry(kind) + .or_default() + .entry(name) + .or_default() + .combine(&structs::gen(gen, def)); + } + TypeKind::Delegate => types + .entry(kind) + .or_default() + .entry(name) + .or_default() + .combine(&delegates::gen(gen, def)), + } + } + + for function in functions.values() { + tokens.combine(function); + } + + for ty in types.values().flat_map(|v| v.values()) { + tokens.combine(ty); + } + + tokens.combine(&extensions::gen_mod(gen, tree.namespace)); + try_format(tokens.into_string()) +} + +#[doc(hidden)] +pub fn namespace_impl(gen: &Gen, tree: &Tree) -> String { + let mut types = BTreeMap::<&str, TokenStream>::new(); + + for def in gen + .reader + .namespace_types(tree.namespace, &Default::default()) + { + let type_name = gen.reader.type_def_type_name(def); + if CORE_TYPES.iter().any(|(x, _)| x == &type_name) { + continue; + } + if gen.reader.type_def_kind(def) != TypeKind::Interface { + continue; + } + let tokens = implements::gen(gen, def); + + if !tokens.is_empty() { + types.insert(type_name.name, tokens); + } + } + + let types = types.values(); + + let mut tokens = quote! { + #(#types)* + }; + + tokens.combine(&extensions::gen_impl(tree.namespace)); + try_format(tokens.into_string()) +} + +/// Generates bindings for a specific component namespace. +pub fn component(namespace: &str, files: &[File]) -> String { + let reader = &Reader::new(files); + let tree = reader.tree(namespace, &Default::default()); + let mut gen = Gen::new(reader); + gen.namespace = tree.namespace; + gen.component = true; + let mut bindings = crate::namespace(&gen, &tree); + bindings.push_str(&namespace_impl(&gen, &tree)); + try_format(bindings) +} + +fn allow() -> TokenStream { + quote! { + #![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] + } +} + +/// Expand a possibly empty generics list with a new generic +fn expand_generics(generics: TokenStream, new: TokenStream) -> TokenStream { + if generics.is_empty() { + quote!(#new) + } else { + quote!(#generics, #new) + } +} + +/// Expand a possibly emppty where clause with a new generic constraint +fn expand_where_clause(where_clause: TokenStream, generic: TokenStream) -> TokenStream { + if where_clause.is_empty() { + quote!(where #generic) + } else { + quote!(#where_clause #generic) + } +} diff --git a/vendor/windows-bindgen/src/method_names.rs b/vendor/windows-bindgen/src/method_names.rs new file mode 100644 index 000000000..9f5dad1c6 --- /dev/null +++ b/vendor/windows-bindgen/src/method_names.rs @@ -0,0 +1,30 @@ +use super::*; + +pub struct MethodNames(BTreeMap<String, u32>); + +impl MethodNames { + pub fn new() -> Self { + Self(BTreeMap::new()) + } + + pub fn add(&mut self, gen: &Gen, method: MethodDef) -> TokenStream { + let name = gen.reader.method_def_special_name(method); + let overload = self.0.entry(name.to_string()).or_insert(0); + *overload += 1; + if *overload > 1 { + format!("{name}{overload}").into() + } else { + to_ident(&name) + } + } + + pub fn add_vtable_types(&mut self, gen: &Gen, def: TypeDef) { + for def in gen.reader.type_def_vtables(def) { + if let Type::TypeDef((def, _)) = def { + for method in gen.reader.type_def_methods(def) { + self.add(gen, method); + } + } + } + } +} diff --git a/vendor/windows-bindgen/src/standalone.rs b/vendor/windows-bindgen/src/standalone.rs new file mode 100644 index 000000000..e8db2fca7 --- /dev/null +++ b/vendor/windows-bindgen/src/standalone.rs @@ -0,0 +1,266 @@ +use super::*; + +/// Generates standalone Windows bindings. +pub fn standalone(names: &[&str]) -> String { + let files = &File::with_default(&[]).unwrap(); + let reader = &Reader::new(files); + let gen = &mut Gen::new(reader); + standalone_imp(gen, names) +} + +/// Generates standalone Windows bindings for the Rust Standard Library. +pub fn standalone_std(names: &[&str]) -> String { + let files = &File::with_default(&[]).unwrap(); + let reader = &Reader::new(files); + let gen = &mut Gen::new(reader); + gen.std = true; + standalone_imp(gen, names) +} + +fn standalone_imp(gen: &mut Gen, names: &[&str]) -> String { + gen.namespace = "Windows."; + gen.standalone = true; + gen.sys = true; + + let mut type_names = BTreeSet::new(); + let mut core_types = BTreeSet::new(); + let mut enums = BTreeSet::new(); + + for name in names { + let type_name = TypeName::parse(name); + let mut found = false; + + if let Some(def) = gen.reader.get(type_name).next() { + found = true; + type_names.insert(type_name); + let mut cfg = gen.reader.type_def_cfg(def, &[]); + core_types.append(&mut cfg.core_types); + for def in cfg.types.values().flatten() { + type_names.insert(gen.reader.type_def_type_name(*def)); + } + if gen.reader.type_def_kind(def) == TypeKind::Struct + && gen.reader.type_def_fields(def).next().is_none() + && gen.reader.type_def_guid(def).is_some() + { + core_types.insert(Type::GUID); + } + } + + if !found { + for method in gen.reader.namespace_functions(type_name.namespace) { + if found { + break; + } + let name = gen.reader.method_def_name(method); + if name == type_name.name { + found = true; + type_names.insert(type_name); + let mut cfg = gen + .reader + .signature_cfg(&gen.reader.method_def_signature(method, &[])); + core_types.append(&mut cfg.core_types); + for def in cfg.types.values().flatten() { + type_names.insert(gen.reader.type_def_type_name(*def)); + } + } + } + for field in gen.reader.namespace_constants(type_name.namespace) { + if found { + break; + } + let name = gen.reader.field_name(field); + if name == type_name.name { + found = true; + type_names.insert(type_name); + let mut cfg = gen.reader.field_cfg(field); + core_types.append(&mut cfg.core_types); + for def in cfg.types.values().flatten() { + type_names.insert(gen.reader.type_def_type_name(*def)); + } + } + } + } + + if !found { + for def in gen + .reader + .namespace_types(type_name.namespace, &Default::default()) + { + if found { + break; + } + if gen.reader.type_def_kind(def) == TypeKind::Enum { + for field in gen.reader.type_def_fields(def) { + if found { + break; + } + let name = gen.reader.field_name(field); + if name == type_name.name { + found = true; + let enum_name = gen.reader.type_def_type_name(def); + type_names.insert(enum_name); + enums.insert((enum_name, type_name.name)); + } + } + } + } + } + } + + let mut sorted = SortedTokens::default(); + + for ty in core_types { + match ty { + Type::HRESULT => sorted.insert("HRESULT", quote! { pub type HRESULT = i32; }), + Type::String => sorted.insert( + "HSTRING", + quote! { pub type HSTRING = *mut ::core::ffi::c_void; }, + ), + Type::IUnknown => sorted.insert( + "IUnknown", + quote! { pub type IUnknown = *mut ::core::ffi::c_void; }, + ), + Type::IInspectable => sorted.insert( + "IInspectable", + quote! { pub type IInspectable = *mut ::core::ffi::c_void; }, + ), + Type::PSTR => sorted.insert("PSTR", quote! { pub type PSTR = *mut u8; }), + Type::PWSTR => sorted.insert("PWSTR", quote! { pub type PWSTR = *mut u16; }), + Type::PCSTR => sorted.insert("PCSTR", quote! { pub type PCSTR = *const u8; }), + Type::PCWSTR => sorted.insert("PCWSTR", quote! { pub type PCWSTR = *const u16; }), + Type::BSTR => sorted.insert("BSTR", quote! { pub type BSTR = *const u16; }), + Type::GUID => { + sorted.insert("GUID", quote! { + #[repr(C)] + pub struct GUID { + pub data1: u32, + pub data2: u16, + pub data3: u16, + pub data4: [u8; 8], + } + impl GUID { + pub const fn from_u128(uuid: u128) -> Self { + Self { data1: (uuid >> 96) as u32, data2: (uuid >> 80 & 0xffff) as u16, data3: (uuid >> 64 & 0xffff) as u16, data4: (uuid as u64).to_be_bytes() } + } + } + impl ::core::marker::Copy for GUID {} + impl ::core::clone::Clone for GUID { + fn clone(&self) -> Self { + *self + } + } + }); + } + _ => {} + } + } + + for type_name in type_names { + let mut found = false; + + for def in gen.reader.get(type_name) { + found = true; + let kind = gen.reader.type_def_kind(def); + + match kind { + TypeKind::Class | TypeKind::Interface => unimplemented!(), + TypeKind::Enum => { + sorted.insert(gen.reader.type_def_name(def), enums::gen(gen, def)); + } + TypeKind::Struct => { + if gen.reader.type_def_fields(def).next().is_none() { + if let Some(guid) = gen.reader.type_def_guid(def) { + let ident = to_ident(type_name.name); + let value = gen.guid(&guid); + let guid = gen.type_name(&Type::GUID); + sorted.insert( + type_name.name, + quote! { + pub const #ident: #guid = #value; + }, + ); + continue; + } + } + sorted.insert(gen.reader.type_def_name(def), structs::gen(gen, def)); + } + TypeKind::Delegate => { + sorted.insert(gen.reader.type_def_name(def), delegates::gen(gen, def)); + } + } + } + + if !found { + for method in gen.reader.namespace_functions(type_name.namespace) { + if found { + break; + } + let name = gen.reader.method_def_name(method); + if name == type_name.name { + found = true; + sorted.insert( + &format!(".{}.{name}", gen.reader.method_def_module_name(method)), + functions::gen(gen, method), + ); + } + } + for field in gen.reader.namespace_constants(type_name.namespace) { + if found { + break; + } + let name = gen.reader.field_name(field); + if name == type_name.name { + found = true; + sorted.insert(name, constants::gen(gen, field)); + } + } + } + } + + for (enum_type, field_name) in enums { + if let Some(def) = gen.reader.get(enum_type).next() { + for field in gen.reader.type_def_fields(def) { + if gen.reader.field_name(field) == field_name { + let ident = to_ident(field_name); + let ty = to_ident(enum_type.name); + let constant = gen.reader.field_constant(field).unwrap(); + let value = gen.value(&gen.reader.constant_value(constant)); + + sorted.insert( + field_name, + quote! { + pub const #ident: #ty = #value; + }, + ); + + break; + } + } + } + } + + let mut tokens: TokenStream = format!( + r#"// Bindings generated by `windows-bindgen` {} + +"#, + std::env!("CARGO_PKG_VERSION") + ) + .into(); + + tokens.combine(&allow()); + + for value in sorted.0.values() { + tokens.combine(value); + } + + try_format(tokens.into_string()) +} + +#[derive(Default)] +struct SortedTokens(BTreeMap<String, TokenStream>); + +impl SortedTokens { + fn insert(&mut self, key: &str, tokens: TokenStream) { + self.0.entry(key.to_string()).or_default().combine(&tokens); + } +} diff --git a/vendor/windows-bindgen/src/structs.rs b/vendor/windows-bindgen/src/structs.rs new file mode 100644 index 000000000..89670bdb5 --- /dev/null +++ b/vendor/windows-bindgen/src/structs.rs @@ -0,0 +1,316 @@ +use super::*; + +pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { + if gen.reader.type_def_is_contract(def) { + return quote! {}; + } + + if gen.reader.type_def_is_handle(def) { + return handles::gen(gen, def); + } + + gen_struct_with_name(gen, def, gen.reader.type_def_name(def), &Cfg::default()) +} + +fn gen_struct_with_name(gen: &Gen, def: TypeDef, struct_name: &str, cfg: &Cfg) -> TokenStream { + let name = to_ident(struct_name); + + if gen.reader.type_def_fields(def).next().is_none() { + let mut tokens = quote! { + #[repr(C)] + pub struct #name(pub u8); + impl ::core::marker::Copy for #name {} + impl ::core::clone::Clone for #name { + fn clone(&self) -> Self { + *self + } + } + }; + if !gen.sys { + tokens.combine("e! { + impl ::windows::core::TypeKind for #name { + type TypeKind = ::windows::core::CopyType; + } + }); + } + return tokens; + } + + let flags = gen.reader.type_def_flags(def); + let cfg = cfg.union(&gen.reader.type_def_cfg(def, &[])); + + let repr = if let Some(layout) = gen.reader.type_def_class_layout(def) { + let packing = Literal::usize_unsuffixed(gen.reader.class_layout_packing_size(layout)); + quote! { #[repr(C, packed(#packing))] } + } else { + quote! { #[repr(C)] } + }; + + let fields = gen.reader.type_def_fields(def).map(|f| { + let name = to_ident(gen.reader.field_name(f)); + let ty = gen.reader.field_type(f, Some(def)); + + if gen.reader.field_flags(f).contains(FieldAttributes::LITERAL) { + quote! {} + } else if !gen.sys + && flags.contains(TypeAttributes::EXPLICIT_LAYOUT) + && !gen.reader.field_is_copyable(f, def) + { + // Rust can't tell that the type is copyable and won't accept windows::core::ManuallyDrop + let ty = gen.type_default_name(&ty); + quote! { pub #name: ::std::mem::ManuallyDrop<#ty>, } + } else if !gen.sys + && !flags.contains(TypeAttributes::WINRT) + && !gen.reader.field_is_blittable(f, def) + { + if let Type::Win32Array((ty, len)) = ty { + let ty = gen.type_default_name(&ty); + quote! { pub #name: [::std::mem::ManuallyDrop<#ty>; #len], } + } else { + let ty = gen.type_default_name(&ty); + quote! { pub #name: ::std::mem::ManuallyDrop<#ty>, } + } + } else { + let ty = gen.type_default_name(&ty); + quote! { pub #name: #ty, } + } + }); + + let struct_or_union = if flags.contains(TypeAttributes::EXPLICIT_LAYOUT) { + quote! { union } + } else { + quote! { struct } + }; + + let doc = gen.cfg_doc(&cfg); + let features = gen.cfg_features(&cfg); + + let mut tokens = quote! { + #repr + #doc + #features + pub #struct_or_union #name {#(#fields)*} + }; + + tokens.combine(&gen_struct_constants(gen, def, &name, &cfg)); + tokens.combine(&gen_copy_clone(gen, def, &name, &cfg)); + tokens.combine(&gen_debug(gen, def, &name, &cfg)); + tokens.combine(&gen_windows_traits(gen, def, &name, &cfg)); + tokens.combine(&gen_compare_traits(gen, def, &name, &cfg)); + + if !gen.sys { + tokens.combine("e! { + #features + impl ::core::default::Default for #name { + fn default() -> Self { + unsafe { ::core::mem::zeroed() } + } + } + }); + } + + for (index, nested_type) in gen.reader.nested_types(def).enumerate() { + let nested_name = format!("{struct_name}_{index}"); + tokens.combine(&gen_struct_with_name(gen, nested_type, &nested_name, &cfg)); + } + + tokens +} + +fn gen_windows_traits(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { + if gen.sys { + quote! {} + } else { + let features = gen.cfg_features(cfg); + let is_copy = gen.reader.type_def_is_blittable(def); + + let type_kind = if is_copy { + quote! { CopyType } + } else { + quote! { ValueType } + }; + + let mut tokens = quote! { + #features + impl ::windows::core::TypeKind for #name { + type TypeKind = ::windows::core::#type_kind; + } + }; + + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + let signature = + Literal::byte_string(gen.reader.type_def_signature(def, &[]).as_bytes()); + + tokens.combine("e! { + #features + impl ::windows::core::RuntimeType for #name { + const SIGNATURE: ::windows::imp::ConstBuffer = ::windows::imp::ConstBuffer::from_slice(#signature); + } + }); + } + + tokens + } +} + +fn gen_compare_traits(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { + let features = gen.cfg_features(cfg); + + if gen.sys + || gen.reader.type_def_has_explicit_layout(def) + || gen.reader.type_def_has_packing(def) + || gen.reader.type_def_has_callback(def) + { + quote! {} + } else { + let fields = gen.reader.type_def_fields(def).filter_map(|f| { + let name = to_ident(gen.reader.field_name(f)); + if gen.reader.field_flags(f).contains(FieldAttributes::LITERAL) { + None + } else { + Some(quote! { self.#name == other.#name }) + } + }); + + quote! { + #features + impl ::core::cmp::PartialEq for #name { + fn eq(&self, other: &Self) -> bool { + #(#fields)&&* + } + } + #features + impl ::core::cmp::Eq for #name {} + } + } +} + +fn gen_debug(gen: &Gen, def: TypeDef, ident: &TokenStream, cfg: &Cfg) -> TokenStream { + if gen.sys + || gen.reader.type_def_has_explicit_layout(def) + || gen.reader.type_def_has_packing(def) + { + quote! {} + } else { + let name = ident.as_str(); + let features = gen.cfg_features(cfg); + + let fields = gen.reader.type_def_fields(def).filter_map(|f| { + if gen.reader.field_flags(f).contains(FieldAttributes::LITERAL) { + None + } else { + let name = gen.reader.field_name(f); + let ident = to_ident(name); + let ty = gen.reader.field_type(f, Some(def)); + if gen.reader.type_has_callback(&ty) { + None + } else { + Some(quote! { .field(#name, &self.#ident) }) + } + } + }); + + quote! { + #features + impl ::core::fmt::Debug for #ident { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_struct(#name) #(#fields)* .finish() + } + } + } + } +} + +fn gen_copy_clone(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { + let features = gen.cfg_features(cfg); + + if gen.sys || gen.reader.type_def_is_copyable(def) { + quote! { + #features + impl ::core::marker::Copy for #name {} + #features + impl ::core::clone::Clone for #name { + fn clone(&self) -> Self { + *self + } + } + } + } else if gen.reader.type_def_class_layout(def).is_some() { + // Don't support copy/clone of packed structs: https://github.com/rust-lang/rust/issues/82523 + quote! {} + } else if !gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + quote! { + #features + impl ::core::clone::Clone for #name { + fn clone(&self) -> Self { + unsafe { ::core::mem::transmute_copy(self) } + } + } + } + } else { + let fields = gen.reader.type_def_fields(def).map(|f| { + let name = to_ident(gen.reader.field_name(f)); + if gen.reader.field_flags(f).contains(FieldAttributes::LITERAL) { + quote! {} + } else if gen.reader.field_is_blittable(f, def) { + quote! { #name: self.#name } + } else { + quote! { #name: self.#name.clone() } + } + }); + + quote! { + #features + impl ::core::clone::Clone for #name { + fn clone(&self) -> Self { + Self { #(#fields),* } + } + } + } + } +} + +fn gen_struct_constants( + gen: &Gen, + def: TypeDef, + struct_name: &TokenStream, + cfg: &Cfg, +) -> TokenStream { + let features = gen.cfg_features(cfg); + + let constants = gen.reader.type_def_fields(def).filter_map(|f| { + if gen.reader.field_flags(f).contains(FieldAttributes::LITERAL) { + if let Some(constant) = gen.reader.field_constant(f) { + let name = to_ident(gen.reader.field_name(f)); + let value = gen.typed_value(&gen.reader.constant_value(constant)); + + return Some(quote! { + pub const #name: #value; + }); + } + } + + None + }); + + let mut tokens = quote! { #(#constants)* }; + + if !tokens.is_empty() { + tokens = quote! { + #features + impl #struct_name { + #tokens + } + }; + } + + tokens +} diff --git a/vendor/windows-bindgen/src/try_format.rs b/vendor/windows-bindgen/src/try_format.rs new file mode 100644 index 000000000..493a8a842 --- /dev/null +++ b/vendor/windows-bindgen/src/try_format.rs @@ -0,0 +1,31 @@ +pub fn try_format(tokens: String) -> String { + use std::io::Write; + + let Ok(mut child) = std::process::Command::new("rustfmt").stdin(std::process::Stdio::piped()).stdout(std::process::Stdio::piped()).stderr(std::process::Stdio::null()).spawn() else { + return tokens; + }; + + let Some(mut stdin) = child.stdin.take() else { + return tokens; + }; + + if stdin.write_all(tokens.as_bytes()).is_err() { + return tokens; + } + + drop(stdin); + + let Ok(output) = child.wait_with_output() else { + return tokens; + }; + + if !output.status.success() { + return tokens; + } + + if let Ok(result) = String::from_utf8(output.stdout) { + result + } else { + tokens + } +} diff --git a/vendor/windows-bindgen/src/winrt_methods.rs b/vendor/windows-bindgen/src/winrt_methods.rs new file mode 100644 index 000000000..457f70c38 --- /dev/null +++ b/vendor/windows-bindgen/src/winrt_methods.rs @@ -0,0 +1,258 @@ +use super::*; + +// TODO take Signature instead of MethodDef (wherever MethodDef is found) +pub fn gen( + gen: &Gen, + def: TypeDef, + generic_types: &[Type], + kind: InterfaceKind, + method: MethodDef, + method_names: &mut MethodNames, + virtual_names: &mut MethodNames, +) -> TokenStream { + let signature = gen.reader.method_def_signature(method, generic_types); + let params = &signature.params; + let name = method_names.add(gen, method); + let interface_name = gen.type_def_name(def, generic_types); + let vname = virtual_names.add(gen, method); + let generics = gen.constraint_generics(params); + let where_clause = gen.where_clause(params); + let mut cfg = gen.reader.signature_cfg(&signature); + gen.reader + .type_def_cfg_combine(def, generic_types, &mut cfg); + let doc = gen.cfg_method_doc(&cfg); + let features = gen.cfg_features(&cfg); + let args = gen_winrt_abi_args(gen, params); + let params = gen_winrt_params(gen, params); + + let return_type_tokens = if let Some(return_type) = &signature.return_type { + let tokens = gen.type_name(return_type); + if return_type.is_winrt_array() { + quote! { ::windows::core::Array<#tokens> } + } else { + quote! { #tokens } + } + } else { + quote! { () } + }; + + let return_arg = if let Some(return_type) = &signature.return_type { + if return_type.is_winrt_array() { + let return_type = gen.type_name(return_type); + quote! { ::windows::core::Array::<#return_type>::set_abi_len(::std::mem::transmute(&mut result__)), result__.as_mut_ptr() as *mut _ as _ } + } else { + quote! { &mut result__ } + } + } else { + quote! {} + }; + + let vcall = if let Some(return_type) = &signature.return_type { + if return_type.is_winrt_array() { + quote! { + let mut result__ = ::core::mem::MaybeUninit::zeroed(); + (::windows::core::Interface::vtable(this).#vname)(::windows::core::Interface::as_raw(this), #args #return_arg) + .and_then(|| result__.assume_init()) + } + } else { + let return_type = gen.type_name(return_type); + quote! { + let mut result__ = ::windows::core::zeroed::<#return_type>(); + (::windows::core::Interface::vtable(this).#vname)(::windows::core::Interface::as_raw(this), #args #return_arg) + .from_abi(result__) + } + } + } else { + quote! { + (::windows::core::Interface::vtable(this).#vname)(::windows::core::Interface::as_raw(this), #args).ok() + } + }; + + match kind { + InterfaceKind::Default => quote! { + #doc + #features + pub fn #name<#generics>(&self, #params) -> ::windows::core::Result<#return_type_tokens> #where_clause { + let this = self; + unsafe { + #vcall + } + } + }, + InterfaceKind::None | InterfaceKind::Base | InterfaceKind::Overridable => { + quote! { + #doc + #features + pub fn #name<#generics>(&self, #params) -> ::windows::core::Result<#return_type_tokens> #where_clause { + let this = &::windows::core::ComInterface::cast::<#interface_name>(self)?; + unsafe { + #vcall + } + } + } + } + InterfaceKind::Static => { + quote! { + #doc + #features + pub fn #name<#generics>(#params) -> ::windows::core::Result<#return_type_tokens> #where_clause { + Self::#interface_name(|this| unsafe { #vcall }) + } + } + } + } +} + +fn gen_winrt_params(gen: &Gen, params: &[SignatureParam]) -> TokenStream { + let mut result = quote! {}; + + let mut generic_params = gen.generic_params(params); + for param in params.iter() { + let name = gen.param_name(param.def); + let kind = gen.type_name(¶m.ty); + let default_type = gen.type_default_name(¶m.ty); + + if gen + .reader + .param_flags(param.def) + .contains(ParamAttributes::INPUT) + { + if param.ty.is_winrt_array() { + result.combine("e! { #name: &[#default_type], }); + } else if gen.reader.signature_param_is_convertible(param) { + let (position, _) = generic_params.next().unwrap(); + let kind: TokenStream = format!("P{position}").into(); + result.combine("e! { #name: #kind, }); + } else if gen.reader.type_is_blittable(¶m.ty) { + result.combine("e! { #name: #kind, }); + } else { + result.combine("e! { #name: &#kind, }); + } + } else if param.ty.is_winrt_array() { + result.combine("e! { #name: &mut [#default_type], }); + } else if param.ty.is_winrt_array_ref() { + result.combine("e! { #name: &mut ::windows::core::Array<#kind>, }); + } else { + result.combine("e! { #name: &mut #default_type, }); + } + } + + result +} + +fn gen_winrt_abi_args(gen: &Gen, params: &[SignatureParam]) -> TokenStream { + let mut tokens = TokenStream::new(); + for param in params { + let name = gen.param_name(param.def); + + let param = if gen + .reader + .param_flags(param.def) + .contains(ParamAttributes::INPUT) + { + if param.ty.is_winrt_array() { + if gen.reader.type_is_blittable(¶m.ty) { + quote! { #name.len() as u32, #name.as_ptr(), } + } else { + quote! { #name.len() as u32, ::core::mem::transmute(#name.as_ptr()), } + } + } else if gen.reader.signature_param_is_failible_param(param) { + quote! { #name.try_into_param()?.abi(), } + } else if gen.reader.signature_param_is_borrowed(param) { + quote! { #name.into_param().abi(), } + } else if gen.reader.type_is_blittable(¶m.ty) { + if param.ty.is_winrt_const_ref() { + quote! { &#name, } + } else { + quote! { #name, } + } + } else { + quote! { ::core::mem::transmute_copy(#name), } + } + } else if param.ty.is_winrt_array() { + if gen.reader.type_is_blittable(¶m.ty) { + quote! { #name.len() as u32, #name.as_mut_ptr(), } + } else { + quote! { #name.len() as u32, ::core::mem::transmute_copy(&#name), } + } + } else if param.ty.is_winrt_array_ref() { + quote! { #name.set_abi_len(), #name as *mut _ as _, } + } else if gen.reader.type_is_blittable(¶m.ty) { + quote! { #name, } + } else { + quote! { #name as *mut _ as _, } + }; + tokens.combine(¶m); + } + tokens +} + +pub fn gen_upcall(gen: &Gen, sig: &Signature, inner: TokenStream) -> TokenStream { + let invoke_args = sig + .params + .iter() + .map(|param| gen_winrt_invoke_arg(gen, param)); + + match &sig.return_type { + Some(return_type) if return_type.is_winrt_array() => { + quote! { + match #inner(#(#invoke_args,)*) { + ::core::result::Result::Ok(ok__) => { + let (ok_data__, ok_data_len__) = ok__.into_abi(); + // use `core::ptr::write` since `result` could be uninitialized + ::core::ptr::write(result__, ok_data__); + ::core::ptr::write(result_size__, ok_data_len__); + ::windows::core::HRESULT(0) + } + ::core::result::Result::Err(err) => err.into() + } + } + } + Some(_) => { + quote! { + match #inner(#(#invoke_args,)*) { + ::core::result::Result::Ok(ok__) => { + // use `core::ptr::write` since `result` could be uninitialized + ::core::ptr::write(result__, ::core::mem::transmute_copy(&ok__)); + ::core::mem::forget(ok__); + ::windows::core::HRESULT(0) + } + ::core::result::Result::Err(err) => err.into() + } + } + } + None => quote! { + #inner(#(#invoke_args,)*).into() + }, + } +} + +fn gen_winrt_invoke_arg(gen: &Gen, param: &SignatureParam) -> TokenStream { + let name = gen.param_name(param.def); + let abi_size_name: TokenStream = + format!("{}_array_size", gen.reader.param_name(param.def)).into(); + + if gen + .reader + .param_flags(param.def) + .contains(ParamAttributes::INPUT) + { + if param.ty.is_winrt_array() { + quote! { ::core::slice::from_raw_parts(::core::mem::transmute_copy(&#name), #abi_size_name as _) } + } else if gen.reader.type_is_primitive(¶m.ty) { + quote! { #name } + } else if param.ty.is_winrt_const_ref() { + quote! { ::core::mem::transmute_copy(&#name) } + } else if gen.reader.type_is_nullable(¶m.ty) { + quote! { ::windows::core::from_raw_borrowed(&#name) } + } else { + quote! { ::core::mem::transmute(&#name) } + } + } else if param.ty.is_winrt_array() { + quote! { ::core::slice::from_raw_parts_mut(::core::mem::transmute_copy(&#name), #abi_size_name as _) } + } else if param.ty.is_winrt_array_ref() { + quote! { ::windows::core::ArrayProxy::from_raw_parts(::core::mem::transmute_copy(&#name), #abi_size_name).as_array() } + } else { + quote! { ::core::mem::transmute_copy(&#name) } + } +} |