diff --git a/crates/libs/metadata/src/lib.rs b/crates/libs/metadata/src/lib.rs index f6110e41e7..07a7440d6b 100644 --- a/crates/libs/metadata/src/lib.rs +++ b/crates/libs/metadata/src/lib.rs @@ -419,6 +419,7 @@ impl<'a> Reader<'a> { pub fn field_is_const(&self, row: Field) -> bool { self.field_attributes(row).any(|attribute| self.attribute_name(attribute) == "ConstAttribute") } + // TODO: enclosing craziness is only needed for nested structs - get rid of those in metadata vnext and this goes away. pub fn field_type(&self, row: Field, enclosing: Option) -> Type { let mut blob = self.row_blob(row.0, 2); blob.read_usize(); @@ -880,8 +881,8 @@ impl<'a> Reader<'a> { pub fn type_def_attributes(&self, row: TypeDef) -> impl Iterator { self.row_attributes(row.0, HasAttribute::TypeDef(row)) } - pub fn type_def_generics(&self, row: TypeDef) -> impl Iterator { - self.row_equal_range(row.0, TABLE_GENERICPARAM, 2, TypeOrMethodDef::TypeDef(row).encode()).map(|row| Type::GenericParam(GenericParam(row))) + pub fn type_def_generics(&self, row: TypeDef) -> Vec { + self.row_equal_range(row.0, TABLE_GENERICPARAM, 2, TypeOrMethodDef::TypeDef(row).encode()).map(|row| Type::GenericParam(GenericParam(row))).collect() } pub fn type_def_interface_impls(&self, row: TypeDef) -> impl Iterator { self.row_equal_range(row.0, TABLE_INTERFACEIMPL, 0, (row.0.row + 1) as _).map(InterfaceImpl) diff --git a/crates/targets/aarch64_msvc/lib/windows.0.48.0.lib b/crates/targets/aarch64_msvc/lib/windows.0.48.0.lib index 564b80f277..02a9d98b14 100644 Binary files a/crates/targets/aarch64_msvc/lib/windows.0.48.0.lib and b/crates/targets/aarch64_msvc/lib/windows.0.48.0.lib differ diff --git a/crates/targets/i686_msvc/lib/windows.0.48.0.lib b/crates/targets/i686_msvc/lib/windows.0.48.0.lib index 8dc75cfce8..76dd4d2da3 100644 Binary files a/crates/targets/i686_msvc/lib/windows.0.48.0.lib and b/crates/targets/i686_msvc/lib/windows.0.48.0.lib differ diff --git a/crates/targets/x86_64_msvc/lib/windows.0.48.0.lib b/crates/targets/x86_64_msvc/lib/windows.0.48.0.lib index cffc2ab11f..dcc06aa07a 100644 Binary files a/crates/targets/x86_64_msvc/lib/windows.0.48.0.lib and b/crates/targets/x86_64_msvc/lib/windows.0.48.0.lib differ diff --git a/crates/tests/riddle/src/lib.rs b/crates/tests/riddle/src/lib.rs index c2cfe359e0..90f3a5723d 100644 --- a/crates/tests/riddle/src/lib.rs +++ b/crates/tests/riddle/src/lib.rs @@ -1,4 +1,5 @@ mod nested_struct; +mod params; mod r#struct; use std::process::Command; diff --git a/crates/tests/riddle/src/params.rs b/crates/tests/riddle/src/params.rs new file mode 100644 index 0000000000..7a2f61423d --- /dev/null +++ b/crates/tests/riddle/src/params.rs @@ -0,0 +1,307 @@ +// Bindings generated by `riddle` 0.0.1 + +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] +#[repr(transparent)] +pub struct IParams(::windows_core::IUnknown); +impl IParams { + pub fn Nothing(&self) -> ::windows_core::Result<()> { + let this = self; + unsafe { + (::windows_core::Interface::vtable(this).Nothing)(::windows_core::Interface::as_raw( + this, + )) + .ok() + } + } + pub fn Bool(&self, a: &mut bool, b: &mut bool) -> ::windows_core::Result { + let this = self; + unsafe { + let mut result__ = ::std::mem::zeroed(); + (::windows_core::Interface::vtable(this).Bool)( + ::windows_core::Interface::as_raw(this), + a, + b, + &mut result__, + ) + .from_abi(result__) + } + } + pub fn I8(&self, a: &mut i8, b: &mut i8) -> ::windows_core::Result { + let this = self; + unsafe { + let mut result__ = ::std::mem::zeroed(); + (::windows_core::Interface::vtable(this).I8)( + ::windows_core::Interface::as_raw(this), + a, + b, + &mut result__, + ) + .from_abi(result__) + } + } + pub fn U8(&self, a: &mut u8, b: &mut u8) -> ::windows_core::Result { + let this = self; + unsafe { + let mut result__ = ::std::mem::zeroed(); + (::windows_core::Interface::vtable(this).U8)( + ::windows_core::Interface::as_raw(this), + a, + b, + &mut result__, + ) + .from_abi(result__) + } + } + pub fn I16(&self, a: &mut i16, b: &mut i16) -> ::windows_core::Result { + let this = self; + unsafe { + let mut result__ = ::std::mem::zeroed(); + (::windows_core::Interface::vtable(this).I16)( + ::windows_core::Interface::as_raw(this), + a, + b, + &mut result__, + ) + .from_abi(result__) + } + } + pub fn U16(&self, a: &mut u16, b: &mut u16) -> ::windows_core::Result { + let this = self; + unsafe { + let mut result__ = ::std::mem::zeroed(); + (::windows_core::Interface::vtable(this).U16)( + ::windows_core::Interface::as_raw(this), + a, + b, + &mut result__, + ) + .from_abi(result__) + } + } + pub fn I32(&self, a: &mut i32, b: &mut i32) -> ::windows_core::Result { + let this = self; + unsafe { + let mut result__ = ::std::mem::zeroed(); + (::windows_core::Interface::vtable(this).I32)( + ::windows_core::Interface::as_raw(this), + a, + b, + &mut result__, + ) + .from_abi(result__) + } + } + pub fn U32(&self, a: &mut u32, b: &mut u32) -> ::windows_core::Result { + let this = self; + unsafe { + let mut result__ = ::std::mem::zeroed(); + (::windows_core::Interface::vtable(this).U32)( + ::windows_core::Interface::as_raw(this), + a, + b, + &mut result__, + ) + .from_abi(result__) + } + } + pub fn I64(&self, a: &mut i64, b: &mut i64) -> ::windows_core::Result { + let this = self; + unsafe { + let mut result__ = ::std::mem::zeroed(); + (::windows_core::Interface::vtable(this).I64)( + ::windows_core::Interface::as_raw(this), + a, + b, + &mut result__, + ) + .from_abi(result__) + } + } + pub fn U64(&self, a: &mut u64, b: &mut u64) -> ::windows_core::Result { + let this = self; + unsafe { + let mut result__ = ::std::mem::zeroed(); + (::windows_core::Interface::vtable(this).U64)( + ::windows_core::Interface::as_raw(this), + a, + b, + &mut result__, + ) + .from_abi(result__) + } + } + pub fn F32(&self, a: &mut f32, b: &mut f32) -> ::windows_core::Result { + let this = self; + unsafe { + let mut result__ = ::std::mem::zeroed(); + (::windows_core::Interface::vtable(this).F32)( + ::windows_core::Interface::as_raw(this), + a, + b, + &mut result__, + ) + .from_abi(result__) + } + } + pub fn F64(&self, a: &mut f64, b: &mut f64) -> ::windows_core::Result { + let this = self; + unsafe { + let mut result__ = ::std::mem::zeroed(); + (::windows_core::Interface::vtable(this).F64)( + ::windows_core::Interface::as_raw(this), + a, + b, + &mut result__, + ) + .from_abi(result__) + } + } + pub fn ISize(&self, a: &mut isize, b: &mut isize) -> ::windows_core::Result { + let this = self; + unsafe { + let mut result__ = ::std::mem::zeroed(); + (::windows_core::Interface::vtable(this).ISize)( + ::windows_core::Interface::as_raw(this), + a, + b, + &mut result__, + ) + .from_abi(result__) + } + } + pub fn USize(&self, a: &mut usize, b: &mut usize) -> ::windows_core::Result { + let this = self; + unsafe { + let mut result__ = ::std::mem::zeroed(); + (::windows_core::Interface::vtable(this).USize)( + ::windows_core::Interface::as_raw(this), + a, + b, + &mut result__, + ) + .from_abi(result__) + } + } +} +::windows_core::imp::interface_hierarchy!( + IParams, + ::windows_core::IUnknown, + ::windows_core::IInspectable +); +impl ::core::cmp::PartialEq for IParams { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} +impl ::core::cmp::Eq for IParams {} +impl ::core::fmt::Debug for IParams { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("IParams").field(&self.0).finish() + } +} +impl ::windows_core::RuntimeType for IParams { + const SIGNATURE: ::windows_core::imp::ConstBuffer = + ::windows_core::imp::ConstBuffer::from_slice(b"TODO"); +} +unsafe impl ::windows_core::Interface for IParams { + type Vtable = IParams_Vtbl; +} +impl ::core::clone::Clone for IParams { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} +unsafe impl ::windows_core::ComInterface for IParams { + const IID: ::windows_core::GUID = ::windows_core::GUID::zeroed(); +} +#[repr(C)] +#[doc(hidden)] +pub struct IParams_Vtbl { + pub base__: ::windows_core::IInspectable_Vtbl, + pub Nothing: + unsafe extern "system" fn(this: *mut ::core::ffi::c_void) -> ::windows_core::HRESULT, + pub Bool: unsafe extern "system" fn( + this: *mut ::core::ffi::c_void, + a: *mut bool, + b: *mut bool, + result__: *mut bool, + ) -> ::windows_core::HRESULT, + pub I8: unsafe extern "system" fn( + this: *mut ::core::ffi::c_void, + a: *mut i8, + b: *mut i8, + result__: *mut i8, + ) -> ::windows_core::HRESULT, + pub U8: unsafe extern "system" fn( + this: *mut ::core::ffi::c_void, + a: *mut u8, + b: *mut u8, + result__: *mut u8, + ) -> ::windows_core::HRESULT, + pub I16: unsafe extern "system" fn( + this: *mut ::core::ffi::c_void, + a: *mut i16, + b: *mut i16, + result__: *mut i16, + ) -> ::windows_core::HRESULT, + pub U16: unsafe extern "system" fn( + this: *mut ::core::ffi::c_void, + a: *mut u16, + b: *mut u16, + result__: *mut u16, + ) -> ::windows_core::HRESULT, + pub I32: unsafe extern "system" fn( + this: *mut ::core::ffi::c_void, + a: *mut i32, + b: *mut i32, + result__: *mut i32, + ) -> ::windows_core::HRESULT, + pub U32: unsafe extern "system" fn( + this: *mut ::core::ffi::c_void, + a: *mut u32, + b: *mut u32, + result__: *mut u32, + ) -> ::windows_core::HRESULT, + pub I64: unsafe extern "system" fn( + this: *mut ::core::ffi::c_void, + a: *mut i64, + b: *mut i64, + result__: *mut i64, + ) -> ::windows_core::HRESULT, + pub U64: unsafe extern "system" fn( + this: *mut ::core::ffi::c_void, + a: *mut u64, + b: *mut u64, + result__: *mut u64, + ) -> ::windows_core::HRESULT, + pub F32: unsafe extern "system" fn( + this: *mut ::core::ffi::c_void, + a: *mut f32, + b: *mut f32, + result__: *mut f32, + ) -> ::windows_core::HRESULT, + pub F64: unsafe extern "system" fn( + this: *mut ::core::ffi::c_void, + a: *mut f64, + b: *mut f64, + result__: *mut f64, + ) -> ::windows_core::HRESULT, + pub ISize: unsafe extern "system" fn( + this: *mut ::core::ffi::c_void, + a: *mut isize, + b: *mut isize, + result__: *mut isize, + ) -> ::windows_core::HRESULT, + pub USize: unsafe extern "system" fn( + this: *mut ::core::ffi::c_void, + a: *mut usize, + b: *mut usize, + result__: *mut usize, + ) -> ::windows_core::HRESULT, +} diff --git a/crates/tests/riddle/tests/params.idl b/crates/tests/riddle/tests/params.idl new file mode 100644 index 0000000000..629d2a5566 --- /dev/null +++ b/crates/tests/riddle/tests/params.idl @@ -0,0 +1,18 @@ +mod Test { + interface IParams { + fn Nothing(); + fn Bool(a: bool, b: bool) -> bool; + fn I8(a: i8, b: i8) -> i8; + fn U8(a: u8, b: u8) -> u8; + fn I16(a: i16, b: i16) -> i16; + fn U16(a: u16, b: u16) -> u16; + fn I32(a: i32, b: i32) -> i32; + fn U32(a: u32, b: u32) -> u32; + fn I64(a: i64, b: i64) -> i64; + fn U64(a: u64, b: u64) -> u64; + fn F32(a: f32, b: f32) -> f32; + fn F64(a: f64, b: f64) -> f64; + fn ISize(a: isize, b: isize) -> isize; + fn USize(a: usize, b: usize) -> usize; + } +} \ No newline at end of file diff --git a/crates/tests/riddle/tests/params.rs b/crates/tests/riddle/tests/params.rs new file mode 100644 index 0000000000..4c2b8fba0d --- /dev/null +++ b/crates/tests/riddle/tests/params.rs @@ -0,0 +1,61 @@ +use test_riddle::run_riddle; +use windows_metadata::*; + +#[test] +fn primitives() { + let files = run_riddle("params"); + let reader = &Reader::new(&files); + + let def = reader + .get(TypeName::new("Test", "IParams")) + .next() + .expect("Type missing"); + + assert_eq!(reader.type_def_kind(def), TypeKind::Interface); + let generics = &reader.type_def_generics(def); + + assert!(reader.type_def_fields(def).next().is_none()); + let methods: Vec = reader.type_def_methods(def).collect(); + assert_eq!(methods.len(), 14); + + assert_eq!(reader.method_def_name(methods[0]), "Nothing"); + let sig = reader.method_def_signature(methods[0], generics); + assert_eq!(sig.return_type, Type::Void); + assert!(sig.params.is_empty()); + + assert_eq!(reader.method_def_name(methods[1]), "Bool"); + assert_eq!(reader.method_def_name(methods[2]), "I8"); + assert_eq!(reader.method_def_name(methods[3]), "U8"); + assert_eq!(reader.method_def_name(methods[4]), "I16"); + assert_eq!(reader.method_def_name(methods[5]), "U16"); + assert_eq!(reader.method_def_name(methods[6]), "I32"); + assert_eq!(reader.method_def_name(methods[7]), "U32"); + assert_eq!(reader.method_def_name(methods[8]), "I64"); + assert_eq!(reader.method_def_name(methods[9]), "U64"); + assert_eq!(reader.method_def_name(methods[10]), "F32"); + assert_eq!(reader.method_def_name(methods[11]), "F64"); + assert_eq!(reader.method_def_name(methods[12]), "ISize"); + assert_eq!(reader.method_def_name(methods[13]), "USize"); + + method(reader, generics, methods[1], Type::Bool); + method(reader, generics, methods[2], Type::I8); + method(reader, generics, methods[3], Type::U8); + method(reader, generics, methods[4], Type::I16); + method(reader, generics, methods[5], Type::U16); + method(reader, generics, methods[6], Type::I32); + method(reader, generics, methods[7], Type::U32); + method(reader, generics, methods[8], Type::I64); + method(reader, generics, methods[9], Type::U64); + method(reader, generics, methods[10], Type::F32); + method(reader, generics, methods[11], Type::F64); + method(reader, generics, methods[12], Type::ISize); + method(reader, generics, methods[13], Type::USize); +} + +fn method(reader: &Reader, generics: &[Type], method: MethodDef, expected: Type) { + let sig = reader.method_def_signature(method, generics); + assert_eq!(sig.return_type, expected); + assert_eq!(sig.params.len(), 2); + assert_eq!(sig.params[0].ty, expected); + assert_eq!(sig.params[1].ty, expected); +} diff --git a/crates/tools/riddle/src/idl/to_idl.rs b/crates/tools/riddle/src/idl/to_idl.rs index 2055682912..09f35f42fd 100644 --- a/crates/tools/riddle/src/idl/to_idl.rs +++ b/crates/tools/riddle/src/idl/to_idl.rs @@ -14,7 +14,7 @@ pub fn from_reader( // the same key as for winmd generation. if let Some((key, _)) = config.first_key_value() { - return Err(Error::new(&format!("invalid configuration value: `{key}`"))); + return Err(Error::new(&format!("invalid configuration value `{key}`"))); } let tree = Tree::new(writer.reader, writer.filter); @@ -144,10 +144,37 @@ impl<'a> Writer<'a> { fn interface_def(&self, def: metadata::TypeDef) -> TokenStream { let name = to_ident(self.reader.type_def_name(def)); + let generics = &self.reader.type_def_generics(def); + + let methods = self.reader.type_def_methods(def).map(|method| { + let name = to_ident(self.reader.method_def_name(method)); + let signature = self.reader.method_def_signature(method, generics); + let return_type = self.return_type(&signature.return_type); + + let params = signature.params.iter().map(|param| { + let name = to_ident(self.reader.param_name(param.def)); + let ty = self.ty(¶m.ty); + quote! { #name: #ty } + }); + + quote! { + fn #name(#(#params),*) #return_type; + } + }); quote! { - struct #name { + interface #name { + #(#methods)* + } + } + } + fn return_type(&self, ty: &metadata::Type) -> TokenStream { + match ty { + metadata::Type::Void => quote! {}, + _ => { + let ty = self.ty(ty); + quote! { -> #ty } } } } @@ -169,6 +196,7 @@ impl<'a> Writer<'a> { metadata::Type::F64 => quote! { f64 }, metadata::Type::ISize => quote! { isize }, metadata::Type::USize => quote! { usize }, + metadata::Type::String => quote! { HSTRING }, metadata::Type::TypeDef(def, generics) => { let namespace = self.namespace(self.reader.type_def_namespace(*def)); let name = to_ident(self.reader.type_def_name(*def)); diff --git a/crates/tools/riddle/src/idl/to_winmd.rs b/crates/tools/riddle/src/idl/to_winmd.rs index 330fd30006..ac0c5eecb6 100644 --- a/crates/tools/riddle/src/idl/to_winmd.rs +++ b/crates/tools/riddle/src/idl/to_winmd.rs @@ -89,7 +89,7 @@ fn write_interface( writer: &mut winmd::Writer, namespace: &str, name: &str, - _member: &idl::Interface, + member: &idl::Interface, ) { let flags = metadata::TypeAttributes::Public | metadata::TypeAttributes::Interface @@ -104,6 +104,28 @@ fn write_interface( TypeName: writer.strings.insert(name), TypeNamespace: writer.strings.insert(namespace), }); + + for method in &member.methods { + let sig = syn_signature(namespace, &method.sig); + let signature = writer.insert_method_sig(&sig); + + writer.tables.MethodDef.push(winmd::MethodDef { + RVA: 0, + ImplFlags: 0, + Flags: 0, + Name: writer.strings.insert(&method.sig.ident.to_string()), + Signature: signature, + ParamList: writer.tables.Param.len() as _, + }); + + for (sequence, param) in sig.params.iter().enumerate() { + writer.tables.Param.push(winmd::Param { + Flags: 0, + Sequence: (sequence + 1) as _, + Name: writer.strings.insert(¶m.name), + }); + } + } } fn write_struct(writer: &mut winmd::Writer, namespace: &str, name: &str, member: &idl::Struct) { @@ -297,6 +319,36 @@ fn write_class(_writer: &mut winmd::Writer, _namespace: &str, _name: &str, _memb // } // } +fn syn_signature(namespace: &str, sig: &syn::Signature) -> winmd::Signature { + let params = sig + .inputs + .iter() + .map(|param| match param { + syn::FnArg::Typed(pat_type) => { + let name = match &*pat_type.pat { + syn::Pat::Ident(pat_ident) => pat_ident.ident.to_string(), + rest => unimplemented!("{rest:?}"), + }; + let ty = syn_type(namespace, &pat_type.ty); + winmd::SignatureParam { name, ty } + } + rest => unimplemented!("{rest:?}"), + }) + .collect(); + + let return_type = if let syn::ReturnType::Type(_, ty) = &sig.output { + syn_type(namespace, ty) + } else { + winmd::Type::Void + }; + + winmd::Signature { + params, + return_type, + call_flags: 0, + } +} + fn syn_type(namespace: &str, ty: &syn::Type) -> winmd::Type { match ty { syn::Type::Path(ty) => syn_type_path(namespace, ty), diff --git a/crates/tools/riddle/src/main.rs b/crates/tools/riddle/src/main.rs index 1b2aa48ce1..8becd3ab6d 100644 --- a/crates/tools/riddle/src/main.rs +++ b/crates/tools/riddle/src/main.rs @@ -64,7 +64,7 @@ Options: "-filter" => kind = ArgKind::Filter, "-config" => kind = ArgKind::Config, "-format" => format = true, - _ => return Err(Error::new(&format!("invalid option: `{arg}`"))), + _ => return Err(Error::new(&format!("invalid option `{arg}`"))), }, ArgKind::Output => { if output.is_none() { @@ -130,6 +130,8 @@ Options: let reader = metadata::Reader::new(&input); let filter = metadata::Filter::new(&include, &exclude); + winmd::verify(&reader, &filter)?; + match extension(&output) { "idl" => idl::from_reader(&reader, &filter, config, &output)?, "winmd" => winmd::from_reader(&reader, &filter, config, &output)?, diff --git a/crates/tools/riddle/src/rust/classes.rs b/crates/tools/riddle/src/rust/classes.rs index d3f73d3d3d..d2d0f12926 100644 --- a/crates/tools/riddle/src/rust/classes.rs +++ b/crates/tools/riddle/src/rust/classes.rs @@ -1,9 +1,9 @@ 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)); +pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { + if writer.sys { + if writer.reader.type_def_has_default_interface(def) { + let name = to_ident(writer.reader.type_def_name(def)); quote! { pub type #name = *mut ::core::ffi::c_void; } @@ -11,31 +11,33 @@ pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { quote! {} } } else { - gen_class(gen, def) + gen_class(writer, def) } } -fn gen_class(gen: &Gen, def: TypeDef) -> TokenStream { - if gen.reader.type_def_extends(def) == Some(TypeName::Attribute) { +fn gen_class(writer: &Writer, def: TypeDef) -> TokenStream { + if writer.reader.type_def_extends(def) == Some(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 name = to_ident(writer.reader.type_def_name(def)); + let interfaces = writer + .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); + let cfg = writer.reader.type_def_cfg(def, &[]); + let doc = writer.cfg_doc(&cfg); + let features = writer.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, + for method in writer.reader.type_def_methods(*def) { + methods.combine(&winrt_methods::writer( + writer, *def, generics, interface.kind, @@ -50,9 +52,9 @@ fn gen_class(gen: &Gen, def: TypeDef) -> TokenStream { 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)); + if writer.reader.type_def_methods(*def).next().is_some() { + let interface_type = writer.type_name(&interface.ty); + let features = writer.cfg_features(&writer.reader.type_def_cfg(*def, generics)); return Some(quote! { #[doc(hidden)] @@ -72,8 +74,8 @@ fn gen_class(gen: &Gen, def: TypeDef) -> TokenStream { _ => None, }); - if gen.reader.type_def_has_default_interface(def) { - let new = if gen.reader.type_def_has_default_constructor(def) { + if writer.reader.type_def_has_default_interface(def) { + let new = if writer.reader.type_def_has_default_constructor(def) { quote! { pub fn new() -> ::windows_core::Result { Self::IActivationFactory(|f| f.ActivateInstance::()) @@ -103,7 +105,7 @@ fn gen_class(gen: &Gen, def: TypeDef) -> TokenStream { } }; - tokens.combine(&gen.interface_core_traits( + tokens.combine(&writer.interface_core_traits( def, &[], &name, @@ -111,7 +113,7 @@ fn gen_class(gen: &Gen, def: TypeDef) -> TokenStream { &TokenStream::new(), &features, )); - tokens.combine(&gen.interface_winrt_trait( + tokens.combine(&writer.interface_winrt_trait( def, &[], &name, @@ -119,9 +121,16 @@ fn gen_class(gen: &Gen, def: TypeDef) -> TokenStream { &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( + tokens.combine(&writer.interface_trait( + def, + &[], + &name, + &TokenStream::new(), + &features, + true, + )); + tokens.combine(&writer.runtime_name_trait(def, &[], &name, &TokenStream::new(), &features)); + tokens.combine(&writer.async_get( def, &[], &name, @@ -129,8 +138,8 @@ fn gen_class(gen: &Gen, def: TypeDef) -> TokenStream { &TokenStream::new(), &features, )); - tokens.combine(&iterators::gen( - gen, + tokens.combine(&iterators::writer( + writer, def, &[], &name, @@ -138,8 +147,8 @@ fn gen_class(gen: &Gen, def: TypeDef) -> TokenStream { &TokenStream::new(), &cfg, )); - tokens.combine(&gen_conversions(gen, def, &name, &interfaces, &cfg)); - tokens.combine(&gen.agile(def, &name, &TokenStream::new(), &features)); + tokens.combine(&gen_conversions(writer, def, &name, &interfaces, &cfg)); + tokens.combine(&writer.agile(def, &name, &TokenStream::new(), &features)); tokens } else { let mut tokens = quote! { @@ -153,26 +162,26 @@ fn gen_class(gen: &Gen, def: TypeDef) -> TokenStream { } }; - tokens.combine(&gen.runtime_name_trait(def, &[], &name, &TokenStream::new(), &features)); + tokens.combine(&writer.runtime_name_trait(def, &[], &name, &TokenStream::new(), &features)); tokens } } fn gen_conversions( - gen: &Gen, + writer: &Writer, def: TypeDef, name: &TokenStream, interfaces: &[Interface], cfg: &Cfg, ) -> TokenStream { - let features = gen.cfg_features(cfg); + let features = writer.cfg_features(cfg); let mut tokens = quote! { #features ::windows_core::imp::interface_hierarchy!(#name, ::windows_core::IUnknown, ::windows_core::IInspectable); }; for interface in interfaces { - if gen.reader.type_is_exclusive(&interface.ty) { + if writer.reader.type_is_exclusive(&interface.ty) { continue; } @@ -183,8 +192,8 @@ fn gen_conversions( continue; } - let into = gen.type_name(&interface.ty); - let features = gen.cfg_features(&cfg.union(&gen.reader.type_cfg(&interface.ty))); + let into = writer.type_name(&interface.ty); + let features = writer.cfg_features(&cfg.union(&writer.reader.type_cfg(&interface.ty))); tokens.combine("e! { #features @@ -192,9 +201,9 @@ fn gen_conversions( }); } - 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, &[]))); + for def in writer.reader.type_def_bases(def) { + let into = writer.type_def_name(def, &[]); + let features = writer.cfg_features(&cfg.union(&writer.reader.type_def_cfg(def, &[]))); tokens.combine("e! { #features diff --git a/crates/tools/riddle/src/rust/com_methods.rs b/crates/tools/riddle/src/rust/com_methods.rs index 09bcf36be2..3c9f137780 100644 --- a/crates/tools/riddle/src/rust/com_methods.rs +++ b/crates/tools/riddle/src/rust/com_methods.rs @@ -1,7 +1,7 @@ use super::*; -pub fn gen( - gen: &Gen, +pub fn writer( + writer: &Writer, def: TypeDef, kind: InterfaceKind, method: MethodDef, @@ -9,15 +9,15 @@ pub fn gen( 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); + let signature = writer.reader.method_def_signature(method, &[]); + let name = method_names.add(writer, method); + let vname = virtual_names.add(writer, method); + let generics = writer.constraint_generics(&signature.params); + let where_clause = writer.where_clause(&signature.params); + let mut cfg = writer.reader.signature_cfg(&signature); + cfg.add_feature(writer.reader.type_def_namespace(def)); + let doc = writer.cfg_method_doc(&cfg); + let features = writer.cfg_features(&cfg); if kind == InterfaceKind::None { return quote! {}; @@ -29,11 +29,11 @@ pub fn gen( bases.combine("e! { .base__ }); } - let kind = gen.reader.signature_kind(&signature); + let kind = writer.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 args = writer.win32_args(&signature.params, kind); + let params = writer.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)); @@ -48,8 +48,8 @@ pub fn gen( } } SignatureKind::QueryOptional(_) => { - let args = gen.win32_args(&signature.params, kind); - let params = gen.win32_params(&signature.params, kind); + let args = writer.win32_args(&signature.params, kind); + let params = writer.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)); @@ -63,10 +63,10 @@ pub fn gen( } } SignatureKind::ResultValue => { - let args = gen.win32_args(&signature.params, kind); - let params = gen.win32_params(&signature.params, kind); + let args = writer.win32_args(&signature.params, kind); + let params = writer.win32_params(&signature.params, kind); let return_type = signature.params[signature.params.len() - 1].ty.deref(); - let return_type = gen.type_name(&return_type); + let return_type = writer.type_name(&return_type); quote! { #doc @@ -78,8 +78,8 @@ pub fn gen( } } SignatureKind::ResultVoid => { - let args = gen.win32_args(&signature.params, kind); - let params = gen.win32_params(&signature.params, kind); + let args = writer.win32_args(&signature.params, kind); + let params = writer.win32_params(&signature.params, kind); quote! { #doc @@ -90,11 +90,11 @@ pub fn gen( } } SignatureKind::ReturnValue => { - let args = gen.win32_args(&signature.params, kind); - let params = gen.win32_params(&signature.params, kind); + let args = writer.win32_args(&signature.params, kind); + let params = writer.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); + let is_nullable = writer.reader.type_is_nullable(&return_type); + let return_type = writer.type_name(&return_type); if is_nullable { quote! { @@ -119,9 +119,9 @@ pub fn gen( } } 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); + let args = writer.win32_args(&signature.params, kind); + let params = writer.win32_params(&signature.params, kind); + let return_type = writer.type_name(&signature.return_type); quote! { #doc @@ -134,9 +134,9 @@ pub fn gen( } } 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); + let args = writer.win32_args(&signature.params, kind); + let params = writer.win32_params(&signature.params, kind); + let return_type = writer.return_sig(&signature); quote! { #doc @@ -147,8 +147,8 @@ pub fn gen( } } SignatureKind::ReturnVoid => { - let args = gen.win32_args(&signature.params, kind); - let params = gen.win32_params(&signature.params, kind); + let args = writer.win32_args(&signature.params, kind); + let params = writer.win32_params(&signature.params, kind); quote! { #doc @@ -161,14 +161,14 @@ pub fn gen( } } -pub fn gen_upcall(gen: &Gen, sig: &Signature, inner: TokenStream) -> TokenStream { - match gen.reader.signature_kind(sig) { +pub fn gen_upcall(writer: &Writer, sig: &Signature, inner: TokenStream) -> TokenStream { + match writer.reader.signature_kind(sig) { SignatureKind::ResultValue => { let invoke_args = sig.params[..sig.params.len() - 1] .iter() - .map(|param| gen_win32_invoke_arg(gen, param)); + .map(|param| gen_win32_invoke_arg(writer, param)); - let result = gen.param_name(sig.params[sig.params.len() - 1].def); + let result = writer.param_name(sig.params[sig.params.len() - 1].def); quote! { match #inner(#(#invoke_args,)*) { @@ -185,7 +185,7 @@ pub fn gen_upcall(gen: &Gen, sig: &Signature, inner: TokenStream) -> TokenStream let invoke_args = sig .params .iter() - .map(|param| gen_win32_invoke_arg(gen, param)); + .map(|param| gen_win32_invoke_arg(writer, param)); quote! { #inner(#(#invoke_args,)*).into() @@ -195,7 +195,7 @@ pub fn gen_upcall(gen: &Gen, sig: &Signature, inner: TokenStream) -> TokenStream let invoke_args = sig .params .iter() - .map(|param| gen_win32_invoke_arg(gen, param)); + .map(|param| gen_win32_invoke_arg(writer, param)); quote! { *result__ = #inner(#(#invoke_args,)*) @@ -205,7 +205,7 @@ pub fn gen_upcall(gen: &Gen, sig: &Signature, inner: TokenStream) -> TokenStream let invoke_args = sig .params .iter() - .map(|param| gen_win32_invoke_arg(gen, param)); + .map(|param| gen_win32_invoke_arg(writer, param)); quote! { #inner(#(#invoke_args,)*) @@ -214,22 +214,22 @@ pub fn gen_upcall(gen: &Gen, sig: &Signature, inner: TokenStream) -> TokenStream } } -fn gen_win32_invoke_arg(gen: &Gen, param: &SignatureParam) -> TokenStream { - let name = gen.param_name(param.def); +fn gen_win32_invoke_arg(writer: &Writer, param: &SignatureParam) -> TokenStream { + let name = writer.param_name(param.def); - if gen + if writer .reader .param_flags(param.def) .contains(ParamAttributes::In) - && gen.reader.type_is_nullable(¶m.ty) + && writer.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 + } else if (!param.ty.is_pointer() && writer.reader.type_is_nullable(¶m.ty)) + || (writer .reader .param_flags(param.def) .contains(ParamAttributes::In) - && !gen.reader.type_is_primitive(¶m.ty)) + && !writer.reader.type_is_primitive(¶m.ty)) { quote! { ::core::mem::transmute(&#name) } } else { diff --git a/crates/tools/riddle/src/rust/constants.rs b/crates/tools/riddle/src/rust/constants.rs index 1e79b911cc..2ce3a37187 100644 --- a/crates/tools/riddle/src/rust/constants.rs +++ b/crates/tools/riddle/src/rust/constants.rs @@ -1,27 +1,27 @@ 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); +pub fn writer(writer: &Writer, def: Field) -> TokenStream { + let name = to_ident(writer.reader.field_name(def)); + let ty = writer.reader.field_type(def, None).to_const_type(); + let cfg = writer.reader.field_cfg(def); + let doc = writer.cfg_doc(&cfg); + let features = writer.cfg_features(&cfg); - if let Some(constant) = gen.reader.field_constant(def) { - let constant_type = gen.reader.constant_type(constant); + if let Some(constant) = writer.reader.field_constant(def) { + let constant_type = writer.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)); + let crate_name = writer.crate_name(); + if writer.reader.field_is_ansi(def) { + let value = writer.value(&writer.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)); + let value = writer.value(&writer.reader.constant_value(constant)); quote! { #doc #features @@ -29,7 +29,7 @@ pub fn gen(gen: &Gen, def: Field) -> TokenStream { } } } else { - let value = gen.typed_value(&gen.reader.constant_value(constant)); + let value = writer.typed_value(&writer.reader.constant_value(constant)); quote! { #doc #features @@ -37,19 +37,19 @@ pub fn gen(gen: &Gen, def: Field) -> TokenStream { } } } 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 kind = writer.type_default_name(&ty); + let value = writer.value(&writer.reader.constant_value(constant)); + let underlying_type = writer.reader.type_underlying_type(&ty); let value = if underlying_type == constant_type { value - } else if gen.std && underlying_type == Type::ISize { + } else if writer.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) { + if !writer.sys && writer.reader.type_has_replacement(&ty) { quote! { #doc #features @@ -63,15 +63,15 @@ pub fn gen(gen: &Gen, def: Field) -> TokenStream { } } } - } else if let Some(guid) = gen.reader.field_guid(def) { - let value = gen.guid(&guid); - let guid = gen.type_name(&Type::GUID); + } else if let Some(guid) = writer.reader.field_guid(def) { + let value = writer.guid(&guid); + let guid = writer.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); + } else if let Some(value) = initializer(writer, def) { + let kind = writer.type_default_name(&ty); quote! { #doc @@ -83,21 +83,21 @@ pub fn gen(gen: &Gen, def: Field) -> TokenStream { } } -fn initializer(gen: &Gen, def: Field) -> Option { - let Some(value) = constant(gen, def) else { +fn initializer(writer: &Writer, def: Field) -> Option { + let Some(value) = constant(writer, def) else { return None; }; let mut input = value.as_str(); - let Type::TypeDef(def, _) = gen.reader.field_type(def, None) else { + let Type::TypeDef(def, _) = writer.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); + for field in writer.reader.type_def_fields(def) { + let (value, rest) = field_initializer(writer, field, input); input = rest; result.combine(&value); } @@ -105,13 +105,13 @@ fn initializer(gen: &Gen, def: Field) -> Option { 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)); +fn field_initializer<'a>(writer: &Writer, field: Field, input: &'a str) -> (TokenStream, &'a str) { + let name = to_ident(writer.reader.field_name(field)); - match gen.reader.field_type(field, None) { + match writer.reader.field_type(field, None) { Type::GUID => { let (literals, rest) = read_literal_array(input, 11); - let value = gen.guid(&GUID::from_string_args(&literals)); + let value = writer.guid(&GUID::from_string_args(&literals)); (quote! { #name: #value, }, rest) } Type::Win32Array(_, len) => { @@ -127,12 +127,13 @@ fn field_initializer<'a>(gen: &Gen, field: Field, input: &'a str) -> (TokenStrea } } -fn constant(gen: &Gen, def: Field) -> Option { - gen.reader +fn constant(writer: &Writer, def: Field) -> Option { + writer + .reader .field_attributes(def) - .find(|attribute| gen.reader.attribute_name(*attribute) == "ConstantAttribute") + .find(|attribute| writer.reader.attribute_name(*attribute) == "ConstantAttribute") .map(|attribute| { - let args = gen.reader.attribute_args(attribute); + let args = writer.reader.attribute_args(attribute); match &args[0].1 { Value::String(value) => value.clone(), rest => unimplemented!("{rest:?}"), diff --git a/crates/tools/riddle/src/rust/delegates.rs b/crates/tools/riddle/src/rust/delegates.rs index 6d2926620b..2ff5bdcb2a 100644 --- a/crates/tools/riddle/src/rust/delegates.rs +++ b/crates/tools/riddle/src/rust/delegates.rs @@ -1,30 +1,30 @@ use super::*; -pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { - if gen +pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { + if writer .reader .type_def_flags(def) .contains(TypeAttributes::WindowsRuntime) { - gen_delegate(gen, def) + gen_delegate(writer, def) } else { - gen_callback(gen, def) + gen_callback(writer, def) } } -fn gen_callback(gen: &Gen, def: TypeDef) -> TokenStream { - let name = to_ident(gen.reader.type_def_name(def)); +fn gen_callback(writer: &Writer, def: TypeDef) -> TokenStream { + let name = to_ident(writer.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 method = writer.reader.type_def_invoke_method(def); + let signature = writer.reader.method_def_signature(method, &[]); + let return_type = writer.return_sig(&signature); + let cfg = writer.reader.type_def_cfg(def, &[]); + let doc = writer.cfg_doc(&cfg); + let features = writer.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); + let name = writer.param_name(p.def); + let tokens = writer.type_default_name(&p.ty); quote! { #name: #tokens } }); @@ -35,41 +35,41 @@ fn gen_callback(gen: &Gen, def: TypeDef) -> TokenStream { } } -fn gen_delegate(gen: &Gen, def: TypeDef) -> TokenStream { - if gen.sys { - let name = to_ident(gen.reader.type_def_name(def)); +fn gen_delegate(writer: &Writer, def: TypeDef) -> TokenStream { + if writer.sys { + let name = to_ident(writer.reader.type_def_name(def)); quote! { pub type #name = *mut ::core::ffi::c_void; } } else { - gen_win_delegate(gen, def) + gen_win_delegate(writer, def) } } -fn gen_win_delegate(gen: &Gen, def: TypeDef) -> TokenStream { - let name = to_ident(gen.reader.type_def_name(def)); +fn gen_win_delegate(writer: &Writer, def: TypeDef) -> TokenStream { + let name = to_ident(writer.reader.type_def_name(def)); let vtbl = name.join("_Vtbl"); let boxed = name.join("Box"); - let generics: &Vec = &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 generics = &writer.reader.type_def_generics(def); + let phantoms = writer.generic_phantoms(generics); + let named_phantoms = writer.generic_named_phantoms(generics); + let constraints = writer.generic_constraints(generics); + let generic_names = writer.generic_names(generics); - let ident = gen.type_def_name(def, generics); + let ident = writer.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 method = writer.reader.type_def_invoke_method(def); + let signature = writer.reader.method_def_signature(method, generics); + let fn_constraint = gen_fn_constraint(writer, def, &signature); - let cfg = gen.reader.type_def_cfg(def, generics); - let doc = gen.cfg_doc(&cfg); - let features = gen.cfg_features(&cfg); + let cfg = writer.reader.type_def_cfg(def, generics); + let doc = writer.cfg_doc(&cfg); + let features = writer.cfg_features(&cfg); - let vtbl_signature = gen.vtbl_signature(def, generics, &signature); - let invoke = winrt_methods::gen( - gen, + let vtbl_signature = writer.vtbl_signature(def, generics, &signature); + let invoke = winrt_methods::writer( + writer, def, generics, InterfaceKind::Default, @@ -77,7 +77,7 @@ fn gen_win_delegate(gen: &Gen, def: TypeDef) -> TokenStream { &mut MethodNames::new(), &mut MethodNames::new(), ); - let invoke_upcall = winrt_methods::gen_upcall(gen, &signature, quote! { ((*this).invoke) }); + let invoke_upcall = winrt_methods::gen_upcall(writer, &signature, quote! { ((*this).invoke) }); let mut tokens = quote! { #doc @@ -153,7 +153,7 @@ fn gen_win_delegate(gen: &Gen, def: TypeDef) -> TokenStream { } }; - tokens.combine(&gen.interface_core_traits( + tokens.combine(&writer.interface_core_traits( def, generics, &ident, @@ -161,8 +161,8 @@ fn gen_win_delegate(gen: &Gen, def: TypeDef) -> TokenStream { &phantoms, &features, )); - tokens.combine(&gen.interface_trait(def, generics, &ident, &constraints, &features, true)); - tokens.combine(&gen.interface_winrt_trait( + tokens.combine(&writer.interface_trait(def, generics, &ident, &constraints, &features, true)); + tokens.combine(&writer.interface_winrt_trait( def, generics, &ident, @@ -170,12 +170,12 @@ fn gen_win_delegate(gen: &Gen, def: TypeDef) -> TokenStream { &phantoms, &features, )); - tokens.combine(&gen.interface_vtbl(def, generics, &ident, &constraints, &features)); + tokens.combine(&writer.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); +fn gen_fn_constraint(writer: &Writer, def: TypeDef, signature: &Signature) -> TokenStream { + let signature = writer.impl_signature(def, signature); quote! { F: FnMut #signature + ::core::marker::Send + 'static } } diff --git a/crates/tools/riddle/src/rust/enums.rs b/crates/tools/riddle/src/rust/enums.rs index b7fbaa6fbc..50348875ee 100644 --- a/crates/tools/riddle/src/rust/enums.rs +++ b/crates/tools/riddle/src/rust/enums.rs @@ -1,27 +1,27 @@ use super::*; -pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { - let type_name = gen.reader.type_def_type_name(def); +pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { + let type_name = writer.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 + let underlying_type = writer.reader.type_def_underlying_type(def); + let underlying_type = writer.type_name(&underlying_type); + let is_scoped = writer.reader.type_def_is_scoped(def); + let cfg = writer.reader.type_def_cfg(def, &[]); + let doc = writer.cfg_doc(&cfg); + let features = writer.cfg_features(&cfg); + + let fields: Vec<(TokenStream, TokenStream)> = writer .reader .type_def_fields(def) .filter_map(|field| { - if gen + if writer .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)); + let field_name = to_ident(writer.reader.field_name(field)); + let constant = writer.reader.field_constant(field).unwrap(); + let value = writer.value(&writer.reader.constant_value(constant)); Some((field_name, value)) } else { @@ -30,7 +30,7 @@ pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { }) .collect(); - let eq = if gen.sys { + let eq = if writer.sys { quote! {} } else { quote! { @@ -39,7 +39,7 @@ pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { } }; - let mut tokens = if is_scoped || !gen.sys { + let mut tokens = if is_scoped || !writer.sys { quote! { #doc #features @@ -68,8 +68,8 @@ pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { #(#fields)* } }); - } else if !gen.minimal { - if gen.sys { + } else if !writer.minimal { + if writer.sys { let fields = fields.iter().map(|(field_name, value)| { quote! { #doc @@ -96,7 +96,7 @@ pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { } } - if is_scoped || !gen.sys { + if is_scoped || !writer.sys { tokens.combine("e! { #features impl ::core::marker::Copy for #ident {} @@ -109,7 +109,7 @@ pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { }); } - if !gen.sys { + if !writer.sys { tokens.combine("e! { #features impl ::core::default::Default for #ident { @@ -120,7 +120,7 @@ pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { }); } - if !gen.sys { + if !writer.sys { let name = type_name.name; tokens.combine("e! { #features @@ -135,7 +135,7 @@ pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { } }); - if gen.reader.type_def_is_flags(def) { + if writer.reader.type_def_is_flags(def) { tokens.combine("e! { #features impl #ident { @@ -182,13 +182,13 @@ pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { }); } - if gen + if writer .reader .type_def_flags(def) .contains(TypeAttributes::WindowsRuntime) { let signature = - Literal::byte_string(gen.reader.type_def_signature(def, &[]).as_bytes()); + Literal::byte_string(writer.reader.type_def_signature(def, &[]).as_bytes()); tokens.combine("e! { #features diff --git a/crates/tools/riddle/src/rust/extensions/mod.rs b/crates/tools/riddle/src/rust/extensions/mod.rs index a85aaae14d..9404dcb05b 100644 --- a/crates/tools/riddle/src/rust/extensions/mod.rs +++ b/crates/tools/riddle/src/rust/extensions/mod.rs @@ -1,11 +1,11 @@ use super::*; -pub fn gen_mod(gen: &Gen, namespace: &str) -> TokenStream { +pub fn gen_mod(writer: &Writer, namespace: &str) -> TokenStream { if namespace == "Windows.Win32.UI.WindowsAndMessaging" { return include_str!("mod/Win32/UI/WindowsAndMessaging/WindowLong.rs").into(); } - if gen.sys { + if writer.sys { return "".into(); } diff --git a/crates/tools/riddle/src/rust/functions.rs b/crates/tools/riddle/src/rust/functions.rs index 4a31186516..99ca3dd03f 100644 --- a/crates/tools/riddle/src/rust/functions.rs +++ b/crates/tools/riddle/src/rust/functions.rs @@ -1,37 +1,37 @@ use super::*; -pub fn gen(gen: &Gen, def: MethodDef) -> TokenStream { - if gen.sys { - gen_sys_function(gen, def) +pub fn writer(writer: &Writer, def: MethodDef) -> TokenStream { + if writer.sys { + gen_sys_function(writer, def) } else { - gen_win_function(gen, def) + gen_win_function(writer, 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)); +fn gen_sys_function(writer: &Writer, def: MethodDef) -> TokenStream { + let signature = writer.reader.method_def_signature(def, &[]); + let cfg = writer.reader.signature_cfg(&signature); + let mut tokens = writer.cfg_features(&cfg); + tokens.combine(&gen_link(writer, &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); +fn gen_win_function(writer: &Writer, def: MethodDef) -> TokenStream { + let name = to_ident(writer.reader.method_def_name(def)); + let signature = writer.reader.method_def_signature(def, &[]); + let generics = writer.constraint_generics(&signature.params); + let where_clause = writer.where_clause(&signature.params); + let abi_return_type = writer.return_sig(&signature); + let cfg = writer.reader.signature_cfg(&signature); + let doc = writer.cfg_doc(&cfg); + let features = writer.cfg_features(&cfg); + let link = gen_link(writer, &signature, &cfg); - let kind = gen.reader.signature_kind(&signature); + let kind = writer.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 args = writer.win32_args(&signature.params, kind); + let params = writer.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)); @@ -48,8 +48,8 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream { } } SignatureKind::QueryOptional(_) => { - let args = gen.win32_args(&signature.params, kind); - let params = gen.win32_params(&signature.params, kind); + let args = writer.win32_args(&signature.params, kind); + let params = writer.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)); @@ -65,10 +65,10 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream { } } SignatureKind::ResultValue => { - let args = gen.win32_args(&signature.params, kind); - let params = gen.win32_params(&signature.params, kind); + let args = writer.win32_args(&signature.params, kind); + let params = writer.win32_params(&signature.params, kind); let return_type = signature.params[signature.params.len() - 1].ty.deref(); - let return_type = gen.type_name(&return_type); + let return_type = writer.type_name(&return_type); quote! { #doc @@ -82,8 +82,8 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream { } } SignatureKind::ResultVoid => { - let args = gen.win32_args(&signature.params, kind); - let params = gen.win32_params(&signature.params, kind); + let args = writer.win32_args(&signature.params, kind); + let params = writer.win32_params(&signature.params, kind); quote! { #doc @@ -96,11 +96,11 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream { } } SignatureKind::ReturnValue => { - let args = gen.win32_args(&signature.params, kind); - let params = gen.win32_params(&signature.params, kind); + let args = writer.win32_args(&signature.params, kind); + let params = writer.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); + let is_nullable = writer.reader.type_is_nullable(&return_type); + let return_type = writer.type_name(&return_type); if is_nullable { quote! { @@ -129,10 +129,10 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream { } } 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); + if handle_last_error(writer, def, &signature) { + let args = writer.win32_args(&signature.params, kind); + let params = writer.win32_params(&signature.params, kind); + let return_type = writer.type_name(&signature.return_type); quote! { #doc @@ -145,8 +145,8 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream { } } } else { - let args = gen.win32_args(&signature.params, kind); - let params = gen.win32_params(&signature.params, kind); + let args = writer.win32_args(&signature.params, kind); + let params = writer.win32_params(&signature.params, kind); quote! { #doc @@ -160,9 +160,9 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream { } } 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); + let args = writer.win32_args(&signature.params, kind); + let params = writer.win32_params(&signature.params, kind); + let does_not_return = does_not_return(writer, def); quote! { #doc @@ -177,14 +177,14 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream { } } -fn gen_link(gen: &Gen, signature: &Signature, cfg: &Cfg) -> TokenStream { - let name = gen.reader.method_def_name(signature.def); +fn gen_link(writer: &Writer, signature: &Signature, cfg: &Cfg) -> TokenStream { + let name = writer.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 library = writer.reader.method_def_module_name(signature.def); + let abi = writer.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) + let symbol = if let Some(impl_map) = writer.reader.method_def_impl_map(signature.def) { + writer.reader.impl_map_import_name(impl_map) } else { name }; @@ -196,24 +196,24 @@ fn gen_link(gen: &Gen, signature: &Signature, cfg: &Cfg) -> TokenStream { }; let params = signature.params.iter().map(|p| { - let name = gen.param_name(p.def); + let name = writer.param_name(p.def); let tokens = if p.kind == SignatureParamKind::ValueType { - gen.type_default_name(&p.ty) + writer.type_default_name(&p.ty) } else { - gen.type_abi_name(&p.ty) + writer.type_abi_name(&p.ty) }; quote! { #name: #tokens } }); - let return_type = gen.return_sig(signature); + let return_type = writer.return_sig(signature); - let vararg = if gen.sys && signature.call_flags.contains(MethodCallAttributes::VARARG) { + let vararg = if writer.sys && signature.call_flags.contains(MethodCallAttributes::VARARG) { "...".into() } else { quote! {} }; - if gen.std || !gen.namespace.starts_with("Windows.") { + if writer.std || !writer.namespace.starts_with("Windows.") { let library = library.trim_end_matches(".dll"); quote! { @@ -223,7 +223,7 @@ fn gen_link(gen: &Gen, signature: &Signature, cfg: &Cfg) -> TokenStream { pub fn #ident(#(#params,)* #vararg) #return_type; } } - } else if let Some(library) = gen.reader.method_def_static_lib(signature.def) { + } else if let Some(library) = writer.reader.method_def_static_lib(signature.def) { quote! { #[link(name = #library, kind = "static")] extern #abi { @@ -238,8 +238,8 @@ fn gen_link(gen: &Gen, signature: &Signature, cfg: &Cfg) -> TokenStream { String::new() }; - let doc = if gen.sys { - gen.cfg_doc(cfg).0 + let doc = if writer.sys { + writer.cfg_doc(cfg).0 } else { String::new() }; @@ -257,31 +257,35 @@ fn gen_link(gen: &Gen, signature: &Signature, cfg: &Cfg) -> TokenStream { } } -fn does_not_return(gen: &Gen, def: MethodDef) -> TokenStream { - if gen.reader.method_def_does_not_return(def) { +fn does_not_return(writer: &Writer, def: MethodDef) -> TokenStream { + if writer.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 +fn handle_last_error(writer: &Writer, def: MethodDef, signature: &Signature) -> bool { + if let Some(map) = writer.reader.method_def_impl_map(def) { + if writer .reader .impl_map_flags(map) .contains(PInvokeAttributes::SupportsLastError) { if let Type::TypeDef(return_type, _) = &signature.return_type { - if gen.reader.type_def_is_handle(*return_type) { - if gen + if writer.reader.type_def_is_handle(*return_type) { + if writer .reader .type_def_underlying_type(*return_type) .is_pointer() { return true; } - if !gen.reader.type_def_invalid_values(*return_type).is_empty() { + if !writer + .reader + .type_def_invalid_values(*return_type) + .is_empty() + { return true; } } diff --git a/crates/tools/riddle/src/rust/handles.rs b/crates/tools/riddle/src/rust/handles.rs index a90c77d6a3..fac70a1b29 100644 --- a/crates/tools/riddle/src/rust/handles.rs +++ b/crates/tools/riddle/src/rust/handles.rs @@ -1,27 +1,27 @@ use super::*; -pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { - if gen.sys { - gen_sys_handle(gen, def) +pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { + if writer.sys { + gen_sys_handle(writer, def) } else { - gen_win_handle(gen, def) + gen_win_handle(writer, 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 fn gen_sys_handle(writer: &Writer, def: TypeDef) -> TokenStream { + let ident = to_ident(writer.reader.type_def_name(def)); + match writer.reader.type_def_underlying_type(def) { + Type::ISize if writer.std => quote! { pub type #ident = *mut ::core::ffi::c_void; }, - Type::USize if gen.std => quote! { + Type::USize if writer.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); + let signature = writer.type_default_name(&underlying_type); quote! { pub type #ident = #signature; @@ -30,11 +30,11 @@ pub fn gen_sys_handle(gen: &Gen, def: TypeDef) -> TokenStream { } } -pub fn gen_win_handle(gen: &Gen, def: TypeDef) -> TokenStream { - let name = gen.reader.type_def_name(def); +pub fn gen_win_handle(writer: &Writer, def: TypeDef) -> TokenStream { + let name = writer.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 underlying_type = writer.reader.type_def_underlying_type(def); + let signature = writer.type_default_name(&underlying_type); let check = if underlying_type.is_pointer() { quote! { impl #ident { @@ -44,7 +44,7 @@ pub fn gen_win_handle(gen: &Gen, def: TypeDef) -> TokenStream { } } } else { - let invalid = gen.reader.type_def_invalid_values(def); + let invalid = writer.reader.type_def_invalid_values(def); if !invalid.is_empty() { let invalid = invalid.iter().map(|value| { @@ -95,9 +95,9 @@ pub fn gen_win_handle(gen: &Gen, def: TypeDef) -> TokenStream { } }; - 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); + if let Some(dependency) = writer.reader.type_def_usable_for(def) { + let type_name = writer.reader.type_def_type_name(dependency); + let mut dependency = writer.namespace(type_name.namespace); dependency.push_str(type_name.name); tokens.combine("e! { diff --git a/crates/tools/riddle/src/rust/implements.rs b/crates/tools/riddle/src/rust/implements.rs index 8f43a95aeb..e6dbe9513c 100644 --- a/crates/tools/riddle/src/rust/implements.rs +++ b/crates/tools/riddle/src/rust/implements.rs @@ -1,30 +1,30 @@ use super::*; -pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { - if gen.reader.type_def_kind(def) != TypeKind::Interface - || (!gen.implement && !gen.reader.type_def_can_implement(def)) +pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { + if writer.reader.type_def_kind(def) != TypeKind::Interface + || (!writer.implement && !writer.reader.type_def_can_implement(def)) { return quote! {}; } - let generics: &Vec = &gen.reader.type_def_generics(def).collect(); - let type_ident = to_ident(gen.reader.type_def_name(def)); + let generics = &writer.reader.type_def_generics(def); + let type_ident = to_ident(writer.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 constraints = writer.generic_constraints(generics); + let generic_names = writer.generic_names(generics); + let named_phantoms = writer.generic_named_phantoms(generics); + let cfg = writer.reader.type_def_cfg_impl(def, generics); + let doc = writer.cfg_doc(&cfg); + let features = writer.cfg_features(&cfg); let mut requires = quote! {}; let type_ident = quote! { #type_ident<#generic_names> }; - let vtables = gen.reader.type_def_vtables(def); + let vtables = writer.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"); + fn gen_required_trait(writer: &Writer, def: TypeDef, generics: &[Type]) -> TokenStream { + let name = writer.type_def_name_imp(def, generics, "_Impl"); quote! { + #name } @@ -33,12 +33,12 @@ pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { 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, &[])) + requires.combine(&gen_required_trait(writer, *def, &[])) } for def in &vtables { if let Type::TypeDef(def, generics) = def { - let name = gen.type_def_name(*def, generics); + let name = writer.type_def_name(*def, generics); matches.combine("e! { || iid == &<#name as ::windows_core::ComInterface>::IID @@ -46,43 +46,44 @@ pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { } } - if gen + if writer .reader .type_def_flags(def) .contains(TypeAttributes::WindowsRuntime) { // TODO: this awkward wrapping of TypeDefs needs fixing - for interface in gen + for interface in writer .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)); + requires.combine(&gen_required_trait(writer, def, &generics)); } } } - let runtime_name = gen.runtime_name_trait(def, generics, &type_ident, &constraints, &features); + let runtime_name = + writer.runtime_name_trait(def, generics, &type_ident, &constraints, &features); let mut method_names = MethodNames::new(); - method_names.add_vtable_types(gen, def); + method_names.add_vtable_types(writer, 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); + let method_traits = writer.reader.type_def_methods(def).map(|method| { + let name = method_names.add(writer, method); + let signature = writer.reader.method_def_signature(method, generics); + let signature_tokens = writer.impl_signature(def, &signature); quote! { fn #name #signature_tokens; } }); let mut method_names = MethodNames::new(); - method_names.add_vtable_types(gen, def); + method_names.add_vtable_types(writer, 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 method_impls = writer.reader.type_def_methods(def).map(|method| { + let name = method_names.add(writer, method); + let signature = writer.reader.method_def_signature(method, generics); + let vtbl_signature = writer.vtbl_signature(def, generics, &signature); - let invoke_upcall = if gen.reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime) { winrt_methods::gen_upcall(gen, &signature, quote! { this.#name }) } else { com_methods::gen_upcall(gen, &signature, quote! { this.#name }) }; + let invoke_upcall = if writer.reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime) { winrt_methods::gen_upcall(writer, &signature, quote! { this.#name }) } else { com_methods::gen_upcall(writer, &signature, quote! { this.#name }) }; if has_unknown_base { quote! { @@ -110,7 +111,7 @@ pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { Some(Type::IUnknown) => methods.combine("e! { base__: ::windows_core::IUnknown_Vtbl::new::(), }), Some(Type::IInspectable) => methods.combine("e! { base__: ::windows_core::IInspectable_Vtbl::new::(), }), Some(Type::TypeDef(def, generics)) => { - let name = gen.type_def_name_imp(*def, generics, "_Vtbl"); + let name = writer.type_def_name_imp(*def, generics, "_Vtbl"); if has_unknown_base { methods.combine("e! { base__: #name::new::(), }); } else { @@ -121,10 +122,10 @@ pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { } let mut method_names = MethodNames::new(); - method_names.add_vtable_types(gen, def); + method_names.add_vtable_types(writer, def); - for method in gen.reader.type_def_methods(def) { - let name = method_names.add(gen, method); + for method in writer.reader.type_def_methods(def) { + let name = method_names.add(writer, method); if has_unknown_base { methods.combine("e! { #name: #name::<#generic_names Identity, Impl, OFFSET>, }); } else { diff --git a/crates/tools/riddle/src/rust/interfaces.rs b/crates/tools/riddle/src/rust/interfaces.rs index 5b191a30c6..3d9466938a 100644 --- a/crates/tools/riddle/src/rust/interfaces.rs +++ b/crates/tools/riddle/src/rust/interfaces.rs @@ -1,18 +1,18 @@ use super::*; -pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { - if gen.sys { - gen_sys_interface(gen, def) +pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { + if writer.sys { + gen_sys_interface(writer, def) } else { - gen_win_interface(gen, def) + gen_win_interface(writer, def) } } -fn gen_sys_interface(gen: &Gen, def: TypeDef) -> TokenStream { - let name = gen.reader.type_def_name(def); +fn gen_sys_interface(writer: &Writer, def: TypeDef) -> TokenStream { + let name = writer.reader.type_def_name(def); let ident = to_ident(name); - if gen.reader.type_def_is_exclusive(def) { + if writer.reader.type_def_is_exclusive(def) { quote! {} } else { quote! { @@ -21,19 +21,19 @@ fn gen_sys_interface(gen: &Gen, def: TypeDef) -> TokenStream { } } -fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream { - let generics: &Vec = &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 +fn gen_win_interface(writer: &Writer, def: TypeDef) -> TokenStream { + let generics = &writer.reader.type_def_generics(def); + let ident = writer.type_def_name(def, generics); + let is_exclusive = writer.reader.type_def_is_exclusive(def); + let phantoms = writer.generic_phantoms(generics); + let constraints = writer.generic_constraints(generics); + let cfg = writer.reader.type_def_cfg(def, &[]); + let doc = writer.cfg_doc(&cfg); + let features = writer.cfg_features(&cfg); + let interfaces = writer .reader .type_interfaces(&Type::TypeDef(def, generics.to_vec())); - let vtables = gen.reader.type_def_vtables(def); + let vtables = writer.reader.type_def_vtables(def); let has_unknown_base = matches!(vtables.first(), Some(Type::IUnknown)); let mut tokens = if is_exclusive { @@ -63,14 +63,14 @@ fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream { let method_names = &mut MethodNames::new(); let virtual_names = &mut MethodNames::new(); - if gen + if writer .reader .type_def_flags(def) .contains(TypeAttributes::WindowsRuntime) { - for method in gen.reader.type_def_methods(def) { - methods.combine(&winrt_methods::gen( - gen, + for method in writer.reader.type_def_methods(def) { + methods.combine(&winrt_methods::writer( + writer, def, generics, InterfaceKind::Default, @@ -81,9 +81,9 @@ fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream { } 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, + for method in writer.reader.type_def_methods(*def) { + methods.combine(&winrt_methods::writer( + writer, *def, generics, InterfaceKind::None, @@ -100,14 +100,15 @@ fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream { match ty { Type::IUnknown | Type::IInspectable => {} Type::TypeDef(def, _) => { - let kind = if gen.reader.type_def_type_name(*def) == TypeName::IDispatch { + let kind = if writer.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, + for method in writer.reader.type_def_methods(*def) { + methods.combine(&com_methods::writer( + writer, *def, kind, method, @@ -122,9 +123,9 @@ fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream { bases -= 1; } - for method in gen.reader.type_def_methods(def) { - methods.combine(&com_methods::gen( - gen, + for method in writer.reader.type_def_methods(def) { + methods.combine(&com_methods::writer( + writer, def, InterfaceKind::Default, method, @@ -147,19 +148,19 @@ fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream { let mut hierarchy_cfg = cfg.clone(); for ty in &vtables { - let into = gen.type_name(ty); + let into = writer.type_name(ty); write!(&mut hierarchy, ", {into}").unwrap(); - hierarchy_cfg = hierarchy_cfg.union(&gen.reader.type_cfg(ty)); + hierarchy_cfg = hierarchy_cfg.union(&writer.reader.type_cfg(ty)); } hierarchy.push_str(");"); - tokens.combine(&gen.cfg_features(&hierarchy_cfg)); + tokens.combine(&writer.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))); + let into = writer.type_name(ty); + let cfg = writer.cfg_features(&cfg.union(&writer.reader.type_cfg(ty))); tokens.combine("e! { #cfg impl<#constraints> ::windows_core::CanInto<#into> for #ident {} @@ -167,14 +168,14 @@ fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream { } } - if gen + if writer .reader .type_def_flags(def) .contains(TypeAttributes::WindowsRuntime) { for interface in &interfaces { - let into = gen.type_name(&interface.ty); - let cfg = gen.cfg_features(&cfg.union(&gen.reader.type_cfg(&interface.ty))); + let into = writer.type_name(&interface.ty); + let cfg = writer.cfg_features(&cfg.union(&writer.reader.type_cfg(&interface.ty))); tokens.combine("e! { #cfg impl<#constraints> ::windows_core::CanTryInto<#into> for #ident {} @@ -182,7 +183,7 @@ fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream { } } - tokens.combine(&gen.interface_core_traits( + tokens.combine(&writer.interface_core_traits( def, generics, &ident, @@ -190,7 +191,7 @@ fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream { &phantoms, &features, )); - tokens.combine(&gen.interface_winrt_trait( + tokens.combine(&writer.interface_winrt_trait( def, generics, &ident, @@ -198,9 +199,16 @@ fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream { &phantoms, &features, )); - tokens.combine(&gen.async_get(def, generics, &ident, &constraints, &phantoms, &features)); - tokens.combine(&iterators::gen( - gen, + tokens.combine(&writer.async_get( + def, + generics, + &ident, + &constraints, + &phantoms, + &features, + )); + tokens.combine(&iterators::writer( + writer, def, generics, &ident, @@ -208,10 +216,10 @@ fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream { &phantoms, &cfg, )); - tokens.combine(&gen.agile(def, &ident, &constraints, &features)); + tokens.combine(&writer.agile(def, &ident, &constraints, &features)); } - tokens.combine(&gen.interface_trait( + tokens.combine(&writer.interface_trait( def, generics, &ident, @@ -219,6 +227,6 @@ fn gen_win_interface(gen: &Gen, def: TypeDef) -> TokenStream { &features, has_unknown_base, )); - tokens.combine(&gen.interface_vtbl(def, generics, &ident, &constraints, &features)); + tokens.combine(&writer.interface_vtbl(def, generics, &ident, &constraints, &features)); tokens } diff --git a/crates/tools/riddle/src/rust/iterators.rs b/crates/tools/riddle/src/rust/iterators.rs index 66f2a55a72..1b2186af01 100644 --- a/crates/tools/riddle/src/rust/iterators.rs +++ b/crates/tools/riddle/src/rust/iterators.rs @@ -1,7 +1,7 @@ use super::*; -pub fn gen( - gen: &Gen, +pub fn writer( + writer: &Writer, def: TypeDef, generics: &[Type], ident: &TokenStream, @@ -9,7 +9,7 @@ pub fn gen( _phantoms: &TokenStream, cfg: &Cfg, ) -> TokenStream { - match gen.reader.type_def_type_name(def) { + match writer.reader.type_def_type_name(def) { // If the type is IIterator then simply implement the Iterator trait over top. TypeName::IIterator => { return quote! { @@ -149,9 +149,9 @@ pub fn gen( _ => {} } - let wfc = gen.namespace("Windows.Foundation.Collections"); + let wfc = writer.namespace("Windows.Foundation.Collections"); let mut iterable = None; - let interfaces = gen + let interfaces = writer .reader .type_interfaces(&Type::TypeDef(def, generics.to_vec())); @@ -159,13 +159,14 @@ pub fn gen( // 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) { + match writer.reader.type_def_type_name(*interface) { TypeName::IVectorView => { - let item = gen.type_name(&interface_generics[0]); + let item = writer.type_name(&interface_generics[0]); let mut cfg = cfg.clone(); - gen.reader + writer + .reader .type_def_cfg_combine(*interface, interface_generics, &mut cfg); - let features = gen.cfg_features(&cfg); + let features = writer.cfg_features(&cfg); return quote! { #features @@ -189,11 +190,12 @@ pub fn gen( }; } TypeName::IVector => { - let item = gen.type_name(&interface_generics[0]); + let item = writer.type_name(&interface_generics[0]); let mut cfg = cfg.clone(); - gen.reader + writer + .reader .type_def_cfg_combine(*interface, interface_generics, &mut cfg); - let features = gen.cfg_features(&cfg); + let features = writer.cfg_features(&cfg); return quote! { #features @@ -227,11 +229,12 @@ pub fn gen( match iterable { None => TokenStream::new(), Some((interface, interface_generics)) => { - let item = gen.type_name(&interface_generics[0]); + let item = writer.type_name(&interface_generics[0]); let mut cfg = cfg.clone(); - gen.reader + writer + .reader .type_def_cfg_combine(interface, &interface_generics, &mut cfg); - let features = gen.cfg_features(&cfg); + let features = writer.cfg_features(&cfg); quote! { #features diff --git a/crates/tools/riddle/src/rust/method_names.rs b/crates/tools/riddle/src/rust/method_names.rs index 97698777a6..1b2d595e10 100644 --- a/crates/tools/riddle/src/rust/method_names.rs +++ b/crates/tools/riddle/src/rust/method_names.rs @@ -7,8 +7,8 @@ impl MethodNames { Self(BTreeMap::new()) } - pub fn add(&mut self, gen: &Gen, method: MethodDef) -> TokenStream { - let name = gen.reader.method_def_special_name(method); + pub fn add(&mut self, writer: &Writer, method: MethodDef) -> TokenStream { + let name = writer.reader.method_def_special_name(method); let overload = self.0.entry(name.to_string()).or_insert(0); *overload += 1; if *overload > 1 { @@ -18,11 +18,11 @@ impl MethodNames { } } - pub fn add_vtable_types(&mut self, gen: &Gen, def: TypeDef) { - for def in gen.reader.type_def_vtables(def) { + pub fn add_vtable_types(&mut self, writer: &Writer, def: TypeDef) { + for def in writer.reader.type_def_vtables(def) { if let Type::TypeDef(def, _) = def { - for method in gen.reader.type_def_methods(def) { - self.add(gen, method); + for method in writer.reader.type_def_methods(def) { + self.add(writer, method); } } } diff --git a/crates/tools/riddle/src/rust/mod.rs b/crates/tools/riddle/src/rust/mod.rs index b9aaef12ad..063d59c9ca 100644 --- a/crates/tools/riddle/src/rust/mod.rs +++ b/crates/tools/riddle/src/rust/mod.rs @@ -5,7 +5,6 @@ mod delegates; mod enums; mod extensions; mod functions; -mod gen; mod handles; mod implements; mod interfaces; @@ -15,6 +14,7 @@ mod standalone; mod structs; mod try_format; mod winrt_methods; +mod writer; use crate::{Error, Result, Tree}; use rayon::prelude::*; @@ -24,64 +24,64 @@ pub fn from_reader( mut config: std::collections::BTreeMap<&str, &str>, output: &str, ) -> Result<()> { - let mut gen = Gen::new(reader, filter, output); - gen.package = config.remove("PACKAGE").is_some(); - gen.flatten = config.remove("FLATTEN").is_some(); - gen.std = config.remove("STD").is_some(); - gen.sys = gen.std || config.remove("SYS").is_some(); - gen.implement = config.remove("IMPLEMENT").is_some(); - gen.minimal = config.remove("MINIMAL").is_some(); + let mut writer = Writer::new(reader, filter, output); + writer.package = config.remove("PACKAGE").is_some(); + writer.flatten = config.remove("FLATTEN").is_some(); + writer.std = config.remove("STD").is_some(); + writer.sys = writer.std || config.remove("SYS").is_some(); + writer.implement = config.remove("IMPLEMENT").is_some(); + writer.minimal = config.remove("MINIMAL").is_some(); // TODO: get rid of this hack so it can work with any metadata - if gen.flatten { - gen.namespace = "Windows."; + if writer.flatten { + writer.namespace = "Windows."; } - if gen.package && gen.flatten { + if writer.package && writer.flatten { return Err(Error::new( "cannot combine PACKAGE and FLATTEN configuration values", )); } - if gen.implement && gen.sys { + if writer.implement && writer.sys { return Err(Error::new( "cannot combine IMPLEMENT and SYS configuration values", )); } if let Some((key, _)) = config.first_key_value() { - return Err(Error::new(&format!("invalid configuration value: `{key}`"))); + return Err(Error::new(&format!("invalid configuration value `{key}`"))); } - if gen.package { - gen_package(&gen) + if writer.package { + gen_package(&writer) } else { - gen_file(&gen) + gen_file(&writer) } } -fn gen_file(gen: &Gen) -> Result<()> { +fn gen_file(writer: &Writer) -> Result<()> { // TODO: harmonize this output code so we don't need these two wildly differnt code paths // there should be a simple way to generate the with or without namespaces. - if gen.flatten { - let tokens = standalone::standalone_imp(gen, gen.filter.includes()); - crate::write_to_file(gen.output, try_format(gen, &tokens)) + if writer.flatten { + let tokens = standalone::standalone_imp(writer, writer.filter.includes()); + crate::write_to_file(writer.output, try_format(writer, &tokens)) } else { let mut tokens = String::new(); - let root = Tree::new(gen.reader, gen.filter); + let root = Tree::new(writer.reader, writer.filter); for tree in root.nested.values() { - tokens.push_str(&namespace(gen, tree)); + tokens.push_str(&namespace(writer, tree)); } - crate::write_to_file(gen.output, try_format(gen, &tokens)) + crate::write_to_file(writer.output, try_format(writer, &tokens)) } } -fn gen_package(gen: &Gen) -> Result<()> { - let directory = crate::directory(gen.output); - let root = Tree::new(gen.reader, gen.filter); +fn gen_package(writer: &Writer) -> Result<()> { + let directory = crate::directory(writer.output); + let root = Tree::new(writer.reader, writer.filter); let mut root_len = 0; for tree in root.nested.values() { @@ -93,24 +93,24 @@ fn gen_package(gen: &Gen) -> Result<()> { trees.par_iter().try_for_each(|tree| { let directory = format!("{directory}/{}", tree.namespace.replace('.', "/")); - let mut tokens = namespace(gen, tree); + let mut tokens = namespace(writer, tree); - let tokens_impl = if !gen.sys { - namespace_impl(gen, tree) + let tokens_impl = if !writer.sys { + namespace_impl(writer, tree) } else { String::new() }; - if !gen.sys && !tokens_impl.is_empty() { + if !writer.sys && !tokens_impl.is_empty() { tokens.push_str("#[cfg(feature = \"implement\")]\n::core::include!(\"impl.rs\");\n"); } let output = format!("{directory}/mod.rs"); - crate::write_to_file(&output, try_format(gen, &tokens))?; + crate::write_to_file(&output, try_format(writer, &tokens))?; - if !gen.sys && !tokens_impl.is_empty() { + if !writer.sys && !tokens_impl.is_empty() { let output = format!("{directory}/impl.rs"); - crate::write_to_file(&output, try_format(gen, &tokens_impl))?; + crate::write_to_file(&output, try_format(writer, &tokens_impl))?; } Ok::<(), Error>(()) @@ -144,23 +144,23 @@ fn gen_package(gen: &Gen) -> Result<()> { } use crate::tokens::*; -use gen::*; use metadata::*; use method_names::*; use std::collections::*; use std::fmt::Write; use try_format::*; +use writer::*; -fn namespace(gen: &Gen, tree: &Tree) -> String { - let gen = &mut gen.clone(); - gen.namespace = tree.namespace; +fn namespace(writer: &Writer, tree: &Tree) -> String { + let writer = &mut writer.clone(); + writer.namespace = tree.namespace; let mut tokens = TokenStream::new(); for (name, tree) in &tree.nested { let name = to_ident(name); let namespace_feature = tree.namespace[tree.namespace.find('.').unwrap() + 1..].replace('.', "_"); - if gen.package { + if writer.package { tokens.combine("e! { #[cfg(feature = #namespace_feature)] pub mod #name; @@ -168,7 +168,7 @@ fn namespace(gen: &Gen, tree: &Tree) -> String { } else { tokens.combine("e! { pub mod #name }); tokens.push_str("{"); - tokens.push_str(&namespace(gen, tree)); + tokens.push_str(&namespace(writer, tree)); tokens.push_str("}"); } } @@ -176,29 +176,29 @@ fn namespace(gen: &Gen, tree: &Tree) -> String { let mut functions = BTreeMap::<&str, TokenStream>::new(); let mut types = BTreeMap::>::new(); - for method in gen.reader.namespace_functions(tree.namespace) { - let name = gen.reader.method_def_name(method); + for method in writer.reader.namespace_functions(tree.namespace) { + let name = writer.reader.method_def_name(method); functions .entry(name) .or_default() - .combine(&functions::gen(gen, method)); + .combine(&functions::writer(writer, method)); } - for field in gen.reader.namespace_constants(tree.namespace) { - let name = gen.reader.field_name(field); + for field in writer.reader.namespace_constants(tree.namespace) { + let name = writer.reader.field_name(field); types .entry(TypeKind::Class) .or_default() .entry(name) .or_default() - .combine(&constants::gen(gen, field)); + .combine(&constants::writer(writer, field)); } - for def in gen + for def in writer .reader .namespace_types(tree.namespace, &Default::default()) { - let type_name = gen.reader.type_def_type_name(def); + let type_name = writer.reader.type_def_type_name(def); if REMAP_TYPES.iter().any(|(x, _)| x == &type_name) { continue; } @@ -206,10 +206,10 @@ fn namespace(gen: &Gen, tree: &Tree) -> String { continue; } let name = type_name.name; - let kind = gen.reader.type_def_kind(def); + let kind = writer.reader.type_def_kind(def); match kind { TypeKind::Class => { - if gen + if writer .reader .type_def_flags(def) .contains(TypeAttributes::WindowsRuntime) @@ -217,7 +217,7 @@ fn namespace(gen: &Gen, tree: &Tree) -> String { types .entry(kind) .or_default() - .insert(name, classes::gen(gen, def)); + .insert(name, classes::writer(writer, def)); } } TypeKind::Interface => types @@ -225,21 +225,21 @@ fn namespace(gen: &Gen, tree: &Tree) -> String { .or_default() .entry(name) .or_default() - .combine(&interfaces::gen(gen, def)), + .combine(&interfaces::writer(writer, def)), TypeKind::Enum => types .entry(kind) .or_default() .entry(name) .or_default() - .combine(&enums::gen(gen, def)), + .combine(&enums::writer(writer, def)), TypeKind::Struct => { - if gen.reader.type_def_fields(def).next().is_none() { - if let Some(guid) = gen.reader.type_def_guid(def) { + if writer.reader.type_def_fields(def).next().is_none() { + if let Some(guid) = writer.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 value = writer.guid(&guid); + let guid = writer.type_name(&Type::GUID); + let cfg = writer.reader.type_def_cfg(def, &[]); + let doc = writer.cfg_doc(&cfg); let constant = quote! { #doc pub const #ident: #guid = #value; @@ -258,14 +258,14 @@ fn namespace(gen: &Gen, tree: &Tree) -> String { .or_default() .entry(name) .or_default() - .combine(&structs::gen(gen, def)); + .combine(&structs::writer(writer, def)); } TypeKind::Delegate => types .entry(kind) .or_default() .entry(name) .or_default() - .combine(&delegates::gen(gen, def)), + .combine(&delegates::writer(writer, def)), } } @@ -277,32 +277,32 @@ fn namespace(gen: &Gen, tree: &Tree) -> String { tokens.combine(ty); } - tokens.combine(&extensions::gen_mod(gen, tree.namespace)); + tokens.combine(&extensions::gen_mod(writer, tree.namespace)); - if gen.implement { - tokens.push_str(&namespace_impl(gen, tree)); + if writer.implement { + tokens.push_str(&namespace_impl(writer, tree)); } tokens.into_string() } -fn namespace_impl(gen: &Gen, tree: &Tree) -> String { - let gen = &mut gen.clone(); - gen.namespace = tree.namespace; +fn namespace_impl(writer: &Writer, tree: &Tree) -> String { + let writer = &mut writer.clone(); + writer.namespace = tree.namespace; let mut types = BTreeMap::<&str, TokenStream>::new(); - for def in gen + for def in writer .reader .namespace_types(tree.namespace, &Default::default()) { - let type_name = gen.reader.type_def_type_name(def); + let type_name = writer.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 { + if writer.reader.type_def_kind(def) != TypeKind::Interface { continue; } - let tokens = implements::gen(gen, def); + let tokens = implements::writer(writer, def); if !tokens.is_empty() { types.insert(type_name.name, tokens); diff --git a/crates/tools/riddle/src/rust/standalone.rs b/crates/tools/riddle/src/rust/standalone.rs index 6fa26c1bf8..997ae63601 100644 --- a/crates/tools/riddle/src/rust/standalone.rs +++ b/crates/tools/riddle/src/rust/standalone.rs @@ -1,28 +1,6 @@ use super::*; -// /// Generates standalone Windows bindings based on the `windows` crate's bindings. -// pub fn standalone_win(reader: &Reader, names: &[&str]) -> String { -// let gen = &mut Gen::new(reader); -// standalone_imp(gen, names) -// } - -// /// Generates standalone Windows bindings based on the `windows-sys` crate's bindings. -// pub fn standalone_sys(reader: &Reader, names: &[&str]) -> String { -// let gen = &mut Gen::new(reader); -// gen.sys = true; -// standalone_imp(gen, names) -// } - -// /// Generates standalone Windows bindings for the Rust Standard Library. -// #[doc(hidden)] -// pub fn standalone_std(reader: &Reader, names: &[&str]) -> String { -// let gen = &mut Gen::new(reader); -// gen.std = true; -// gen.sys = true; -// standalone_imp(gen, names) -// } - -pub fn standalone_imp<'a, I: Iterator>(gen: &Gen, names: I) -> String { +pub fn standalone_imp<'a, I: Iterator>(writer: &Writer, names: I) -> String { let mut types = BTreeSet::new(); let mut functions = BTreeSet::new(); let mut constants = BTreeSet::new(); @@ -31,58 +9,61 @@ pub fn standalone_imp<'a, I: Iterator>(gen: &Gen, names: I) -> S let mut found = false; let type_name = TypeName::parse(name); - for def in gen.reader.get(type_name) { + for def in writer.reader.get(type_name) { found = true; - gen.reader + writer + .reader .type_collect_standalone(&Type::TypeDef(def, vec![]), &mut types); } - for method in gen + for method in writer .reader .namespace_functions(type_name.namespace) - .filter(|method| gen.reader.method_def_name(*method) == type_name.name) + .filter(|method| writer.reader.method_def_name(*method) == type_name.name) { found = true; functions.insert(method); - let signature = gen.reader.method_def_signature(method, &[]); - gen.reader + let signature = writer.reader.method_def_signature(method, &[]); + writer + .reader .type_collect_standalone(&signature.return_type, &mut types); signature .params .iter() - .for_each(|param| gen.reader.type_collect_standalone(¶m.ty, &mut types)); + .for_each(|param| writer.reader.type_collect_standalone(¶m.ty, &mut types)); } - if let Some(field) = gen + if let Some(field) = writer .reader .namespace_constants(type_name.namespace) - .find(|field| gen.reader.field_name(*field) == type_name.name) + .find(|field| writer.reader.field_name(*field) == type_name.name) { found = true; constants.insert(field); - gen.reader.type_collect_standalone( - &gen.reader.field_type(field, None).to_const_type(), + writer.reader.type_collect_standalone( + &writer.reader.field_type(field, None).to_const_type(), &mut types, ); } - if let Some(field) = gen + if let Some(field) = writer .reader .namespace_types(type_name.namespace, &Default::default()) .find_map(|def| { - if gen.reader.type_def_kind(def) == TypeKind::Enum { - return gen + if writer.reader.type_def_kind(def) == TypeKind::Enum { + return writer .reader .type_def_fields(def) - .find(|field| gen.reader.field_name(*field) == type_name.name); + .find(|field| writer.reader.field_name(*field) == type_name.name); } None }) { found = true; constants.insert(field); - gen.reader - .type_collect_standalone(&gen.reader.field_type(field, None), &mut types); + writer + .reader + .type_collect_standalone(&writer.reader.field_type(field, None), &mut types); } assert!(found, "{} not found", type_name); @@ -92,31 +73,35 @@ pub fn standalone_imp<'a, I: Iterator>(gen: &Gen, names: I) -> S for ty in types { match ty { - Type::HRESULT if gen.sys => { + Type::HRESULT if writer.sys => { sorted.insert("HRESULT", quote! { pub type HRESULT = i32; }) } - Type::String if gen.sys => sorted.insert( + Type::String if writer.sys => sorted.insert( "HSTRING", quote! { pub type HSTRING = *mut ::core::ffi::c_void; }, ), - Type::IUnknown if gen.sys => sorted.insert( + Type::IUnknown if writer.sys => sorted.insert( "IUnknown", quote! { pub type IUnknown = *mut ::core::ffi::c_void; }, ), - Type::IInspectable if gen.sys => sorted.insert( + Type::IInspectable if writer.sys => sorted.insert( "IInspectable", quote! { pub type IInspectable = *mut ::core::ffi::c_void; }, ), - Type::PSTR if gen.sys => sorted.insert("PSTR", quote! { pub type PSTR = *mut u8; }), - Type::PWSTR if gen.sys => sorted.insert("PWSTR", quote! { pub type PWSTR = *mut u16; }), - Type::PCSTR if gen.sys => { + Type::PSTR if writer.sys => sorted.insert("PSTR", quote! { pub type PSTR = *mut u8; }), + Type::PWSTR if writer.sys => { + sorted.insert("PWSTR", quote! { pub type PWSTR = *mut u16; }) + } + Type::PCSTR if writer.sys => { sorted.insert("PCSTR", quote! { pub type PCSTR = *const u8; }) } - Type::PCWSTR if gen.sys => { + Type::PCWSTR if writer.sys => { sorted.insert("PCWSTR", quote! { pub type PCWSTR = *const u16; }) } - Type::BSTR if gen.sys => sorted.insert("BSTR", quote! { pub type BSTR = *const u16; }), - Type::GUID if gen.sys => { + Type::BSTR if writer.sys => { + sorted.insert("BSTR", quote! { pub type BSTR = *const u16; }) + } + Type::GUID if writer.sys => { sorted.insert("GUID", quote! { #[repr(C)] pub struct GUID { @@ -139,42 +124,42 @@ pub fn standalone_imp<'a, I: Iterator>(gen: &Gen, names: I) -> S }); } Type::TypeDef(def, _) => { - let kind = gen.reader.type_def_kind(def); + let kind = writer.reader.type_def_kind(def); match kind { TypeKind::Class => { - let name = gen.reader.type_def_name(def); - if gen.sys { + let name = writer.reader.type_def_name(def); + if writer.sys { let ident = to_ident(name); sorted.insert( name, quote! { pub type #ident = *mut ::core::ffi::c_void; }, ); } else { - sorted.insert(name, classes::gen(gen, def)); + sorted.insert(name, classes::writer(writer, def)); } } TypeKind::Interface => { - let name = gen.reader.type_def_name(def); - if gen.sys { + let name = writer.reader.type_def_name(def); + if writer.sys { let ident = to_ident(name); sorted.insert( name, quote! { pub type #ident = *mut ::core::ffi::c_void; }, ); } else { - sorted.insert(name, interfaces::gen(gen, def)); + sorted.insert(name, interfaces::writer(writer, def)); } } TypeKind::Enum => { - sorted.insert(gen.reader.type_def_name(def), enums::gen(gen, def)); + sorted.insert(writer.reader.type_def_name(def), enums::writer(writer, def)); } TypeKind::Struct => { - let name = gen.reader.type_def_name(def); - if gen.reader.type_def_fields(def).next().is_none() { - if let Some(guid) = gen.reader.type_def_guid(def) { + let name = writer.reader.type_def_name(def); + if writer.reader.type_def_fields(def).next().is_none() { + if let Some(guid) = writer.reader.type_def_guid(def) { let ident = to_ident(name); - let value = gen.guid(&guid); - let guid = gen.type_name(&Type::GUID); + let value = writer.guid(&guid); + let guid = writer.type_name(&Type::GUID); sorted.insert( name, quote! { @@ -184,10 +169,13 @@ pub fn standalone_imp<'a, I: Iterator>(gen: &Gen, names: I) -> S continue; } } - sorted.insert(name, structs::gen(gen, def)); + sorted.insert(name, structs::writer(writer, def)); } TypeKind::Delegate => { - sorted.insert(gen.reader.type_def_name(def), delegates::gen(gen, def)); + sorted.insert( + writer.reader.type_def_name(def), + delegates::writer(writer, def), + ); } } } @@ -199,17 +187,17 @@ pub fn standalone_imp<'a, I: Iterator>(gen: &Gen, names: I) -> S sorted.insert( &format!( ".{}.{}", - gen.reader.method_def_module_name(function), - gen.reader.method_def_name(function) + writer.reader.method_def_module_name(function), + writer.reader.method_def_name(function) ), - functions::gen(gen, function), + functions::writer(writer, function), ); } for constant in constants { sorted.insert( - gen.reader.field_name(constant), - constants::gen(gen, constant), + writer.reader.field_name(constant), + constants::writer(writer, constant), ); } diff --git a/crates/tools/riddle/src/rust/structs.rs b/crates/tools/riddle/src/rust/structs.rs index 6b98bdc642..510e008bfe 100644 --- a/crates/tools/riddle/src/rust/structs.rs +++ b/crates/tools/riddle/src/rust/structs.rs @@ -1,21 +1,31 @@ use super::*; -pub fn gen(gen: &Gen, def: TypeDef) -> TokenStream { - if gen.reader.type_def_is_contract(def) { +pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream { + if writer.reader.type_def_is_contract(def) { return quote! {}; } - if gen.reader.type_def_is_handle(def) { - return handles::gen(gen, def); + if writer.reader.type_def_is_handle(def) { + return handles::writer(writer, def); } - gen_struct_with_name(gen, def, gen.reader.type_def_name(def), &Cfg::default()) + gen_struct_with_name( + writer, + def, + writer.reader.type_def_name(def), + &Cfg::default(), + ) } -fn gen_struct_with_name(gen: &Gen, def: TypeDef, struct_name: &str, cfg: &Cfg) -> TokenStream { +fn gen_struct_with_name( + writer: &Writer, + def: TypeDef, + struct_name: &str, + cfg: &Cfg, +) -> TokenStream { let name = to_ident(struct_name); - if gen.reader.type_def_fields(def).next().is_none() { + if writer.reader.type_def_fields(def).next().is_none() { let mut tokens = quote! { #[repr(C)] pub struct #name(pub u8); @@ -26,7 +36,7 @@ fn gen_struct_with_name(gen: &Gen, def: TypeDef, struct_name: &str, cfg: &Cfg) - } } }; - if !gen.sys { + if !writer.sys { tokens.combine("e! { impl ::windows_core::TypeKind for #name { type TypeKind = ::windows_core::CopyType; @@ -36,41 +46,45 @@ fn gen_struct_with_name(gen: &Gen, def: TypeDef, struct_name: &str, cfg: &Cfg) - return tokens; } - let flags = gen.reader.type_def_flags(def); - let cfg = cfg.union(&gen.reader.type_def_cfg(def, &[])); + let flags = writer.reader.type_def_flags(def); + let cfg = cfg.union(&writer.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)); + let repr = if let Some(layout) = writer.reader.type_def_class_layout(def) { + let packing = Literal::usize_unsuffixed(writer.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)); + let fields = writer.reader.type_def_fields(def).map(|f| { + let name = to_ident(writer.reader.field_name(f)); + let ty = writer.reader.field_type(f, Some(def)); - if gen.reader.field_flags(f).contains(FieldAttributes::Literal) { + if writer + .reader + .field_flags(f) + .contains(FieldAttributes::Literal) + { quote! {} - } else if !gen.sys + } else if !writer.sys && flags.contains(TypeAttributes::ExplicitLayout) - && !gen.reader.field_is_copyable(f, def) + && !writer.reader.field_is_copyable(f, def) { - let ty = gen.type_default_name(&ty); + let ty = writer.type_default_name(&ty); quote! { pub #name: ::std::mem::ManuallyDrop<#ty>, } - } else if !gen.sys + } else if !writer.sys && !flags.contains(TypeAttributes::WindowsRuntime) - && !gen.reader.field_is_blittable(f, def) + && !writer.reader.field_is_blittable(f, def) { if let Type::Win32Array(ty, len) = ty { - let ty = gen.type_default_name(&ty); + let ty = writer.type_default_name(&ty); quote! { pub #name: [::std::mem::ManuallyDrop<#ty>; #len], } } else { - let ty = gen.type_default_name(&ty); + let ty = writer.type_default_name(&ty); quote! { pub #name: ::std::mem::ManuallyDrop<#ty>, } } } else { - let ty = gen.type_default_name(&ty); + let ty = writer.type_default_name(&ty); quote! { pub #name: #ty, } } }); @@ -81,8 +95,8 @@ fn gen_struct_with_name(gen: &Gen, def: TypeDef, struct_name: &str, cfg: &Cfg) - quote! { struct } }; - let doc = gen.cfg_doc(&cfg); - let features = gen.cfg_features(&cfg); + let doc = writer.cfg_doc(&cfg); + let features = writer.cfg_features(&cfg); let mut tokens = quote! { #repr @@ -91,13 +105,13 @@ fn gen_struct_with_name(gen: &Gen, def: TypeDef, struct_name: &str, cfg: &Cfg) - 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)); + tokens.combine(&gen_struct_constants(writer, def, &name, &cfg)); + tokens.combine(&gen_copy_clone(writer, def, &name, &cfg)); + tokens.combine(&gen_debug(writer, def, &name, &cfg)); + tokens.combine(&gen_windows_traits(writer, def, &name, &cfg)); + tokens.combine(&gen_compare_traits(writer, def, &name, &cfg)); - if !gen.sys { + if !writer.sys { tokens.combine("e! { #features impl ::core::default::Default for #name { @@ -108,20 +122,25 @@ fn gen_struct_with_name(gen: &Gen, def: TypeDef, struct_name: &str, cfg: &Cfg) - }); } - for (index, nested_type) in gen.reader.nested_types(def).enumerate() { + for (index, nested_type) in writer.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.combine(&gen_struct_with_name( + writer, + nested_type, + &nested_name, + &cfg, + )); } tokens } -fn gen_windows_traits(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { - if gen.sys { +fn gen_windows_traits(writer: &Writer, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { + if writer.sys { quote! {} } else { - let features = gen.cfg_features(cfg); - let is_copy = gen.reader.type_def_is_blittable(def); + let features = writer.cfg_features(cfg); + let is_copy = writer.reader.type_def_is_blittable(def); let type_kind = if is_copy { quote! { CopyType } @@ -136,13 +155,13 @@ fn gen_windows_traits(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> } }; - if gen + if writer .reader .type_def_flags(def) .contains(TypeAttributes::WindowsRuntime) { let signature = - Literal::byte_string(gen.reader.type_def_signature(def, &[]).as_bytes()); + Literal::byte_string(writer.reader.type_def_signature(def, &[]).as_bytes()); tokens.combine("e! { #features @@ -156,19 +175,23 @@ fn gen_windows_traits(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> } } -fn gen_compare_traits(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { - let features = gen.cfg_features(cfg); +fn gen_compare_traits(writer: &Writer, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { + let features = writer.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) + if writer.sys + || writer.reader.type_def_has_explicit_layout(def) + || writer.reader.type_def_has_packing(def) + || writer.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) { + let fields = writer.reader.type_def_fields(def).filter_map(|f| { + let name = to_ident(writer.reader.field_name(f)); + if writer + .reader + .field_flags(f) + .contains(FieldAttributes::Literal) + { None } else { Some(quote! { self.#name == other.#name }) @@ -188,24 +211,28 @@ fn gen_compare_traits(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> } } -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) +fn gen_debug(writer: &Writer, def: TypeDef, ident: &TokenStream, cfg: &Cfg) -> TokenStream { + if writer.sys + || writer.reader.type_def_has_explicit_layout(def) + || writer.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) { + let features = writer.cfg_features(cfg); + + let fields = writer.reader.type_def_fields(def).filter_map(|f| { + if writer + .reader + .field_flags(f) + .contains(FieldAttributes::Literal) + { None } else { - let name = gen.reader.field_name(f); + let name = writer.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) { + let ty = writer.reader.field_type(f, Some(def)); + if writer.reader.type_has_callback(&ty) { None } else { Some(quote! { .field(#name, &self.#ident) }) @@ -224,10 +251,10 @@ fn gen_debug(gen: &Gen, def: TypeDef, ident: &TokenStream, cfg: &Cfg) -> TokenSt } } -fn gen_copy_clone(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { - let features = gen.cfg_features(cfg); +fn gen_copy_clone(writer: &Writer, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> TokenStream { + let features = writer.cfg_features(cfg); - if gen.sys || gen.reader.type_def_is_copyable(def) { + if writer.sys || writer.reader.type_def_is_copyable(def) { quote! { #features impl ::core::marker::Copy for #name {} @@ -238,10 +265,10 @@ fn gen_copy_clone(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> Tok } } } - } else if gen.reader.type_def_class_layout(def).is_some() { + } else if writer.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 + } else if !writer .reader .type_def_flags(def) .contains(TypeAttributes::WindowsRuntime) @@ -255,11 +282,15 @@ fn gen_copy_clone(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> Tok } } } 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) { + let fields = writer.reader.type_def_fields(def).map(|f| { + let name = to_ident(writer.reader.field_name(f)); + if writer + .reader + .field_flags(f) + .contains(FieldAttributes::Literal) + { quote! {} - } else if gen.reader.field_is_blittable(f, def) { + } else if writer.reader.field_is_blittable(f, def) { quote! { #name: self.#name } } else { quote! { #name: self.#name.clone() } @@ -278,18 +309,22 @@ fn gen_copy_clone(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> Tok } fn gen_struct_constants( - gen: &Gen, + writer: &Writer, def: TypeDef, struct_name: &TokenStream, cfg: &Cfg, ) -> TokenStream { - let features = gen.cfg_features(cfg); + let features = writer.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)); + let constants = writer.reader.type_def_fields(def).filter_map(|f| { + if writer + .reader + .field_flags(f) + .contains(FieldAttributes::Literal) + { + if let Some(constant) = writer.reader.field_constant(f) { + let name = to_ident(writer.reader.field_name(f)); + let value = writer.typed_value(&writer.reader.constant_value(constant)); return Some(quote! { pub const #name: #value; diff --git a/crates/tools/riddle/src/rust/try_format.rs b/crates/tools/riddle/src/rust/try_format.rs index d8d6d5f221..5247e24e04 100644 --- a/crates/tools/riddle/src/rust/try_format.rs +++ b/crates/tools/riddle/src/rust/try_format.rs @@ -1,10 +1,10 @@ use std::io::Write; -pub fn try_format(gen: &super::Gen, tokens: &str) -> String { +pub fn try_format(writer: &super::Writer, tokens: &str) -> String { let version = std::env!("CARGO_PKG_VERSION"); // Packaging - e.g. windows/windows-sys crates - assumes the crate will allow whatever warnings it deems fit. - let allow = if gen.package { + let allow = if writer.package { "" } else { "#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)]\n" diff --git a/crates/tools/riddle/src/rust/winrt_methods.rs b/crates/tools/riddle/src/rust/winrt_methods.rs index f39e1a9a0a..0ac258e5c8 100644 --- a/crates/tools/riddle/src/rust/winrt_methods.rs +++ b/crates/tools/riddle/src/rust/winrt_methods.rs @@ -1,8 +1,8 @@ use super::*; // TODO take Signature instead of MethodDef (wherever MethodDef is found) -pub fn gen( - gen: &Gen, +pub fn writer( + writer: &Writer, def: TypeDef, generic_types: &[Type], kind: InterfaceKind, @@ -10,25 +10,26 @@ pub fn gen( method_names: &mut MethodNames, virtual_names: &mut MethodNames, ) -> TokenStream { - let signature = gen.reader.method_def_signature(method, generic_types); + let signature = writer.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 + let name = method_names.add(writer, method); + let interface_name = writer.type_def_name(def, generic_types); + let vname = virtual_names.add(writer, method); + let generics = writer.constraint_generics(params); + let where_clause = writer.where_clause(params); + let mut cfg = writer.reader.signature_cfg(&signature); + writer + .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 doc = writer.cfg_method_doc(&cfg); + let features = writer.cfg_features(&cfg); + let args = gen_winrt_abi_args(writer, params); + let params = gen_winrt_params(writer, params); let return_type_tokens = match &signature.return_type { Type::Void => quote! { () }, _ => { - let tokens = gen.type_name(&signature.return_type); + let tokens = writer.type_name(&signature.return_type); if signature.return_type.is_winrt_array() { quote! { ::windows_core::Array<#tokens> } } else { @@ -41,7 +42,7 @@ pub fn gen( Type::Void => quote! {}, _ => { if signature.return_type.is_winrt_array() { - let return_type = gen.type_name(&signature.return_type); + let return_type = writer.type_name(&signature.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__ } @@ -106,27 +107,27 @@ pub fn gen( } } -fn gen_winrt_params(gen: &Gen, params: &[SignatureParam]) -> TokenStream { +fn gen_winrt_params(writer: &Writer, params: &[SignatureParam]) -> TokenStream { let mut result = quote! {}; - let mut generic_params = gen.generic_params(params); + let mut generic_params = writer.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); + let name = writer.param_name(param.def); + let kind = writer.type_name(¶m.ty); + let default_type = writer.type_default_name(¶m.ty); - if gen + if writer .reader .param_flags(param.def) .contains(ParamAttributes::In) { if param.ty.is_winrt_array() { result.combine("e! { #name: &[#default_type], }); - } else if gen.reader.signature_param_is_convertible(param) { + } else if writer.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) { + } else if writer.reader.type_is_blittable(¶m.ty) { result.combine("e! { #name: #kind, }); } else { result.combine("e! { #name: &#kind, }); @@ -143,27 +144,27 @@ fn gen_winrt_params(gen: &Gen, params: &[SignatureParam]) -> TokenStream { result } -fn gen_winrt_abi_args(gen: &Gen, params: &[SignatureParam]) -> TokenStream { +fn gen_winrt_abi_args(writer: &Writer, params: &[SignatureParam]) -> TokenStream { let mut tokens = TokenStream::new(); for param in params { - let name = gen.param_name(param.def); + let name = writer.param_name(param.def); - let param = if gen + let param = if writer .reader .param_flags(param.def) .contains(ParamAttributes::In) { if param.ty.is_winrt_array() { - if gen.reader.type_is_blittable(¶m.ty) { + if writer.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) { + } else if writer.reader.signature_param_is_failible_param(param) { quote! { #name.try_into_param()?.abi(), } - } else if gen.reader.signature_param_is_borrowed(param) { + } else if writer.reader.signature_param_is_borrowed(param) { quote! { #name.into_param().abi(), } - } else if gen.reader.type_is_blittable(¶m.ty) { + } else if writer.reader.type_is_blittable(¶m.ty) { if param.ty.is_const_ref() { quote! { &#name, } } else { @@ -173,14 +174,14 @@ fn gen_winrt_abi_args(gen: &Gen, params: &[SignatureParam]) -> TokenStream { quote! { ::core::mem::transmute_copy(#name), } } } else if param.ty.is_winrt_array() { - if gen.reader.type_is_blittable(¶m.ty) { + if writer.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) { + } else if writer.reader.type_is_blittable(¶m.ty) { quote! { #name, } } else { quote! { #name as *mut _ as _, } @@ -190,11 +191,11 @@ fn gen_winrt_abi_args(gen: &Gen, params: &[SignatureParam]) -> TokenStream { tokens } -pub fn gen_upcall(gen: &Gen, sig: &Signature, inner: TokenStream) -> TokenStream { +pub fn gen_upcall(writer: &Writer, sig: &Signature, inner: TokenStream) -> TokenStream { let invoke_args = sig .params .iter() - .map(|param| gen_winrt_invoke_arg(gen, param)); + .map(|param| gen_winrt_invoke_arg(writer, param)); match &sig.return_type { Type::Void => quote! { @@ -215,7 +216,7 @@ pub fn gen_upcall(gen: &Gen, sig: &Signature, inner: TokenStream) -> TokenStream } } _ => { - let forget = if gen.reader.type_is_blittable(&sig.return_type) { + let forget = if writer.reader.type_is_blittable(&sig.return_type) { quote! {} } else { quote! { ::core::mem::forget(ok__); } @@ -236,23 +237,23 @@ pub fn gen_upcall(gen: &Gen, sig: &Signature, inner: TokenStream) -> TokenStream } } -fn gen_winrt_invoke_arg(gen: &Gen, param: &SignatureParam) -> TokenStream { - let name = gen.param_name(param.def); +fn gen_winrt_invoke_arg(writer: &Writer, param: &SignatureParam) -> TokenStream { + let name = writer.param_name(param.def); let abi_size_name: TokenStream = - format!("{}_array_size", gen.reader.param_name(param.def)).into(); + format!("{}_array_size", writer.reader.param_name(param.def)).into(); - if gen + if writer .reader .param_flags(param.def) .contains(ParamAttributes::In) { 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) { + } else if writer.reader.type_is_primitive(¶m.ty) { quote! { #name } } else if param.ty.is_const_ref() { quote! { ::core::mem::transmute_copy(&#name) } - } else if gen.reader.type_is_nullable(¶m.ty) { + } else if writer.reader.type_is_nullable(¶m.ty) { quote! { ::windows_core::from_raw_borrowed(&#name) } } else { quote! { ::core::mem::transmute(&#name) } diff --git a/crates/tools/riddle/src/rust/gen.rs b/crates/tools/riddle/src/rust/writer.rs similarity index 99% rename from crates/tools/riddle/src/rust/gen.rs rename to crates/tools/riddle/src/rust/writer.rs index aed04e7fb3..9fbda3eea3 100644 --- a/crates/tools/riddle/src/rust/gen.rs +++ b/crates/tools/riddle/src/rust/writer.rs @@ -1,27 +1,26 @@ use super::*; -// TODO: rename to Writer for consistency #[derive(Clone)] -pub struct Gen<'a> { +pub struct Writer<'a> { pub reader: &'a Reader<'a>, pub filter: &'a metadata::Filter<'a>, pub output: &'a str, pub namespace: &'a str, pub implement: bool, // TODO: ideally we can use this to generate implementation traits on the fly and // and have a single interface definition macro for consumption that expands to include - // impl traits when the `implement` cfg flag is set and then this gen option would be + // impl traits when the `implement` cfg flag is set and then this writer option would be // unecessary. // // Maybe this macro is the embedable version of the IDL format?! like a more intelligient // version of the existing interface macro... pub std: bool, // tweaks for internal std library support - pub sys: bool, // gen sys-style bindings + pub sys: bool, // writer sys-style bindings pub flatten: bool, // strips out namespaces - implies !package pub package: bool, // default is single file with no cfg - implies !flatten pub minimal: bool, // strips out enumerators - in future possibly other helpers as well } -impl<'a> Gen<'a> { +impl<'a> Writer<'a> { pub fn new(reader: &'a Reader, filter: &'a metadata::Filter, output: &'a str) -> Self { Self { reader, @@ -714,7 +713,13 @@ impl<'a> Gen<'a> { quote! { ::windows_core::imp::ConstBuffer::from_slice(#type_signature) } } else { let signature = Literal::byte_string( - format!("{{{:#?}}}", self.reader.type_def_guid(def).unwrap()).as_bytes(), + // TODO: workaround for riddle winmd generation (no attribute support) + if let Some(guid) = self.reader.type_def_guid(def) { + format!("{{{:#?}}}", guid) + } else { + "TODO".to_string() + } + .as_bytes(), ); if generics.is_empty() { diff --git a/crates/tools/riddle/src/winmd/mod.rs b/crates/tools/riddle/src/winmd/mod.rs index cb86273f30..88de5bbaec 100644 --- a/crates/tools/riddle/src/winmd/mod.rs +++ b/crates/tools/riddle/src/winmd/mod.rs @@ -1,4 +1,6 @@ mod to_winmd; -pub use to_winmd::from_reader; +mod verify; pub mod writer; +pub use to_winmd::from_reader; +pub use verify::verify; pub use writer::*; diff --git a/crates/tools/riddle/src/winmd/to_winmd.rs b/crates/tools/riddle/src/winmd/to_winmd.rs index 1432f700e2..3db956d43e 100644 --- a/crates/tools/riddle/src/winmd/to_winmd.rs +++ b/crates/tools/riddle/src/winmd/to_winmd.rs @@ -3,12 +3,24 @@ use crate::winmd::{self, writer}; pub fn from_reader( reader: &metadata::Reader, filter: &metadata::Filter, - _config: std::collections::BTreeMap<&str, &str>, + config: std::collections::BTreeMap<&str, &str>, output: &str, ) -> crate::Result<()> { let mut writer = winmd::Writer::new(output); + // TODO: do we need any configuration values for winmd generation? + // Maybe per-namespace winmd files for namespace-splitting - be sure to use + // the same key as for winmd generation. + + if let Some((key, _)) = config.first_key_value() { + return Err(crate::Error::new(&format!( + "invalid configuration value `{key}`" + ))); + } + for def in reader.types(filter) { + let generics = &reader.type_def_generics(def); + let extends = if let Some(extends) = reader.type_def_extends(def) { writer.insert_type_ref(extends.namespace, extends.name) } else { @@ -25,7 +37,7 @@ pub fn from_reader( }); for field in reader.type_def_fields(def) { - let ty = writer_type(reader, &reader.field_type(field, Some(def))); + let ty = winmd_type(reader, &reader.field_type(field, Some(def))); let signature = writer.insert_field_sig(&ty); writer.tables.Field.push(writer::Field { @@ -34,6 +46,29 @@ pub fn from_reader( Signature: signature, }); } + + for method in reader.type_def_methods(def) { + let name = reader.method_def_name(method); + let sig = winmd_signature(reader, &reader.method_def_signature(method, generics)); + let signature = writer.insert_method_sig(&sig); + + writer.tables.MethodDef.push(winmd::MethodDef { + RVA: 0, + ImplFlags: 0, + Flags: 0, + Name: writer.strings.insert(name), + Signature: signature, + ParamList: writer.tables.Param.len() as _, + }); + + for (sequence, param) in sig.params.iter().enumerate() { + writer.tables.Param.push(writer::Param { + Flags: 0, + Sequence: (sequence + 1) as _, + Name: writer.strings.insert(¶m.name), + }); + } + } } // TODO: In theory, `config` could instruct this function to balance the types across a number of winmd files @@ -41,7 +76,26 @@ pub fn from_reader( crate::write_to_file(output, writer.into_stream()).map_err(|err| err.with_path(output)) } -fn writer_type(reader: &metadata::Reader, ty: &metadata::Type) -> winmd::Type { +fn winmd_signature(reader: &metadata::Reader, sig: &metadata::Signature) -> winmd::Signature { + let params = sig + .params + .iter() + .map(|param| { + let name = reader.param_name(param.def).to_string(); + let ty = winmd_type(reader, ¶m.ty); + winmd::SignatureParam { name, ty } + }) + .collect(); + + let return_type = winmd_type(reader, &sig.return_type); + winmd::Signature { + params, + return_type, + call_flags: 0, + } +} + +fn winmd_type(reader: &metadata::Reader, ty: &metadata::Type) -> winmd::Type { match ty { metadata::Type::Void => winmd::Type::Void, metadata::Type::Bool => winmd::Type::Bool, @@ -72,7 +126,7 @@ fn writer_type(reader: &metadata::Reader, ty: &metadata::Type) -> winmd::Type { metadata::Type::TypeDef(def, generics) => winmd::Type::TypeRef(winmd::TypeName { namespace: reader.type_def_namespace(*def).to_string(), name: reader.type_def_name(*def).to_string(), - generics: generics.iter().map(|ty| writer_type(reader, ty)).collect(), + generics: generics.iter().map(|ty| winmd_type(reader, ty)).collect(), }), rest => unimplemented!("{rest:?}"), } diff --git a/crates/tools/riddle/src/winmd/verify.rs b/crates/tools/riddle/src/winmd/verify.rs new file mode 100644 index 0000000000..26d4dff784 --- /dev/null +++ b/crates/tools/riddle/src/winmd/verify.rs @@ -0,0 +1,30 @@ +pub fn verify(reader: &metadata::Reader, filter: &metadata::Filter) -> crate::Result<()> { + for def in reader.types(filter) { + let generics = &reader.type_def_generics(def); + + reader + .type_def_fields(def) + .try_for_each(|field| not_type_ref(reader, &reader.field_type(field, Some(def))))?; + + reader.type_def_methods(def).try_for_each(|method| { + let sig = reader.method_def_signature(method, generics); + not_type_ref(reader, &sig.return_type)?; + + sig.params + .iter() + .try_for_each(|param| not_type_ref(reader, ¶m.ty)) + })?; + } + + Ok(()) +} + +fn not_type_ref(reader: &metadata::Reader, ty: &metadata::Type) -> crate::Result<()> { + if let metadata::Type::TypeRef(ty) = ty { + return Err(crate::Error::new(&format!( + "missing type definition `{}`", + reader.type_def_or_ref(*ty) + ))); + } + Ok(()) +} diff --git a/crates/tools/riddle/src/winmd/writer/mod.rs b/crates/tools/riddle/src/winmd/writer/mod.rs index 319249811b..0c32c68d89 100644 --- a/crates/tools/riddle/src/winmd/writer/mod.rs +++ b/crates/tools/riddle/src/winmd/writer/mod.rs @@ -153,6 +153,18 @@ impl Writer { // self.blobs.insert(&blob) // } + pub fn insert_method_sig(&mut self, sig: &Signature) -> u32 { + let mut blob = vec![sig.call_flags]; + usize_blob(sig.params.len(), &mut blob); + self.type_blob(&sig.return_type, &mut blob); + + for param in &sig.params { + self.type_blob(¶m.ty, &mut blob); + } + + self.blobs.insert(&blob) + } + pub fn insert_field_sig(&mut self, ty: &Type) -> u32 { // TODO: can either cache in Writer, like we do for scopes and references, or regenerate each time. // Profile once we can stress test this with field/method signatures. diff --git a/crates/tools/riddle/src/winmd/writer/type.rs b/crates/tools/riddle/src/winmd/writer/type.rs index 73f888a5df..03a085c030 100644 --- a/crates/tools/riddle/src/winmd/writer/type.rs +++ b/crates/tools/riddle/src/winmd/writer/type.rs @@ -66,3 +66,15 @@ impl Type { Self::Win32Array(Box::new(self), len) } } + +pub struct Signature { + pub params: Vec, + pub return_type: Type, + pub call_flags: u8, +} + +// TODO: just Param? +pub struct SignatureParam { + pub name: String, + pub ty: Type, +}