diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 651cf84e16..ee292c0137 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -33,8 +33,6 @@ jobs: run: cargo clippy -p cppwinrt - name: Clippy helpers run: cargo clippy -p helpers - - name: Clippy riddle - run: cargo clippy -p riddle - name: Clippy sample_bits run: cargo clippy -p sample_bits - name: Clippy sample_com_uri @@ -239,8 +237,6 @@ jobs: run: cargo clippy -p test_return_handle - name: Clippy test_return_struct run: cargo clippy -p test_return_struct - - name: Clippy test_riddle - run: cargo clippy -p test_riddle - name: Clippy test_standalone run: cargo clippy -p test_standalone - name: Clippy test_string_param diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6295cd9456..93cb7fd187 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -57,8 +57,6 @@ jobs: run: cargo test -p cppwinrt --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test helpers run: cargo test -p helpers --target ${{ matrix.target }} ${{ matrix.etc }} - - name: Test riddle - run: cargo test -p riddle --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test sample_bits run: cargo test -p sample_bits --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test sample_com_uri @@ -153,10 +151,10 @@ jobs: run: cargo test -p test_agile_reference --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_alternate_success_code run: cargo test -p test_alternate_success_code --target ${{ matrix.target }} ${{ matrix.etc }} - - name: Clean - run: cargo clean - name: Test test_arch run: cargo test -p test_arch --target ${{ matrix.target }} ${{ matrix.etc }} + - name: Clean + run: cargo clean - name: Test test_arch_feature run: cargo test -p test_arch_feature --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_array @@ -255,10 +253,10 @@ jobs: run: cargo test -p test_registry --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_registry_default run: cargo test -p test_registry_default --target ${{ matrix.target }} ${{ matrix.etc }} - - name: Clean - run: cargo clean - name: Test test_reserved run: cargo test -p test_reserved --target ${{ matrix.target }} ${{ matrix.etc }} + - name: Clean + run: cargo clean - name: Test test_resources run: cargo test -p test_resources --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_result @@ -267,8 +265,6 @@ jobs: run: cargo test -p test_return_handle --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_return_struct run: cargo test -p test_return_struct --target ${{ matrix.target }} ${{ matrix.etc }} - - name: Test test_riddle - run: cargo test -p test_riddle --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_standalone run: cargo test -p test_standalone --target ${{ matrix.target }} ${{ matrix.etc }} - name: Test test_string_param diff --git a/crates/libs/bindgen/src/lib.rs b/crates/libs/bindgen/src/lib.rs index 4ecdc572d9..e697199b40 100644 --- a/crates/libs/bindgen/src/lib.rs +++ b/crates/libs/bindgen/src/lib.rs @@ -3,11 +3,9 @@ mod args; mod error; mod metadata; -mod rdl; mod rust; mod tokens; mod tree; -mod winmd; pub use error::{Error, Result}; use tree::Tree; @@ -35,7 +33,6 @@ where let mut include = Vec::<&str>::new(); let mut exclude = Vec::<&str>::new(); let mut config = std::collections::BTreeMap::<&str, &str>::new(); - let mut format = false; for arg in &args { if arg.starts_with('-') { @@ -48,7 +45,6 @@ where "-o" | "--out" => kind = ArgKind::Output, "-f" | "--filter" => kind = ArgKind::Filter, "--config" => kind = ArgKind::Config, - "--format" => format = true, _ => return Err(Error::new(&format!("invalid option `{arg}`"))), }, ArgKind::Output => { @@ -76,29 +72,6 @@ where } } - if format { - if output.is_some() || !include.is_empty() || !exclude.is_empty() { - return Err(Error::new( - "`--format` cannot be combined with `--out` or `--filter`", - )); - } - - let input = filter_input(&input, &["rdl"])?; - - if input.is_empty() { - return Err(Error::new("no .rdl inputs")); - } - - for path in &input { - read_file_text(path) - .and_then(|source| rdl::File::parse_str(&source)) - .and_then(|file| write_to_file(path, file.fmt())) - .map_err(|err| err.with_path(path))?; - } - - return Ok(String::new()); - } - let Some(output) = output else { return Err(Error::new("no output")); }; @@ -115,10 +88,8 @@ where let reader = metadata::Reader::filter(input, &include, &exclude, &config); match extension(&output) { - "rdl" => rdl::from_reader(reader, config, &output)?, - "winmd" => winmd::from_reader(reader, config, &output)?, "rs" => rust::from_reader(reader, config, &output)?, - _ => return Err(Error::new("output extension must be one of winmd/rdl/rs")), + _ => return Err(Error::new("output extension must be one of `rs`")), } let elapsed = time.elapsed().as_secs_f32(); @@ -195,22 +166,12 @@ fn read_input(input: &[&str]) -> Result> { } for input in &input { - let file = if extension(input) == "winmd" { - read_winmd_file(input)? - } else { - read_rdl_file(input)? - }; - - results.push(file); + results.push(read_winmd_file(input)?); } Ok(results) } -fn read_file_text(path: &str) -> Result { - std::fs::read_to_string(path).map_err(|_| Error::new("failed to read text file")) -} - fn read_file_bytes(path: &str) -> Result> { std::fs::read(path).map_err(|_| Error::new("failed to read binary file")) } @@ -228,20 +189,6 @@ fn read_file_lines(path: &str) -> Result> { Ok(lines) } -fn read_rdl_file(path: &str) -> Result { - read_file_text(path) - .and_then(|source| rdl::File::parse_str(&source)) - .and_then(|file| file.into_winmd()) - .map(|bytes| { - // TODO: Write bytes to file if you need to debug the intermediate .winmd file like so: - _ = write_to_file("temp.winmd", &bytes); - - // Unwrapping here is fine since `rdl_to_winmd` should have produced a valid winmd - metadata::File::new(bytes).unwrap() - }) - .map_err(|err| err.with_path(path)) -} - fn read_winmd_file(path: &str) -> Result { read_file_bytes(path).and_then(|bytes| { metadata::File::new(bytes) diff --git a/crates/libs/bindgen/src/rdl/fmt.rs b/crates/libs/bindgen/src/rdl/fmt.rs deleted file mode 100644 index c0fe8bdcb7..0000000000 --- a/crates/libs/bindgen/src/rdl/fmt.rs +++ /dev/null @@ -1,454 +0,0 @@ -use super::*; - -// TODO: should we use rustfmt in the short term (with pre/post) - -#[derive(Default)] -pub struct Writer { - out: String, - indent: usize, - newline: bool, -} - -impl Writer { - pub fn new(file: &File) -> Self { - let mut writer = Self::default(); - writer.rdl_file(file); - writer - } - - pub fn into_string(mut self) -> String { - self.out.push('\n'); - self.out - } - - fn word(&mut self, value: &str) { - if self.newline { - self.newline = false; - self.out.push('\n'); - for _ in 0..self.indent { - self.out.push_str(" "); - } - } - - self.out.push_str(value); - } - - fn newline(&mut self) { - self.newline = true; - } - - fn rdl_file(&mut self, file: &File) { - if file.winrt { - self.word("#![winrt]\n"); - } else { - self.word("#![win32]\n"); - } - - self.newline(); - - for reference in &file.references { - self.item_use(reference); - } - - for module in &file.modules { - self.rdl_module(module); - } - } - - fn rdl_module(&mut self, module: &Module) { - self.word("mod "); - self.word(module.name()); - self.word(" {"); - self.newline(); - self.indent += 1; - - for member in &module.members { - self.rdl_module_member(member); - self.newline(); - } - - self.indent -= 1; - self.newline(); - self.word("}"); - self.newline(); - } - - fn rdl_module_member(&mut self, member: &ModuleMember) { - match member { - ModuleMember::Module(member) => self.rdl_module(member), - ModuleMember::Interface(member) => self.rdl_interface(member), - ModuleMember::Struct(member) => self.rdl_struct(member), - ModuleMember::Enum(member) => self.rdl_enum(member), - ModuleMember::Class(member) => self.rdl_class(member), - ModuleMember::Constant(member) => self.rdl_constant(member), - ModuleMember::Function(member) => self.rdl_function(member), - } - } - - fn rdl_class(&mut self, member: &Class) { - self.attrs(&member.attributes); - self.word("class "); - self.word(&member.name); - - if !member.extends.is_empty() || member.base.is_some() { - self.word(" : "); - - if let Some(path) = &member.base { - self.word("class "); - self.type_path(path); - - if !member.extends.is_empty() { - self.word(", "); - } - } - - let mut first = true; - for path in &member.extends { - if first { - first = false; - } else { - self.word(", "); - } - self.type_path(path); - } - } - - self.word(";"); - self.newline(); - } - - fn rdl_interface(&mut self, member: &Interface) { - self.attrs(&member.attributes); - self.word("interface "); - self.word(&member.name); - - if !member.generics.is_empty() { - self.word("<"); - - let mut first = true; - for generic in &member.generics { - if first { - first = false; - } else { - self.word(", "); - } - self.word(generic); - } - - self.word(">"); - } - - if !member.extends.is_empty() { - self.word(" : "); - - let mut first = true; - for path in &member.extends { - if first { - first = false; - } else { - self.word(", "); - } - self.type_path(path); - } - } - - self.word(" {"); - self.newline(); - self.indent += 1; - - for method in &member.methods { - self.trait_item_fn(method); - self.word(";"); - self.newline(); - } - - self.indent -= 1; - self.newline(); - self.word("}"); - } - - fn rdl_constant(&mut self, member: &Constant) { - self.item_const(&member.item); - } - - fn rdl_function(&mut self, member: &Function) { - self.trait_item_fn(&member.item); - self.word(";"); - self.newline(); - } - - fn item_const(&mut self, item: &syn::ItemConst) { - self.word("const "); - self.ident(&item.ident); - self.word(": "); - self.ty(&item.ty); - self.word(" = "); - self.expr(&item.expr); - self.word(";"); - self.newline(); - } - - fn attrs(&mut self, attrs: &[syn::Attribute]) { - for attr in attrs { - self.attr(attr); - } - } - - fn attr(&mut self, attr: &syn::Attribute) { - self.word("#["); - self.meta(&attr.meta); - self.word("]"); - self.newline(); - } - - fn meta(&mut self, meta: &syn::Meta) { - match meta { - syn::Meta::Path(path) => self.path(path), - syn::Meta::List(list) => self.meta_list(list), - syn::Meta::NameValue(meta) => self.meta_name_value(meta), - } - } - - fn meta_list(&mut self, meta_list: &syn::MetaList) { - self.path(&meta_list.path); - self.word("("); - self.word(&meta_list.tokens.to_string()); - self.word(")"); - } - - fn meta_name_value(&mut self, meta: &syn::MetaNameValue) { - self.path(&meta.path); - self.word(" = "); - self.expr(&meta.value); - } - - fn rdl_struct(&mut self, member: &Struct) { - self.attrs(&member.attributes); - - self.word("struct "); - self.word(&member.name); - self.word(" {"); - self.newline(); - self.indent += 1; - - for field in &member.fields { - self.word(&field.name); - self.word(": "); - self.ty(&field.ty); - self.word(","); - self.newline(); - } - - self.indent -= 1; - self.newline(); - self.word("}"); - } - - fn rdl_enum(&mut self, member: &Enum) { - self.attrs(&member.item.attrs); - - self.word("enum "); - self.ident(&member.item.ident); - self.word(" {"); - self.newline(); - self.indent += 1; - - for variant in &member.item.variants { - self.ident(&variant.ident); - if let Some((_, expr)) = &variant.discriminant { - self.word(" = "); - self.expr(expr); - } - self.word(","); - self.newline(); - } - - self.indent -= 1; - self.newline(); - self.word("}"); - } - - fn trait_item_fn(&mut self, method: &syn::TraitItemFn) { - self.attrs(&method.attrs); - self.signature(&method.sig); - } - - fn signature(&mut self, signature: &syn::Signature) { - self.word("fn "); - self.ident(&signature.ident); - self.word("("); - - let mut first = true; - for input in &signature.inputs { - if first { - first = false; - } else { - self.word(", "); - } - self.fn_arg(input); - } - - self.word(")"); - - if let syn::ReturnType::Type(_, ty) = &signature.output { - self.word(" -> "); - self.ty(ty); - } - } - - fn fn_arg(&mut self, fn_arg: &syn::FnArg) { - if let syn::FnArg::Typed(pat_type) = fn_arg { - self.pat_type(pat_type); - } - } - - fn pat_type(&mut self, pat_type: &syn::PatType) { - self.pat(&pat_type.pat); - self.word(": "); - self.ty(&pat_type.ty); - } - - fn pat(&mut self, pat: &syn::Pat) { - match pat { - syn::Pat::Ident(pat_ident) => self.pat_ident(pat_ident), - rest => unimplemented!("{rest:?}"), - } - } - - fn pat_ident(&mut self, pat_ident: &syn::PatIdent) { - self.ident(&pat_ident.ident); - } - - fn ty(&mut self, ty: &syn::Type) { - match ty { - syn::Type::Path(ty) => self.type_path(ty), - syn::Type::Ptr(ptr) => self.type_ptr(ptr), - syn::Type::Array(array) => self.type_array(array), - rest => unimplemented!("{rest:?}"), - } - } - - fn type_array(&mut self, array: &syn::TypeArray) { - self.word("["); - self.ty(&array.elem); - self.word("; "); - self.expr(&array.len); - self.word("]"); - } - - fn expr(&mut self, expr: &syn::Expr) { - match expr { - syn::Expr::Lit(lit) => self.expr_lit(lit), - syn::Expr::Unary(unary) => self.expr_unary(unary), - rest => unimplemented!("{rest:?}"), - } - } - - fn expr_unary(&mut self, unary: &syn::ExprUnary) { - self.word("-"); - self.expr(&unary.expr); - } - - fn expr_lit(&mut self, expr: &syn::ExprLit) { - self.lit(&expr.lit); - } - - fn lit(&mut self, lit: &syn::Lit) { - match lit { - syn::Lit::Int(lit) => self.lit_int(lit), - syn::Lit::Str(lit) => self.lit_str(lit), - _ => _ = dbg!(lit), - } - } - - fn lit_str(&mut self, lit: &syn::LitStr) { - self.word("\""); - self.word(&lit.value()); - self.word("\""); - } - - fn lit_int(&mut self, lit: &syn::LitInt) { - self.word(&lit.token().to_string()); - } - - fn type_ptr(&mut self, ptr: &syn::TypePtr) { - if ptr.mutability.is_some() { - self.word("*mut "); - } else { - self.word("*const "); - } - self.ty(&ptr.elem); - } - - fn type_path(&mut self, ty: &syn::TypePath) { - self.path(&ty.path); - } - - fn path(&mut self, path: &syn::Path) { - let mut first = true; - for segment in &path.segments { - if first { - first = false; - } else { - self.word("::"); - } - self.path_segment(segment); - } - } - - pub fn path_segment(&mut self, segment: &syn::PathSegment) { - self.ident(&segment.ident); - - if let syn::PathArguments::AngleBracketed(args) = &segment.arguments { - self.word("<"); - - let mut first = true; - for arg in &args.args { - if first { - first = false; - } else { - self.word(", "); - } - self.generic_argument(arg); - } - - self.word(">"); - } - } - - fn generic_argument(&mut self, arg: &syn::GenericArgument) { - match arg { - syn::GenericArgument::Type(ty) => self.ty(ty), - rest => unimplemented!("{rest:?}"), - } - } - - fn item_use(&mut self, item: &syn::ItemUse) { - self.word("use "); - self.use_tree(&item.tree); - self.word(";"); - self.newline(); - } - - fn use_tree(&mut self, use_tree: &syn::UseTree) { - match use_tree { - syn::UseTree::Path(use_path) => self.use_path(use_path), - syn::UseTree::Name(use_name) => self.use_name(use_name), - _ => {} - } - } - - fn use_path(&mut self, use_path: &syn::UsePath) { - self.ident(&use_path.ident); - self.word("::"); - self.use_tree(&use_path.tree); - } - - fn use_name(&mut self, use_name: &syn::UseName) { - self.ident(&use_name.ident); - } - - pub fn ident(&mut self, ident: &syn::Ident) { - self.word(&ident.to_string()); - } -} diff --git a/crates/libs/bindgen/src/rdl/from_reader.rs b/crates/libs/bindgen/src/rdl/from_reader.rs deleted file mode 100644 index b1fb2d2239..0000000000 --- a/crates/libs/bindgen/src/rdl/from_reader.rs +++ /dev/null @@ -1,465 +0,0 @@ -use super::*; -use tokens::{quote, to_ident, TokenStream}; - -pub fn from_reader( - reader: &'static metadata::Reader, - mut config: std::collections::BTreeMap<&str, &str>, - output: &str, -) -> Result<()> { - let dialect = match config.remove("type") { - Some("winrt") => Dialect::WinRT, - Some("win32") => Dialect::Win32, - _ => { - return Err(Error::new( - "configuration value `type` must be `win32` or `winrt`", - )) - } - }; - - let mut writer = Writer::new(reader, output, dialect); - - // TODO: be sure to use the same "split" key for winmd splitting. - // May also want to support split=N similar to the way MIDLRT supports winmd splitting - // at different nesting levels. - writer.split = config.remove("split").is_some(); - - if let Some((key, _)) = config.first_key_value() { - return Err(Error::new(&format!("invalid configuration value `{key}`"))); - } - - if writer.split { - gen_split(&writer) - } else { - gen_file(&writer) - } -} - -fn gen_split(writer: &Writer) -> Result<()> { - let tree = Tree::new(writer.reader); - let directory = directory(&writer.output); - - // TODO: parallelize - for tree in tree.flatten() { - let tokens = writer.tree(tree); - - if !tokens.is_empty() { - let output = format!("{directory}/{}.rdl", tree.namespace); - writer.write_to_file(&output, tokens)?; - } - } - - Ok(()) -} - -fn gen_file(writer: &Writer) -> Result<()> { - let tree = Tree::new(writer.reader); - let tokens = writer.tree(&tree); - writer.write_to_file(&writer.output, tokens) -} - -#[derive(Debug, Copy, Clone, PartialEq)] -enum Dialect { - Win32, - WinRT, -} - -struct Writer { - reader: &'static metadata::Reader, - namespace: &'static str, - dialect: Dialect, - split: bool, - output: String, -} - -impl Writer { - fn new(reader: &'static metadata::Reader, output: &str, dialect: Dialect) -> Self { - Self { - reader, - namespace: "", - output: output.to_string(), - dialect, - split: false, - } - } - - fn with_namespace(&self, namespace: &'static str) -> Self { - Self { - reader: self.reader, - namespace, - dialect: self.dialect, - output: self.output.clone(), - split: self.split, - } - } - - fn write_to_file(&self, output: &str, tokens: TokenStream) -> Result<()> { - let dialect = match self.dialect { - Dialect::Win32 => quote! { #![win32] }, - Dialect::WinRT => quote! { #![winrt] }, - }; - - let tokens = quote! { - #dialect - #tokens - }; - - let file = File::parse_str(&tokens.into_string())?; - write_to_file(output, file.fmt()) - //write_to_file(output, tokens.into_string()) - } - - fn tree(&self, tree: &Tree) -> TokenStream { - let items = self.items(tree); - - if self.split { - let mut tokens = items; - - if !tokens.is_empty() { - for name in tree.namespace.rsplit('.').map(to_ident) { - tokens = quote! { - mod #name { - #tokens - } - }; - } - } - - tokens - } else { - let name = to_ident( - tree.namespace - .rsplit_once('.') - .map_or(tree.namespace, |(_, name)| name), - ); - - let modules = tree - .nested - .values() - .map(|tree| self.with_namespace(tree.namespace).tree(tree)); - - if tree.namespace.is_empty() { - quote! { - #(#modules)* - #items - } - } else { - quote! { - mod #name { - #(#modules)* - #items - } - } - } - } - } - - fn items(&self, tree: &Tree) -> TokenStream { - let mut functions = vec![]; - let mut constants = vec![]; - let mut types = vec![]; - - if !tree.namespace.is_empty() { - for item in self - .reader - .namespace_items(tree.namespace) - .filter(|item| match item { - metadata::Item::Type(def) => { - let winrt = def - .flags() - .contains(metadata::TypeAttributes::WindowsRuntime); - match self.dialect { - Dialect::Win32 => !winrt, - Dialect::WinRT => winrt, - } - } - metadata::Item::Fn(_, _) | metadata::Item::Const(_) => { - self.dialect == Dialect::Win32 - } - }) - { - match item { - metadata::Item::Type(def) => types.push(self.type_def(def)), - metadata::Item::Const(field) => constants.push(self.constant(field)), - metadata::Item::Fn(method, namespace) => { - functions.push(self.function(method, namespace)) - } - } - } - } - - quote! { - #(#functions)* - #(#constants)* - #(#types)* - } - } - - fn function(&self, def: metadata::MethodDef, _namespace: &str) -> TokenStream { - let name = to_ident(def.name()); - quote! { fn #name(); } - } - - fn constant(&self, def: metadata::Field) -> TokenStream { - let name = to_ident(def.name()); - quote! { const #name: i32 = 0; } - } - - fn type_def(&self, def: metadata::TypeDef) -> TokenStream { - if let Some(extends) = def.extends() { - if extends.namespace() == "System" { - if extends.name() == "Enum" { - self.enum_def(def) - } else if extends.name() == "ValueType" { - self.struct_def(def) - } else if extends.name() == "MulticastDelegate" { - self.delegate_def(def) - } else { - self.class_def(def) - } - } else { - self.class_def(def) - } - } else { - self.interface_def(def) - } - } - - fn enum_def(&self, def: metadata::TypeDef) -> TokenStream { - let name = to_ident(def.name()); - - quote! { - struct #name { - - } - } - } - - fn struct_def(&self, def: metadata::TypeDef) -> TokenStream { - let name = to_ident(def.name()); - - let fields = def.fields().map(|field| { - let name = to_ident(field.name()); - let ty = self.ty(&field.ty(Some(def))); - quote! { - #name: #ty - } - }); - - quote! { - struct #name { - #(#fields),* - } - } - } - - fn delegate_def(&self, def: metadata::TypeDef) -> TokenStream { - let name = to_ident(def.name()); - - quote! { - struct #name { - - } - } - } - - fn class_def(&self, def: metadata::TypeDef) -> TokenStream { - let name = to_ident(def.name()); - let implements = self.implements(def, &[]); - - quote! { - class #name #implements; - } - } - - fn interface_def(&self, def: metadata::TypeDef) -> TokenStream { - let name = to_ident(def.name()); - let generics = &metadata::type_def_generics(def); - let implements = self.implements(def, generics); - - let methods = def.methods().map(|method| { - let name = to_ident(method.name()); - - // TODO: use reader.method_def_signature instead - let signature = metadata::method_def_signature(def.namespace(), method, generics); - - let return_type = self.return_type(&signature.return_type); - - let params = signature.params.iter().map(|param| { - let name = to_ident(param.def.name()); - let ty = self.ty(¶m.ty); - quote! { #name: #ty } - }); - - quote! { - fn #name(#(#params),*) #return_type; - } - }); - - let generics = self.generics(generics); - - quote! { - interface #name #generics #implements { - #(#methods)* - } - } - } - - fn generics(&self, generics: &[metadata::Type]) -> TokenStream { - if generics.is_empty() { - quote! {} - } else { - let generics = generics.iter().map(|generic| self.ty(generic)); - - quote! { <#(#generics),*>} - } - } - - fn implements(&self, def: metadata::TypeDef, generics: &[metadata::Type]) -> TokenStream { - let mut types = Vec::::new(); - - // TODO: if a winrt composable class then start with base - // TODO: then list default interface first - // Then everything else - - for interface in metadata::type_def_interfaces(def, generics) { - if interface.kind == metadata::InterfaceKind::Default { - types.insert(0, self.ty(&interface.ty)); - } else { - types.push(self.ty(&interface.ty)); - } - } - - if let Some(type_name) = def.extends() { - if type_name != metadata::TypeName::Object { - let namespace = self.namespace(type_name.namespace()); - let name = to_ident(type_name.name()); - // TODO: ideally the "class" contextual keyword wouldn't be needed here - // but currently there's no way to tell the base class apart from a required interface. - types.insert(0, quote! { class #namespace #name }); - } - } - - if types.is_empty() { - quote! {} - } else { - quote! { : #(#types),* } - } - } - - fn return_type(&self, ty: &metadata::Type) -> TokenStream { - match ty { - metadata::Type::Void => quote! {}, - _ => { - let ty = self.ty(ty); - quote! { -> #ty } - } - } - } - - fn ty(&self, ty: &metadata::Type) -> TokenStream { - match ty { - metadata::Type::Void => quote! { core::ffi::c_void }, - metadata::Type::Bool => quote! { bool }, - metadata::Type::Char => quote! { u16 }, - metadata::Type::I8 => quote! { i8 }, - metadata::Type::U8 => quote! { u8 }, - metadata::Type::I16 => quote! { i16 }, - metadata::Type::U16 => quote! { u16 }, - metadata::Type::I32 => quote! { i32 }, - metadata::Type::U32 => quote! { u32 }, - metadata::Type::I64 => quote! { i64 }, - metadata::Type::U64 => quote! { u64 }, - metadata::Type::F32 => quote! { f32 }, - metadata::Type::F64 => quote! { f64 }, - metadata::Type::ISize => quote! { isize }, - metadata::Type::USize => quote! { usize }, - - // TODO: dialect-specific keywords for "well-known types" that don't map to metadata in all cases. - metadata::Type::String => quote! { HSTRING }, - metadata::Type::Name(metadata::TypeName::HResult) => quote! { HRESULT }, - metadata::Type::Name(metadata::TypeName::GUID) => quote! { GUID }, - metadata::Type::Object => quote! { IInspectable }, - metadata::Type::Name(metadata::TypeName::IUnknown) => quote! { IUnknown }, - metadata::Type::Name(metadata::TypeName::BSTR) => quote! { BSTR }, - metadata::Type::Name(metadata::TypeName::PSTR) => quote! { PSTR }, - metadata::Type::Name(metadata::TypeName::PWSTR) => quote! { PWSTR }, - metadata::Type::Const(metadata::TypeName::PSTR) => quote! { PCSTR }, - metadata::Type::Const(metadata::TypeName::PWSTR) => quote! { PCWSTR }, - metadata::Type::TypeDef(def, generics) => { - let namespace = self.namespace(def.namespace()); - let name = to_ident(def.name()); - if generics.is_empty() { - quote! { #namespace #name } - } else { - let generics = generics.iter().map(|ty| self.ty(ty)); - quote! { #namespace #name<#(#generics,)*> } - } - } - - metadata::Type::Name(type_name) => { - let namespace = self.namespace(type_name.namespace()); - let name = to_ident(type_name.name()); - quote! { #namespace #name } - } - - metadata::Type::GenericParam(generic) => generic.name().into(), - metadata::Type::WinrtArray(ty) => self.ty(ty), - metadata::Type::WinrtArrayRef(ty) => self.ty(ty), - metadata::Type::ConstRef(ty) => self.ty(ty), - metadata::Type::MutPtr(ty, _pointers) => self.ty(ty), - metadata::Type::ConstPtr(ty, _pointers) => self.ty(ty), - metadata::Type::Win32Array(ty, _len) => self.ty(ty), - metadata::Type::PrimitiveOrEnum(_, ty) => self.ty(ty), - rest => unimplemented!("{rest:?}"), - } - } - - fn namespace(&self, namespace: &str) -> TokenStream { - // TODO: handle nested structs? - if namespace.is_empty() || self.namespace == namespace { - quote! {} - } else { - // TODO: problem with making relative paths here is that we don't have the context to disambiguate - - // let mut relative = self.namespace.split('.').peekable(); - // let mut namespace = namespace.split('.').peekable(); - // let mut related = false; - - // while relative.peek() == namespace.peek() { - // related = true; - - // if relative.next().is_none() { - // break; - // } - - // namespace.next(); - // } - - // let mut tokens = TokenStream::new(); - - // if related { - // for _ in 0..relative.count() { - // tokens.push_str("super::"); - // } - // } - - // for namespace in namespace { - // tokens.push_str(namespace); - // tokens.push_str("::"); - // } - - // tokens - - // TODO: so instead we just gen it out in full - - let mut tokens = TokenStream::new(); - - for namespace in namespace.split('.') { - tokens.push_str(namespace); - tokens.push_str("::"); - } - - tokens - } - } -} diff --git a/crates/libs/bindgen/src/rdl/mod.rs b/crates/libs/bindgen/src/rdl/mod.rs deleted file mode 100644 index d3f76d8660..0000000000 --- a/crates/libs/bindgen/src/rdl/mod.rs +++ /dev/null @@ -1,420 +0,0 @@ -#![allow(dead_code)] - -use super::*; -mod fmt; -mod from_reader; -mod to_winmd; -use crate::Result; -pub use from_reader::from_reader; -use syn::spanned::Spanned; - -// TODO: may want to finally get rid of `syn` as it also doesn't support preserving code comments - -impl File { - pub fn parse_str(input: &str) -> Result { - Ok(syn::parse_str::(input)?) - } - - // Note: this isn't called automatically by `parse_str` to avoid canonicalizing when we're merely formatting IDL. - pub fn canonicalize(&mut self) -> Result<()> { - // TODO maybe we rewrite the `File` here to resolve any `super` references and use declarations so that - // subsequently the rdl-to-winmd conversion can just assume everything's fully qualified? - // * super can't refer to something outside of the IDL file - // * use declarations are only used for unqualified names that aren't defined in the IDL file - // * use declarations don't support globs and must name all externally defined types - // This way we can quickly kick out common invalid IDL files before we lost file/span context info - - Ok(()) - } - - pub fn fmt(&self) -> String { - fmt::Writer::new(self).into_string() - } - - pub fn into_winmd(mut self) -> Result> { - self.canonicalize()?; - to_winmd::rdl_to_winmd(&self) - } -} - -// The value of the IDL-specific memory representation is that it allows for constructs that are not modeled in the abstract Module -// tree such as the use declarations and if we get rid of it we'd always "format" IDL by stripping out any of that into a single -// canonical form which would not be very friendly to developers. -#[derive(Debug)] -pub struct File { - pub winrt: bool, - pub references: Vec, - pub modules: Vec, -} - -// TODO: need to change these to unpack the syn types and store strings we can reference for efficiency along with spans since the syn -// is made for value semantics. - -#[derive(Clone, Debug)] -pub struct Module { - pub namespace: String, - pub members: Vec, -} - -#[derive(Clone, Debug)] -pub enum ModuleMember { - Module(Module), - Interface(Interface), - Struct(Struct), - Enum(Enum), - Class(Class), - Function(Function), - Constant(Constant), -} - -impl ModuleMember { - pub fn name(&self) -> &str { - match self { - Self::Module(module) => extension(&module.namespace), - Self::Interface(member) => &member.name, - Self::Struct(member) => &member.name, - Self::Enum(member) => &member.name, - Self::Class(member) => &member.name, - Self::Function(member) => &member.name, - Self::Constant(member) => &member.name, - } - } -} - -#[derive(Clone, Debug)] -pub struct Enum { - pub winrt: bool, - pub name: String, - pub item: syn::ItemEnum, -} - -#[derive(Clone, Debug)] -pub struct Constant { - pub name: String, - pub item: syn::ItemConst, -} - -#[derive(Clone, Debug)] -pub struct Struct { - pub winrt: bool, - pub name: String, - pub attributes: Vec, - pub span: proc_macro2::Span, - pub fields: Vec, -} - -#[derive(Clone, Debug)] -pub struct Field { - pub name: String, - pub attributes: Vec, - pub span: proc_macro2::Span, - pub ty: syn::Type, -} - -#[derive(Clone, Debug)] -pub struct Class { - pub name: String, - pub attributes: Vec, - pub base: Option, - pub extends: Vec, -} - -#[derive(Clone, Debug)] -pub struct Function { - pub name: String, - pub item: syn::TraitItemFn, -} - -#[derive(Clone, Debug)] -pub struct Interface { - pub winrt: bool, - pub name: String, - pub generics: Vec, - pub attributes: Vec, - pub extends: Vec, - pub methods: Vec, -} - -syn::custom_keyword!(interface); -syn::custom_keyword!(class); - -fn winrt(input: syn::parse::ParseStream<'_>) -> syn::Result { - let attributes = input.call(syn::Attribute::parse_inner)?; - if attributes.len() == 1 { - if let syn::Meta::Path(path) = &attributes[0].meta { - if path.is_ident("winrt") { - return Ok(true); - } - - if path.is_ident("win32") { - return Ok(false); - } - } - } - - Err(syn::Error::new( - input.span(), - "A single `#![win32]` or `#![winrt]` attribute required", - )) -} - -impl syn::parse::Parse for File { - fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { - let mut references = vec![]; - let mut modules = vec![]; - let winrt = winrt(input)?; - - while !input.is_empty() { - let lookahead = input.lookahead1(); - if lookahead.peek(syn::Token![mod]) { - modules.push(Module::parse("", winrt, input)?); - } else if lookahead.peek(syn::Token![use]) { - references.push(input.parse()?); - } else { - return Err(lookahead.error()); - } - } - Ok(Self { - winrt, - references, - modules, - }) - } -} - -impl Module { - fn name(&self) -> &str { - self.namespace - .rsplit_once('.') - .map_or(&self.namespace, |(_, name)| name) - } - - fn parse( - namespace: &str, - winrt: bool, - input: syn::parse::ParseStream<'_>, - ) -> syn::Result { - input.parse::()?; - let name = input.parse::()?.to_string(); - - let namespace = if namespace.is_empty() { - name.to_string() - } else { - format!("{namespace}.{name}") - }; - - let content; - syn::braced!(content in input); - let mut members = vec![]; - while !content.is_empty() { - members.push(ModuleMember::parse(&namespace, winrt, &content)?); - } - Ok(Self { namespace, members }) - } -} - -impl ModuleMember { - fn parse( - namespace: &str, - winrt: bool, - input: syn::parse::ParseStream<'_>, - ) -> syn::Result { - let attributes: Vec = input.call(syn::Attribute::parse_outer)?; - let lookahead = input.lookahead1(); - if lookahead.peek(syn::Token![mod]) { - if let Some(attribute) = attributes.first() { - return Err(syn::Error::new( - attribute.span(), - "`use` attributes not supported", - )); - } - Ok(ModuleMember::Module(Module::parse( - namespace, winrt, input, - )?)) - } else if lookahead.peek(interface) { - Ok(ModuleMember::Interface(Interface::parse( - namespace, winrt, attributes, input, - )?)) - } else if lookahead.peek(syn::Token![struct]) { - Ok(ModuleMember::Struct(Struct::parse( - namespace, winrt, attributes, input, - )?)) - } else if lookahead.peek(syn::Token![enum]) { - Ok(ModuleMember::Enum(Enum::parse( - namespace, winrt, attributes, input, - )?)) - } else if lookahead.peek(class) { - Ok(ModuleMember::Class(Class::parse(attributes, input)?)) - } else if lookahead.peek(syn::Token![fn]) { - Ok(ModuleMember::Function(Function::parse( - namespace, attributes, input, - )?)) - } else if lookahead.peek(syn::Token![const]) { - Ok(ModuleMember::Constant(Constant::parse( - namespace, attributes, input, - )?)) - } else { - Err(lookahead.error()) - } - } -} - -impl Class { - fn parse( - attributes: Vec, - input: syn::parse::ParseStream<'_>, - ) -> syn::Result { - input.parse::()?; - let name = input.parse::()?.to_string(); - let mut extends = Vec::new(); - let mut base = None; - - if input.peek(syn::Token![:]) { - input.parse::()?; - while !input.peek(syn::Token![;]) { - if input.peek(class) { - input.parse::()?; - base = Some(input.parse()?); - } else { - extends.push(input.parse()?); - } - _ = input.parse::(); - } - } - - input.parse::()?; - Ok(Self { - attributes, - name, - base, - extends, - }) - } -} - -impl Interface { - fn parse( - _namespace: &str, - winrt: bool, - attributes: Vec, - input: syn::parse::ParseStream<'_>, - ) -> syn::Result { - input.parse::()?; - let name = input.parse::()?.to_string(); - - let mut generics = Vec::new(); - - if input.peek(syn::Token![<]) { - input.parse::()?; - while input.peek(syn::Ident) { - generics.push(input.parse::()?.to_string()); - _ = input.parse::(); - } - - input.parse::]>()?; - } - - let mut extends = Vec::new(); - - if input.peek(syn::Token![:]) { - input.parse::()?; - while !input.peek(syn::token::Brace) { - extends.push(input.parse()?); - _ = input.parse::(); - } - } - - let content; - syn::braced!(content in input); - let mut methods = vec![]; - while !content.is_empty() { - methods.push(content.parse()?); - } - Ok(Self { - winrt, - attributes, - generics, - extends, - name, - methods, - }) - } -} - -impl Struct { - fn parse( - _namespace: &str, - winrt: bool, - attributes: Vec, - input: syn::parse::ParseStream<'_>, - ) -> syn::Result { - // TODO: need to validate that the struct is valid according to the constraints of the winmd type system. - // Same for the other types. That way we can spit out errors quickly for things like unnamed fields. - let span = input.span(); - let item: syn::ItemStruct = input.parse()?; - let name = item.ident.to_string(); - let mut fields = vec![]; - - let syn::Fields::Named(named) = item.fields else { - return Err(syn::Error::new(item.span(), "unnamed fields not supported")); - }; - - for field in named.named { - fields.push(Field { - span: field.span(), - attributes: field.attrs, - // Simply unwrapping since we already know that it is a named field. - name: field.ident.unwrap().to_string(), - ty: field.ty, - }); - } - - Ok(Self { - winrt, - name, - attributes, - span, - fields, - }) - } -} - -impl Enum { - fn parse( - _namespace: &str, - winrt: bool, - attributes: Vec, - input: syn::parse::ParseStream<'_>, - ) -> syn::Result { - let mut item: syn::ItemEnum = input.parse()?; - item.attrs = attributes; - let name = item.ident.to_string(); - Ok(Self { winrt, name, item }) - } -} - -impl Constant { - fn parse( - _namespace: &str, - attributes: Vec, - input: syn::parse::ParseStream<'_>, - ) -> syn::Result { - let mut item: syn::ItemConst = input.parse()?; - item.attrs = attributes; - let name = item.ident.to_string(); - Ok(Self { name, item }) - } -} - -impl Function { - fn parse( - _namespace: &str, - attributes: Vec, - input: syn::parse::ParseStream<'_>, - ) -> syn::Result { - let mut item: syn::TraitItemFn = input.parse()?; - item.attrs = attributes; - let name = item.sig.ident.to_string(); - Ok(Self { name, item }) - } -} diff --git a/crates/libs/bindgen/src/rdl/to_winmd.rs b/crates/libs/bindgen/src/rdl/to_winmd.rs deleted file mode 100644 index 4ce240dd90..0000000000 --- a/crates/libs/bindgen/src/rdl/to_winmd.rs +++ /dev/null @@ -1,415 +0,0 @@ -use super::*; -use crate::winmd::writer; - -// TODO: store span in winmd so that errors resolving type references can be traced back to file/line/column -use std::collections::HashMap; -//use syn::spanned::Spanned; - -// TODO: this creates a temporary in-memory winmd used to treat the IDL content uniformly as metadata. -// The winmd_to_winmd does the harder job of validating and producing canonical winmd for public consumption. - -pub fn rdl_to_winmd(file: &File) -> Result> { - // Local-to-qualified type names found in use declaration - e.g. "IStringable" -> "Windows.Foundation.IStringable" - // This is just a convenience for the developer to shorten common references like this but would not support globs or renames. - // Note that none of these are verified to be real until much later when the winmd is validated since we don't - // know what other metadata may be combined - let mut _use_map = HashMap::::new(); - - // TODO: read file and populate use_map - - // Types are collected here in two passes - this allows us to figure out whether a local name points to a relative type - // or a type from a use declaration...? - let mut collector = HashMap::>::new(); - - file.modules - .iter() - .for_each(|module| collect_module(&mut collector, module)); - - // TODO: collect type names into hashmap (phase 1) and just drop clones of the IDL members into the collector - - // TODO: Can we just walk the collector at this point and populate the winmd writer and thus need the read-phase? - // this second walking of the collector is basically the "define" phase - - let mut writer = winmd::Writer::new("temp.winmd"); - - collector.iter().for_each(|(namespace, members)| { - members - .iter() - .for_each(|(name, member)| write_member(&mut writer, namespace, name, member)) - }); - - Ok(writer.into_stream()) -} - -fn collect_module<'a>( - collector: &mut HashMap>, - module: &'a Module, -) { - module - .members - .iter() - .for_each(|member| collect_member(collector, module, member)); -} - -fn collect_member<'a>( - collector: &mut HashMap>, - module: &'a Module, - member: &'a ModuleMember, -) { - match member { - ModuleMember::Module(module) => collect_module(collector, module), - ModuleMember::Constant(_) | ModuleMember::Function(_) => { - collector - .entry(module.namespace.to_string()) - .or_default() - .entry("Apis") - .or_insert(member.clone()); - } - _ => { - collector - .entry(module.namespace.to_string()) - .or_default() - .entry(member.name()) - .or_insert(member.clone()); - } - } -} - -fn write_member(writer: &mut winmd::Writer, namespace: &str, name: &str, member: &ModuleMember) { - match member { - ModuleMember::Interface(member) => write_interface(writer, namespace, name, member), - ModuleMember::Struct(member) => write_struct(writer, namespace, name, member), - ModuleMember::Enum(member) => write_enum(writer, namespace, name, member), - ModuleMember::Class(member) => write_class(writer, namespace, name, member), - rest => unimplemented!("{rest:?}"), - } -} - -fn write_interface(writer: &mut winmd::Writer, namespace: &str, name: &str, member: &Interface) { - let mut flags = metadata::TypeAttributes::Public - | metadata::TypeAttributes::Interface - | metadata::TypeAttributes::Abstract; - - if member.winrt { - flags |= metadata::TypeAttributes::WindowsRuntime - } - - writer.tables.TypeDef.push(winmd::TypeDef { - Extends: winmd::TypeDefOrRef::none(), - FieldList: writer.tables.Field.len() as u32, - MethodList: writer.tables.MethodDef.len() as u32, - Flags: flags.0, - TypeName: writer.strings.insert(name), - TypeNamespace: writer.strings.insert(namespace), - }); - - for (number, generic) in member.generics.iter().enumerate() { - writer.tables.GenericParam.push(writer::GenericParam { - Number: number as u16, - Flags: 0, - Owner: writer::TypeOrMethodDef::TypeDef(writer.tables.TypeDef.len() as u32 - 1), - Name: writer.strings.insert(generic), - }); - } - - for type_path in &member.extends { - let ty = syn_type_path(namespace, &member.generics, type_path); - - let reference = match &ty { - winmd::Type::TypeRef(type_name) if type_name.generics.is_empty() => { - writer.insert_type_ref(&type_name.namespace, &type_name.name) - } - winmd::Type::TypeRef(_) => writer.insert_type_spec(ty), - rest => unimplemented!("{rest:?}"), - }; - - writer.tables.InterfaceImpl.push(writer::InterfaceImpl { - Class: writer.tables.TypeDef.len() as u32 - 1, - Interface: reference, - }); - } - - for method in &member.methods { - let signature = syn_signature(namespace, &member.generics, &method.sig); - - let params: Vec = signature - .params - .iter() - .map(|param| param.ty.clone()) - .collect(); - - let signature_blob = writer.insert_method_sig( - metadata::MethodCallAttributes(0), - &signature.return_type, - ¶ms, - ); - - let flags = metadata::MethodAttributes::Abstract - | metadata::MethodAttributes::HideBySig - | metadata::MethodAttributes::HideBySig - | metadata::MethodAttributes::NewSlot - | metadata::MethodAttributes::Public - | metadata::MethodAttributes::Virtual; - - writer.tables.MethodDef.push(winmd::MethodDef { - RVA: 0, - ImplFlags: 0, - Flags: flags.0, - Name: writer.strings.insert(&method.sig.ident.to_string()), - Signature: signature_blob, - ParamList: writer.tables.Param.len() as u32, - }); - - for (sequence, param) in signature.params.iter().enumerate() { - writer.tables.Param.push(winmd::Param { - Flags: 0, - Sequence: (sequence + 1) as u16, - Name: writer.strings.insert(¶m.name), - }); - } - } -} - -fn write_struct(writer: &mut winmd::Writer, namespace: &str, name: &str, member: &Struct) { - let mut flags = metadata::TypeAttributes::Public - | metadata::TypeAttributes::Sealed - | metadata::TypeAttributes::SequentialLayout; - - if member.winrt { - flags |= metadata::TypeAttributes::WindowsRuntime - } - - let extends = writer.insert_type_ref("System", "ValueType"); - - writer.tables.TypeDef.push(winmd::TypeDef { - Extends: extends, - FieldList: writer.tables.Field.len() as u32, - MethodList: writer.tables.MethodDef.len() as u32, - Flags: flags.0, - TypeName: writer.strings.insert(name), - TypeNamespace: writer.strings.insert(namespace), - }); - - for field in &member.fields { - let flags = metadata::FieldAttributes::Public; - let ty = syn_type(namespace, &[], &field.ty); - let signature = writer.insert_field_sig(&ty); - - writer.tables.Field.push(winmd::Field { - Flags: flags.0, - Name: writer.strings.insert(&field.name), - Signature: signature, - }); - } -} - -fn write_enum(_writer: &mut winmd::Writer, _namespace: &str, _name: &str, _member: &Enum) {} - -fn write_class(writer: &mut winmd::Writer, namespace: &str, name: &str, member: &Class) { - let flags = metadata::TypeAttributes::Public - | metadata::TypeAttributes::Sealed - | metadata::TypeAttributes::WindowsRuntime; - - let extends = if let Some(base) = &member.base { - match syn_type_path(namespace, &[], base) { - winmd::Type::TypeRef(base) => writer.insert_type_ref(&base.namespace, &base.name), - rest => unimplemented!("{rest:?}"), - } - } else { - writer.insert_type_ref("System", "Object") - }; - - writer.tables.TypeDef.push(winmd::TypeDef { - Extends: extends, - // Even though ECMA-335 says these can be "null", bugs in ILDASM necessitate this to avoid "misreading" the list terminators. - FieldList: writer.tables.Field.len() as u32, - MethodList: writer.tables.MethodDef.len() as u32, - Flags: flags.0, - TypeName: writer.strings.insert(name), - TypeNamespace: writer.strings.insert(namespace), - }); - - for (index, extends) in member.extends.iter().enumerate() { - let ty = syn_type_path(namespace, &[], extends); - - let reference = match &ty { - winmd::Type::TypeRef(type_name) if type_name.generics.is_empty() => { - writer.insert_type_ref(&type_name.namespace, &type_name.name) - } - winmd::Type::TypeRef(_) => writer.insert_type_spec(ty), - winmd::Type::IUnknown => writer.insert_type_ref("Windows.Win32.System.Com", "IUnknown"), - winmd::Type::IInspectable => { - writer.insert_type_ref("Windows.Win32.System.WinRT", "IInspectable") - } - rest => unimplemented!("{rest:?}"), - }; - - writer.tables.InterfaceImpl.push(writer::InterfaceImpl { - Class: writer.tables.TypeDef.len() as u32 - 1, - Interface: reference, - }); - - if index == 0 { - // TODO: add the DefaultAttribute to the first interface - } - } -} - -fn syn_signature(namespace: &str, generics: &[String], 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, generics, &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, generics, ty) - } else { - winmd::Type::Void - }; - - winmd::Signature { - params, - return_type, - call_flags: 0, - } -} - -fn syn_type(namespace: &str, generics: &[String], ty: &syn::Type) -> winmd::Type { - match ty { - syn::Type::Path(ty) => syn_type_path(namespace, generics, ty), - syn::Type::Ptr(ptr) => syn_type_ptr(namespace, ptr), - syn::Type::Array(array) => syn_type_array(namespace, array), - rest => unimplemented!("{rest:?}"), - } -} - -fn syn_type_array(namespace: &str, array: &syn::TypeArray) -> winmd::Type { - let ty = syn_type(namespace, &[], &array.elem); - - if let syn::Expr::Lit(lit) = &array.len { - if let syn::Lit::Int(lit) = &lit.lit { - if let Ok(len) = lit.base10_parse() { - return ty.into_array(len); - } - } - } - - unimplemented!() -} - -fn syn_type_ptr(namespace: &str, ptr: &syn::TypePtr) -> winmd::Type { - let ty = syn_type(namespace, &[], &ptr.elem); - if ptr.mutability.is_some() { - ty.into_mut_ptr() - } else { - ty.into_const_ptr() - } -} - -fn syn_type_path(namespace: &str, generics: &[String], ty: &syn::TypePath) -> winmd::Type { - if ty.qself.is_none() { - return syn_path(namespace, generics, &ty.path); - } - - unimplemented!() -} - -fn syn_path(namespace: &str, generics: &[String], path: &syn::Path) -> winmd::Type { - if let Some(segment) = path.segments.first() { - if path.segments.len() == 1 && segment.arguments.is_empty() { - let name = segment.ident.to_string(); - - if let Some(number) = generics.iter().position(|generic| generic == &name) { - return winmd::Type::GenericParam(number as u16); - } - - match name.as_str() { - "void" => return winmd::Type::Void, - "bool" => return winmd::Type::Bool, - "char" => return winmd::Type::Char, - "i8" => return winmd::Type::I8, - "u8" => return winmd::Type::U8, - "i16" => return winmd::Type::I16, - "u16" => return winmd::Type::U16, - "i32" => return winmd::Type::I32, - "u32" => return winmd::Type::U32, - "i64" => return winmd::Type::I64, - "u64" => return winmd::Type::U64, - "f32" => return winmd::Type::F32, - "f64" => return winmd::Type::F64, - "isize" => return winmd::Type::ISize, - "usize" => return winmd::Type::USize, - "HSTRING" => return winmd::Type::String, - "GUID" => return winmd::Type::GUID, - "IUnknown" => return winmd::Type::IUnknown, - "IInspectable" => return winmd::Type::IInspectable, - "HRESULT" => return winmd::Type::HRESULT, - "PSTR" => return winmd::Type::PSTR, - "PWSTR" => return winmd::Type::PWSTR, - "PCSTR" => return winmd::Type::PCSTR, - "PCWSTR" => return winmd::Type::PCWSTR, - "BSTR" => return winmd::Type::BSTR, - _ => {} - }; - } - } - - // TODO: Here we assume that paths are absolute since there's no way to disambiguate between nested and absolute paths - // The canonicalize function (should maybe) preprocesses the IDL to make this work - - let mut builder = vec![]; - - for segment in &path.segments { - let segment = segment.ident.to_string(); - - if segment == "super" { - if builder.is_empty() { - for segment in namespace.split('.') { - builder.push(segment.to_string()); - } - } - builder.pop(); - } else { - builder.push(segment); - } - } - - // Unwrapping is fine as there should always be at least one segment. - let (name, type_namespace) = builder.split_last().unwrap(); - let type_namespace = if type_namespace.is_empty() { - namespace.to_string() - } else { - type_namespace.join(".") - }; - let mut type_generics = vec![]; - - if let Some(segment) = path.segments.last() { - if let syn::PathArguments::AngleBracketed(args) = &segment.arguments { - for arg in &args.args { - match arg { - syn::GenericArgument::Type(ty) => { - type_generics.push(syn_type(namespace, generics, ty)) - } - rest => unimplemented!("{rest:?}"), - } - } - } - } - - winmd::Type::TypeRef(winmd::TypeName { - namespace: type_namespace, - name: name.to_string(), - generics: type_generics, - }) -} diff --git a/crates/libs/bindgen/src/rust/standalone.rs b/crates/libs/bindgen/src/rust/standalone.rs index bddc8e4465..2234b756dc 100644 --- a/crates/libs/bindgen/src/rust/standalone.rs +++ b/crates/libs/bindgen/src/rust/standalone.rs @@ -137,7 +137,6 @@ fn item_collect_standalone( } } } -// TODO: remove or move to riddle fn type_collect_standalone( writer: &Writer, ty: &metadata::Type, diff --git a/crates/libs/bindgen/src/tokens/mod.rs b/crates/libs/bindgen/src/tokens/mod.rs index dc37ea3e35..8dd7cf00f8 100644 --- a/crates/libs/bindgen/src/tokens/mod.rs +++ b/crates/libs/bindgen/src/tokens/mod.rs @@ -45,8 +45,6 @@ macro_rules! quote { }}; } -pub use quote; - /// Formatting macro for constructing a `TokenStream`. /// ///
diff --git a/crates/libs/bindgen/src/winmd/from_reader.rs b/crates/libs/bindgen/src/winmd/from_reader.rs deleted file mode 100644 index b01d92f066..0000000000 --- a/crates/libs/bindgen/src/winmd/from_reader.rs +++ /dev/null @@ -1,257 +0,0 @@ -use super::*; -use metadata::{AsRow, HasAttributes}; - -pub fn from_reader( - reader: &metadata::Reader, - config: std::collections::BTreeMap<&str, &str>, - output: &str, -) -> Result<()> { - let mut writer = 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(Error::new(&format!("invalid configuration value `{key}`"))); - } - - // TODO: just use the reader directly since we now have everything in the reader, there's no need to abstract - // away the source format. Few reprs is always better. - - for item in reader.items() { - // TODO: cover all variants - let metadata::Item::Type(def) = item else { - continue; - }; - - let generics = &metadata::type_def_generics(def); - - let extends = if let Some(extends) = def.extends() { - writer.insert_type_ref(extends.namespace(), extends.name()) - } else { - TypeDefOrRef::none() - }; - - writer.tables.TypeDef.push(TypeDef { - Extends: extends, - FieldList: writer.tables.Field.len() as u32, - Flags: def.flags().0, - MethodList: writer.tables.MethodDef.len() as u32, - TypeName: writer.strings.insert(def.name()), - TypeNamespace: writer.strings.insert(def.namespace()), - }); - - let def_ref = writer.tables.TypeDef.len() as u32 - 1; - - for generic in def.generics() { - writer.tables.GenericParam.push(GenericParam { - Number: generic.number(), // TODO: isn't this just going to be incremental? - Flags: 0, - Owner: TypeOrMethodDef::TypeDef(def_ref), - Name: writer.strings.insert(generic.name()), - }); - } - - for interface in metadata::type_def_interfaces(def, generics) { - let ty = winmd_type(&interface.ty); - - let reference = match &ty { - Type::TypeRef(type_name) if type_name.generics.is_empty() => { - writer.insert_type_ref(&type_name.namespace, &type_name.name) - } - Type::TypeRef(_) => writer.insert_type_spec(ty), - Type::IUnknown => writer.insert_type_ref("Windows.Win32.System.Com", "IUnknown"), - Type::IInspectable => { - writer.insert_type_ref("Windows.Win32.System.WinRT", "IInspectable") - } - rest => unimplemented!("{rest:?}"), - }; - - writer.tables.InterfaceImpl.push(InterfaceImpl { - Class: def_ref, - Interface: reference, - }); - } - - // TODO: if the class is "Apis" then should we sort the fields (constants) and methods (functions) for stability - - for field in def.fields() { - let ty = winmd_type(&field.ty(Some(def))); - let signature = writer.insert_field_sig(&ty); - - writer.tables.Field.push(Field { - Flags: field.flags().0, - Name: writer.strings.insert(field.name()), - Signature: signature, - }); - - if let Some(constant) = field.constant() { - writer.tables.Constant.push(Constant { - Type: constant.usize(0) as u16, - Parent: HasConstant::Field(writer.tables.Field.len() as u32 - 1), - Value: writer.blobs.insert(&constant.blob(2)), - }) - } - } - - for method in def.methods() { - let signature = method.signature(generics); - let return_type = winmd_type(&signature.return_type); - let param_types: Vec = signature.params.iter().map(winmd_type).collect(); - - let signature = - writer.insert_method_sig(signature.call_flags, &return_type, ¶m_types); - - writer.tables.MethodDef.push(MethodDef { - RVA: 0, - ImplFlags: method.impl_flags().0, - Flags: method.flags().0, - Name: writer.strings.insert(method.name()), - Signature: signature, - ParamList: writer.tables.Param.len() as u32, - }); - - for param in method.params() { - writer.tables.Param.push(Param { - Flags: param.flags().0, - Sequence: param.sequence(), - Name: writer.strings.insert(param.name()), - }); - } - } - - for attribute in def.attributes() { - let metadata::AttributeType::MemberRef(attribute_ctor) = attribute.ty(); - assert_eq!(attribute_ctor.name(), ".ctor"); - let metadata::MemberRefParent::TypeRef(attribute_type) = attribute_ctor.parent(); - - let attribute_type_ref = if let TypeDefOrRef::TypeRef(type_ref) = - writer.insert_type_ref(attribute_type.namespace(), attribute_type.name()) - { - MemberRefParent::TypeRef(type_ref) - } else { - panic!() - }; - - let signature = attribute_ctor.signature(); - let return_type = winmd_type(&signature.return_type); - let param_types: Vec = signature.params.iter().map(winmd_type).collect(); - let signature = - writer.insert_method_sig(signature.call_flags, &return_type, ¶m_types); - - writer.tables.MemberRef.push(MemberRef { - Class: attribute_type_ref, - Name: writer.strings.insert(".ctor"), - Signature: signature, - }); - - let mut values = 1u16.to_le_bytes().to_vec(); // prolog - let args = attribute.args(); - let mut named_arg_count = false; - - for (index, (name, value)) in args.iter().enumerate() { - value_blob(value, &mut values); - - if !named_arg_count && !name.is_empty() { - named_arg_count = true; - let named_arg_count = (args.len() - index) as u16; - values.extend_from_slice(&named_arg_count.to_le_bytes()); - break; - } - } - - if !named_arg_count { - values.extend_from_slice(&0u16.to_le_bytes()); - } - - let values = writer.blobs.insert(&values); - - writer.tables.CustomAttribute.push(CustomAttribute { - Parent: HasAttribute::TypeDef(def_ref), - Type: AttributeType::MemberRef(writer.tables.MemberRef.len() as u32 - 1), - Value: values, - }); - } - } - - // TODO: In theory, `config` could instruct this function to balance the types across a number of winmd files - // like mdmerge supports for namespace-splitting. - write_to_file(output, writer.into_stream()).map_err(|err| err.with_path(output)) -} - -// TODO: need a Blob type for writing -fn value_blob(value: &metadata::Value, blob: &mut Vec) { - match value { - metadata::Value::Bool(value) => { - if *value { - blob.push(1) - } else { - blob.push(0) - } - } - metadata::Value::U32(value) => blob.extend_from_slice(&value.to_le_bytes()), - metadata::Value::I32(value) => blob.extend_from_slice(&value.to_le_bytes()), - metadata::Value::U16(value) => blob.extend_from_slice(&value.to_le_bytes()), - metadata::Value::U8(value) => blob.extend_from_slice(&value.to_le_bytes()), - metadata::Value::EnumDef(_def, value) => value_blob(value, blob), - - metadata::Value::TypeName(value) => { - let value = value.to_string(); - usize_blob(value.len(), blob); - blob.extend_from_slice(value.as_bytes()); - } - metadata::Value::String(value) => { - usize_blob(value.len(), blob); - blob.extend_from_slice(value.as_bytes()); - } - rest => unimplemented!("{rest:?}"), - } -} - -// TODO: keep the basic type conversion -fn winmd_type(ty: &metadata::Type) -> Type { - match ty { - metadata::Type::Void => Type::Void, - metadata::Type::Bool => Type::Bool, - metadata::Type::Char => Type::Char, - metadata::Type::I8 => Type::I8, - metadata::Type::U8 => Type::U8, - metadata::Type::I16 => Type::I16, - metadata::Type::U16 => Type::U16, - metadata::Type::I32 => Type::I32, - metadata::Type::U32 => Type::U32, - metadata::Type::I64 => Type::I64, - metadata::Type::U64 => Type::U64, - metadata::Type::F32 => Type::F32, - metadata::Type::F64 => Type::F64, - metadata::Type::ISize => Type::ISize, - metadata::Type::USize => Type::USize, - metadata::Type::String => Type::String, - metadata::Type::Name(metadata::TypeName::GUID) => Type::GUID, - metadata::Type::Name(metadata::TypeName::IUnknown) => Type::IUnknown, - metadata::Type::Object => Type::IInspectable, - metadata::Type::Name(metadata::TypeName::HResult) => Type::HRESULT, - metadata::Type::Name(metadata::TypeName::PSTR) => Type::PSTR, - metadata::Type::Name(metadata::TypeName::PWSTR) => Type::PWSTR, - metadata::Type::Const(metadata::TypeName::PSTR) => Type::PCSTR, - metadata::Type::Const(metadata::TypeName::PWSTR) => Type::PCWSTR, - metadata::Type::Name(metadata::TypeName::BSTR) => Type::BSTR, - metadata::Type::Name(metadata::TypeName::Type) => Type::Type, - metadata::Type::TypeDef(def, generics) => Type::TypeRef(TypeName { - namespace: def.namespace().to_string(), - name: def.name().to_string(), - generics: generics.iter().map(winmd_type).collect(), - }), - metadata::Type::GenericParam(generic) => Type::GenericParam(generic.number()), - metadata::Type::ConstRef(ty) => Type::ConstRef(Box::new(winmd_type(ty))), - metadata::Type::WinrtArrayRef(ty) => Type::WinrtArrayRef(Box::new(winmd_type(ty))), - metadata::Type::WinrtArray(ty) => Type::WinrtArray(Box::new(winmd_type(ty))), - metadata::Type::MutPtr(ty, pointers) => Type::MutPtr(Box::new(winmd_type(ty)), *pointers), - metadata::Type::ConstPtr(ty, pointers) => { - Type::ConstPtr(Box::new(winmd_type(ty)), *pointers) - } - metadata::Type::Win32Array(ty, len) => Type::Win32Array(Box::new(winmd_type(ty)), *len), - rest => unimplemented!("{rest:?}"), - } -} diff --git a/crates/libs/bindgen/src/winmd/mod.rs b/crates/libs/bindgen/src/winmd/mod.rs deleted file mode 100644 index 3ee7c6d079..0000000000 --- a/crates/libs/bindgen/src/winmd/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod from_reader; -pub mod writer; -use super::*; -pub use from_reader::from_reader; -pub use writer::*; diff --git a/crates/libs/bindgen/src/winmd/writer/blobs.rs b/crates/libs/bindgen/src/winmd/writer/blobs.rs deleted file mode 100644 index 2393399fb1..0000000000 --- a/crates/libs/bindgen/src/winmd/writer/blobs.rs +++ /dev/null @@ -1,50 +0,0 @@ -use super::*; - -pub struct Blobs { - map: HashMap, u32>, - stream: Vec, -} - -impl Default for Blobs { - fn default() -> Self { - Self { - map: Default::default(), - stream: vec![0], - } - } -} - -impl Blobs { - pub fn insert(&mut self, value: &[u8]) -> u32 { - if value.is_empty() { - return 0; - } - - match self.map.entry(value.to_vec()) { - std::collections::hash_map::Entry::Vacant(entry) => { - let offset = *entry.insert(self.stream.len() as u32); - let len = value.len(); - match len { - 0..=0x7F => self.stream.push(len as u8), - 0x80..=0x3FFF => { - self.stream.push((0x80 | len >> 8) as u8); - self.stream.push((0xFF & len) as u8); - } - _ => { - self.stream.push((0xC0 | len >> 24) as u8); - self.stream.push((0xFF & len >> 16) as u8); - self.stream.push((0xFF & len >> 8) as u8); - self.stream.push((0xFF & len) as u8); - } - } - self.stream.extend_from_slice(value); - offset - } - std::collections::hash_map::Entry::Occupied(entry) => *entry.get(), - } - } - - pub fn into_stream(self) -> Vec { - self.stream.into_stream() - } -} diff --git a/crates/libs/bindgen/src/winmd/writer/codes.rs b/crates/libs/bindgen/src/winmd/writer/codes.rs deleted file mode 100644 index 16e2565c52..0000000000 --- a/crates/libs/bindgen/src/winmd/writer/codes.rs +++ /dev/null @@ -1,69 +0,0 @@ -#![allow(dead_code, clippy::enum_variant_names)] - -macro_rules! code { - ($name:ident($size:literal) $(($table:ident, $code:literal))+) => { - #[derive(Clone, Copy)] - pub enum $name { - $($table(u32),)* - } - impl $name { - pub fn encode(&self) -> u32 { - match self { - $(Self::$table(row) => (row.overflowing_add(1).0) << $size | $code,)* - } - } - } - }; -} - -code! { AttributeType(3) - (MemberRef, 3) -} - -// TODO: needs to be called HasCustomAttribute -code! { HasAttribute(5) - (MethodDef, 0) - (Field, 1) - (TypeRef, 2) - (TypeDef, 3) - (Param, 4) - (InterfaceImpl, 5) - (MemberRef, 6) - (TypeSpec, 13) - (GenericParam, 19) -} - -code! { HasConstant(2) - (Field, 0) -} - -code! { MemberForwarded(1) - (MethodDef, 1) -} - -code! { MemberRefParent(3) - (TypeRef, 1) -} - -code! { TypeDefOrRef(2) - (TypeDef, 0) - (TypeRef, 1) - (TypeSpec, 2) -} - -impl TypeDefOrRef { - pub fn none() -> Self { - TypeDefOrRef::TypeDef(u32::MAX) - } -} - -code! { TypeOrMethodDef(1) - (TypeDef, 0) -} - -code! { ResolutionScope(2) - (Module, 0) - (ModuleRef, 1) - (AssemblyRef, 2) - (TypeRef, 3) -} diff --git a/crates/libs/bindgen/src/winmd/writer/file.rs b/crates/libs/bindgen/src/winmd/writer/file.rs deleted file mode 100644 index 8f480d6294..0000000000 --- a/crates/libs/bindgen/src/winmd/writer/file.rs +++ /dev/null @@ -1,171 +0,0 @@ -use super::*; - -pub fn write(mut tables: Vec, mut strings: Vec, mut blobs: Vec) -> Vec { - if [tables.len(), strings.len(), blobs.len()] - .iter() - .any(|len| *len > u32::MAX as usize) - { - panic!("heap too large"); - } - - unsafe { - let mut guids = vec![0; 16]; // zero guid - let size_of_streams = tables.len() + guids.len() + strings.len() + blobs.len(); - - let mut dos: metadata::IMAGE_DOS_HEADER = core::mem::zeroed(); - dos.e_magic = metadata::IMAGE_DOS_SIGNATURE; - dos.e_lfarlc = 64; - dos.e_lfanew = core::mem::size_of::() as i32; - - let mut file: metadata::IMAGE_FILE_HEADER = core::mem::zeroed(); - file.Machine = metadata::IMAGE_FILE_MACHINE_I386; - file.NumberOfSections = 1; - file.SizeOfOptionalHeader = - core::mem::size_of::() as u16; - file.Characteristics = metadata::IMAGE_FILE_DLL - | metadata::IMAGE_FILE_32BIT_MACHINE - | metadata::IMAGE_FILE_EXECUTABLE_IMAGE; - - let mut optional: metadata::IMAGE_OPTIONAL_HEADER32 = core::mem::zeroed(); - optional.Magic = metadata::IMAGE_NT_OPTIONAL_HDR32_MAGIC; - optional.MajorLinkerVersion = 11; - optional.SizeOfInitializedData = 1024; - optional.ImageBase = 0x400000; - optional.SectionAlignment = SECTION_ALIGNMENT; - optional.FileAlignment = 512; - optional.MajorOperatingSystemVersion = 6; - optional.MinorOperatingSystemVersion = 2; - optional.MajorSubsystemVersion = 6; - optional.MinorSubsystemVersion = 2; - optional.SizeOfHeaders = 512; - optional.Subsystem = metadata::IMAGE_SUBSYSTEM_WINDOWS_CUI; - optional.DllCharacteristics = metadata::IMAGE_DLLCHARACTERISTICS_NX_COMPAT - | metadata::IMAGE_DLLCHARACTERISTICS_NO_SEH - | metadata::IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; - optional.SizeOfStackReserve = 0x100000; - optional.SizeOfHeapReserve = 4096; - optional.LoaderFlags = 0x100000; - optional.NumberOfRvaAndSizes = 16; - - let mut section: metadata::IMAGE_SECTION_HEADER = core::mem::zeroed(); - section.Name = *b".text\0\0\0"; - section.Characteristics = 0x4000_0020; - section.VirtualAddress = SECTION_ALIGNMENT; - - let mut clr: metadata::IMAGE_COR20_HEADER = core::mem::zeroed(); - clr.cb = core::mem::size_of::() as u32; - clr.MajorRuntimeVersion = 2; - clr.MinorRuntimeVersion = 5; - clr.Flags = 1; - - let metadata = metadata::METADATA_HEADER { - signature: metadata::METADATA_SIGNATURE, - major_version: 1, - minor_version: 1, - length: 20, - version: *b"WindowsRuntime 1.4\0\0", - streams: 4, - ..Default::default() - }; - - type TablesHeader = StreamHeader<4>; - type StringsHeader = StreamHeader<12>; - type GuidsHeader = StreamHeader<8>; - type BlobsHeader = StreamHeader<8>; - - let size_of_stream_headers = core::mem::size_of::() - + core::mem::size_of::() - + core::mem::size_of::() - + core::mem::size_of::(); - let size_of_image = optional.FileAlignment as usize - + core::mem::size_of::() - + core::mem::size_of::() - + size_of_stream_headers - + size_of_streams; - - optional.SizeOfImage = round(size_of_image, optional.SectionAlignment as usize) as u32; - section.Misc.VirtualSize = size_of_image as u32 - optional.FileAlignment; - section.SizeOfRawData = round( - section.Misc.VirtualSize as usize, - optional.FileAlignment as usize, - ) as u32; - - optional.DataDirectory[14] = metadata::IMAGE_DATA_DIRECTORY { - VirtualAddress: SECTION_ALIGNMENT, - Size: core::mem::size_of::() as u32, - }; - section.PointerToRawData = optional.FileAlignment; - clr.MetaData.VirtualAddress = - SECTION_ALIGNMENT + core::mem::size_of::() as u32; - clr.MetaData.Size = - section.Misc.VirtualSize - core::mem::size_of::() as u32; - - let mut buffer = Vec::::new(); - - buffer.write_header(&dos); - buffer.write_u32(metadata::IMAGE_NT_SIGNATURE); - buffer.write_header(&file); - buffer.write_header(&optional); - buffer.write_header(§ion); - debug_assert!(buffer.len() < optional.FileAlignment as usize); - buffer.resize(optional.FileAlignment as usize, 0); - buffer.write_header(&clr); - let metadata_offset = buffer.len(); - buffer.write_header(&metadata); - - let stream_offset = buffer.len() - metadata_offset + size_of_stream_headers; - let tables_header = TablesHeader::new(stream_offset as u32, tables.len() as u32, b"#~\0\0"); - let strings_header = StringsHeader::new( - tables_header.next_offset(), - strings.len() as u32, - b"#Strings\0\0\0\0", - ); - let guids_header = GuidsHeader::new( - strings_header.next_offset(), - guids.len() as u32, - b"#GUID\0\0\0", - ); - let blobs_header = BlobsHeader::new( - guids_header.next_offset(), - blobs.len() as u32, - b"#Blob\0\0\0", - ); - - buffer.write_header(&tables_header); - buffer.write_header(&strings_header); - buffer.write_header(&guids_header); - buffer.write_header(&blobs_header); - - buffer.append(&mut tables); - buffer.append(&mut strings); - buffer.append(&mut guids); - buffer.append(&mut blobs); - - assert_eq!(clr.MetaData.Size as usize, buffer.len() - metadata_offset); - assert_eq!(size_of_image, buffer.len()); - - buffer - } -} - -const SECTION_ALIGNMENT: u32 = 4096; - -#[repr(C)] -struct StreamHeader { - offset: u32, - size: u32, - name: [u8; LEN], -} - -impl StreamHeader { - fn new(offset: u32, size: u32, name: &[u8; LEN]) -> Self { - Self { - offset, - size, - name: *name, - } - } - fn next_offset(&self) -> u32 { - self.offset + self.size - } -} diff --git a/crates/libs/bindgen/src/winmd/writer/mod.rs b/crates/libs/bindgen/src/winmd/writer/mod.rs deleted file mode 100644 index 299eb206b6..0000000000 --- a/crates/libs/bindgen/src/winmd/writer/mod.rs +++ /dev/null @@ -1,363 +0,0 @@ -mod blobs; -mod codes; -mod file; -mod strings; -mod tables; -mod traits; -mod r#type; - -use super::*; -use blobs::Blobs; -pub use codes::*; -pub use r#type::*; -use std::collections::HashMap; -use strings::Strings; -pub use tables::*; -use traits::*; - -pub struct Writer { - pub blobs: Blobs, - pub strings: Strings, - pub tables: Tables, - pub scopes: HashMap, - // TODO: is this faster than jsut using a single HashMap with a (String,String) key? - pub type_refs: HashMap>, - pub type_specs: HashMap, -} - -impl Writer { - pub fn new(name: &str) -> Self { - let mut writer = Self { - blobs: Default::default(), - strings: Default::default(), - tables: Default::default(), - scopes: Default::default(), - type_refs: Default::default(), - type_specs: Default::default(), - }; - - writer.tables.TypeDef.push(TypeDef { - TypeName: writer.strings.insert(""), - Flags: 0, - TypeNamespace: 0, - Extends: TypeDefOrRef::none(), - FieldList: 0, - MethodList: 0, - }); - - let name = name.rsplit_once(['/', '\\']).map_or(name, |(_, name)| name); - - writer.tables.Module.push(Module { - Name: writer.strings.insert(name), - Mvid: 1, - ..Default::default() - }); - - let name = name.rsplit_once('.').map_or(name, |(_, name)| name); - - writer.tables.Assembly.push(Assembly { - Name: writer.strings.insert(name), - HashAlgId: 0x00008004, - MajorVersion: 0xFF, - MinorVersion: 0xFF, - BuildNumber: 0xFF, - RevisionNumber: 0xFF, - Flags: metadata::AssemblyFlags::WindowsRuntime.0, - ..Default::default() - }); - - // Some winmd parsers will fail to read without an `mscorlib` reference. The `insert_module_types` function will typically include it - // automatically but a minimal `Module` tree may not add this dependency. - writer.insert_scope("System"); - - writer - } - - pub fn into_stream(self) -> Vec { - file::write( - self.tables.into_stream(), - self.strings.into_stream(), - self.blobs.into_stream(), - ) - } - - pub fn insert_method_sig( - &mut self, - call_flags: metadata::MethodCallAttributes, - return_type: &Type, - param_types: &[Type], - ) -> u32 { - let mut blob = vec![call_flags.0]; - usize_blob(param_types.len(), &mut blob); - self.type_blob(return_type, &mut blob); - - for ty in param_types { - self.type_blob(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 type_refs, or regenerate each time. - // Profile once we can stress test this with field/method signatures. - - let mut blob = vec![0x6]; // FIELD - self.type_blob(ty, &mut blob); - - self.blobs.insert(&blob) - } - - fn insert_scope(&mut self, namespace: &str) -> ResolutionScope { - if let Some(scope) = self.scopes.get(namespace) { - *scope - } else if namespace == "System" { - let scope = ResolutionScope::AssemblyRef( - self.tables.AssemblyRef.push2(AssemblyRef { - Name: self.strings.insert("mscorlib"), - MajorVersion: 4, - PublicKeyOrToken: self - .blobs - .insert(&[0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89]), // TODO: comment on this - ..Default::default() - }), - ); - self.scopes.insert(namespace.to_string(), scope); - scope - } else { - // TODO: may need to capture the original assembly info for external type_refs. - let scope = ResolutionScope::AssemblyRef(self.tables.AssemblyRef.push2(AssemblyRef { - Name: self.strings.insert(namespace), - MajorVersion: 0xFF, - MinorVersion: 0xFF, - BuildNumber: 0xFF, - RevisionNumber: 0xFF, - Flags: metadata::AssemblyFlags::WindowsRuntime.0, - ..Default::default() - })); - self.scopes.insert(namespace.to_string(), scope); - scope - } - } - - pub fn insert_type_ref(&mut self, namespace: &str, name: &str) -> TypeDefOrRef { - if let Some(key) = self.type_refs.get(namespace) { - if let Some(reference) = key.get(name) { - return *reference; - } - } - - let scope = self.insert_scope(namespace); - - let reference = TypeDefOrRef::TypeRef(self.tables.TypeRef.push2(TypeRef { - TypeName: self.strings.insert(name), - TypeNamespace: self.strings.insert(namespace), - ResolutionScope: scope, - })); - self.type_refs - .entry(namespace.to_string()) - .or_default() - .insert(name.to_string(), reference); - reference - } - - pub fn insert_type_spec(&mut self, ty: Type) -> TypeDefOrRef { - if let Some(key) = self.type_specs.get(&ty) { - return *key; - } - - let mut blob = vec![]; - self.type_blob(&ty, &mut blob); - let signature = self.blobs.insert(&blob); - - let reference = TypeDefOrRef::TypeSpec(self.tables.TypeSpec.push2(TypeSpec { - Signature: signature, - })); - self.type_specs.insert(ty, reference); - reference - } - - fn type_blob(&mut self, ty: &Type, blob: &mut Vec) { - match ty { - Type::Void => blob.push(metadata::ELEMENT_TYPE_VOID), - Type::Bool => blob.push(metadata::ELEMENT_TYPE_BOOLEAN), - Type::Char => blob.push(metadata::ELEMENT_TYPE_CHAR), - Type::I8 => blob.push(metadata::ELEMENT_TYPE_I1), - Type::U8 => blob.push(metadata::ELEMENT_TYPE_U1), - Type::I16 => blob.push(metadata::ELEMENT_TYPE_I2), - Type::U16 => blob.push(metadata::ELEMENT_TYPE_U2), - Type::I32 => blob.push(metadata::ELEMENT_TYPE_I4), - Type::U32 => blob.push(metadata::ELEMENT_TYPE_U4), - Type::I64 => blob.push(metadata::ELEMENT_TYPE_I8), - Type::U64 => blob.push(metadata::ELEMENT_TYPE_U8), - Type::F32 => blob.push(metadata::ELEMENT_TYPE_R4), - Type::F64 => blob.push(metadata::ELEMENT_TYPE_R8), - Type::ISize => blob.push(metadata::ELEMENT_TYPE_I), - Type::USize => blob.push(metadata::ELEMENT_TYPE_U), - Type::String => blob.push(metadata::ELEMENT_TYPE_STRING), - Type::IInspectable => blob.push(metadata::ELEMENT_TYPE_OBJECT), - Type::GUID => { - let code = self.insert_type_ref("System", "Guid"); - blob.push(metadata::ELEMENT_TYPE_VALUETYPE); - usize_blob(code.encode() as usize, blob); - } - Type::HRESULT => { - let code = self.insert_type_ref("Windows.Foundation", "HResult"); - blob.push(metadata::ELEMENT_TYPE_VALUETYPE); - usize_blob(code.encode() as usize, blob); - } - Type::TypeRef(ty) => { - if !ty.generics.is_empty() { - blob.push(metadata::ELEMENT_TYPE_GENERICINST); - } - let code = self.insert_type_ref(&ty.namespace, &ty.name); - blob.push(metadata::ELEMENT_TYPE_VALUETYPE); - usize_blob(code.encode() as usize, blob); - - if !ty.generics.is_empty() { - usize_blob(ty.generics.len(), blob); - - for ty in &ty.generics { - self.type_blob(ty, blob); - } - } - } - Type::BSTR => { - let code = self.insert_type_ref("Windows.Win32.Foundation", "BSTR"); - blob.push(metadata::ELEMENT_TYPE_VALUETYPE); - usize_blob(code.encode() as usize, blob); - } - Type::IUnknown => { - let code = self.insert_type_ref("Windows.Win32.Foundation", "IUnknown"); - blob.push(metadata::ELEMENT_TYPE_VALUETYPE); - usize_blob(code.encode() as usize, blob); - } - Type::PCWSTR | Type::PWSTR => { - let code = self.insert_type_ref("Windows.Win32.Foundation", "PWSTR"); - blob.push(metadata::ELEMENT_TYPE_VALUETYPE); - usize_blob(code.encode() as usize, blob); - } - Type::PCSTR | Type::PSTR => { - let code = self.insert_type_ref("Windows.Win32.Foundation", "PSTR"); - blob.push(metadata::ELEMENT_TYPE_VALUETYPE); - usize_blob(code.encode() as usize, blob); - } - Type::ConstRef(ty) => { - usize_blob(metadata::ELEMENT_TYPE_CMOD_OPT as usize, blob); - usize_blob( - self.insert_type_ref("System.Runtime.CompilerServices", "IsConst") - .encode() as usize, - blob, - ); - usize_blob(metadata::ELEMENT_TYPE_BYREF as usize, blob); - self.type_blob(ty, blob); - } - Type::WinrtArrayRef(ty) => { - usize_blob(metadata::ELEMENT_TYPE_BYREF as usize, blob); - usize_blob(metadata::ELEMENT_TYPE_SZARRAY as usize, blob); - self.type_blob(ty, blob); - } - Type::WinrtArray(ty) => { - usize_blob(metadata::ELEMENT_TYPE_SZARRAY as usize, blob); - self.type_blob(ty, blob); - } - Type::Win32Array(ty, bounds) => { - usize_blob(metadata::ELEMENT_TYPE_ARRAY as usize, blob); - self.type_blob(ty, blob); - usize_blob(1, blob); // rank - usize_blob(1, blob); // count - usize_blob(*bounds, blob); - } - Type::Type => { - let code = self.insert_type_ref("System", "Type"); - blob.push(metadata::ELEMENT_TYPE_CLASS); - usize_blob(code.encode() as usize, blob); - } - Type::MutPtr(ty, pointers) | Type::ConstPtr(ty, pointers) => { - for _ in 0..*pointers { - usize_blob(metadata::ELEMENT_TYPE_PTR as usize, blob); - } - self.type_blob(ty, blob); - } - Type::GenericParam(index) => { - blob.push(metadata::ELEMENT_TYPE_VAR); - usize_blob(*index as usize, blob); - } - } - } -} - -fn round(size: usize, round: usize) -> usize { - let round = round - 1; - (size + round) & !round -} - -// TODO: need a Blob type for writing -pub fn usize_blob(value: usize, blob: &mut Vec) { - // See II.23.2 in ECMA-335 - assert!(value < 0x20000000); - - if value < 0x80 { - blob.push(value as u8); - } else if value < 0x4000 { - blob.push((0x80 | (value & 0x3F00) >> 8) as u8); - blob.push((value & 0xFF) as u8); - } else { - blob.push((0xC0 | (value & 0x1F000000) >> 24) as u8); - blob.push(((value & 0xFF0000) >> 16) as u8); - blob.push(((value & 0xFF00) >> 8) as u8); - blob.push((value & 0xFF) as u8); - } -} - -// #[cfg(test)] -// mod tests { -// use super::*; - -// #[test] -// fn test_usize_blob() { -// let mut blob = vec![]; -// usize_blob(0, &mut blob); -// usize_blob(1, &mut blob); -// usize_blob(2, &mut blob); - -// usize_blob(0x80 - 2, &mut blob); -// usize_blob(0x80 - 1, &mut blob); -// usize_blob(0x80, &mut blob); -// usize_blob(0x80 + 1, &mut blob); -// usize_blob(0x80 + 2, &mut blob); - -// usize_blob(0x4000 - 2, &mut blob); -// usize_blob(0x4000 - 1, &mut blob); -// usize_blob(0x4000, &mut blob); -// usize_blob(0x4000 + 1, &mut blob); -// usize_blob(0x4000 + 2, &mut blob); - -// usize_blob(0x20000000 - 3, &mut blob); -// usize_blob(0x20000000 - 2, &mut blob); -// usize_blob(0x20000000 - 1, &mut blob); - -// let mut blob = metadata::Blob::new(0, &blob); -// assert_eq!(blob.read_usize(), 0); -// assert_eq!(blob.read_usize(), 1); -// assert_eq!(blob.read_usize(), 2); - -// assert_eq!(blob.read_usize(), 0x80 - 2); -// assert_eq!(blob.read_usize(), 0x80 - 1); -// assert_eq!(blob.read_usize(), 0x80); -// assert_eq!(blob.read_usize(), 0x80 + 1); -// assert_eq!(blob.read_usize(), 0x80 + 2); - -// assert_eq!(blob.read_usize(), 0x4000 - 2); -// assert_eq!(blob.read_usize(), 0x4000 - 1); -// assert_eq!(blob.read_usize(), 0x4000); -// assert_eq!(blob.read_usize(), 0x4000 + 1); -// assert_eq!(blob.read_usize(), 0x4000 + 2); - -// assert_eq!(blob.read_usize(), 0x20000000 - 3); -// assert_eq!(blob.read_usize(), 0x20000000 - 2); -// assert_eq!(blob.read_usize(), 0x20000000 - 1); - -// assert_eq!(blob.slice.len(), 0); -// } -// } diff --git a/crates/libs/bindgen/src/winmd/writer/strings.rs b/crates/libs/bindgen/src/winmd/writer/strings.rs deleted file mode 100644 index f7c3dd9c06..0000000000 --- a/crates/libs/bindgen/src/winmd/writer/strings.rs +++ /dev/null @@ -1,38 +0,0 @@ -use super::*; -use std::collections::hash_map::*; - -pub struct Strings { - map: HashMap, - stream: Vec, -} - -impl Default for Strings { - fn default() -> Self { - Self { - map: Default::default(), - stream: vec![0], - } - } -} - -impl Strings { - pub fn insert(&mut self, value: &str) -> u32 { - if value.is_empty() { - return 0; - } - - match self.map.entry(value.to_string()) { - Entry::Vacant(entry) => { - let offset = *entry.insert(self.stream.len() as u32); - self.stream.extend_from_slice(value.as_bytes()); - self.stream.push(0); - offset - } - Entry::Occupied(entry) => *entry.get(), - } - } - - pub fn into_stream(self) -> Vec { - self.stream.into_stream() - } -} diff --git a/crates/libs/bindgen/src/winmd/writer/tables.rs b/crates/libs/bindgen/src/winmd/writer/tables.rs deleted file mode 100644 index 7f055e5853..0000000000 --- a/crates/libs/bindgen/src/winmd/writer/tables.rs +++ /dev/null @@ -1,426 +0,0 @@ -#![allow(dead_code, non_snake_case)] - -use super::*; - -#[derive(Default)] -pub struct Tables { - // TODO: use BTreeSet for tables that have a primary key, unless they are naturally sorted. - pub Assembly: Vec, - pub AssemblyRef: Vec, - pub ClassLayout: Vec, - pub Constant: Vec, - pub CustomAttribute: Vec, - pub Field: Vec, - pub GenericParam: Vec, - pub ImplMap: Vec, - pub InterfaceImpl: Vec, - pub MemberRef: Vec, - pub MethodDef: Vec, - pub Module: Vec, - pub ModuleRef: Vec, - pub NestedClass: Vec, - pub Param: Vec, - pub Property: Vec, - pub TypeDef: Vec, - pub TypeRef: Vec, - pub TypeSpec: Vec, -} - -#[derive(Default)] -pub struct Assembly { - pub HashAlgId: u32, - pub MajorVersion: u16, - pub MinorVersion: u16, - pub BuildNumber: u16, - pub RevisionNumber: u16, - pub Flags: u32, - pub PublicKey: u32, - pub Name: u32, - pub Culture: u32, -} - -#[derive(Default)] -pub struct AssemblyRef { - pub MajorVersion: u16, - pub MinorVersion: u16, - pub BuildNumber: u16, - pub RevisionNumber: u16, - pub Flags: u32, - pub PublicKeyOrToken: u32, - pub Name: u32, - pub Culture: u32, - pub HashValue: u32, -} - -#[derive(Default)] -pub struct ClassLayout { - pub PackingSize: u16, - pub ClassSize: u32, - pub Parent: u32, -} - -pub struct Constant { - pub Type: u16, - pub Parent: HasConstant, - pub Value: u32, -} - -pub struct CustomAttribute { - pub Parent: HasAttribute, - pub Type: AttributeType, - pub Value: u32, -} - -#[derive(Default)] -pub struct Field { - pub Flags: u16, - pub Name: u32, - pub Signature: u32, -} - -pub struct GenericParam { - pub Number: u16, - pub Flags: u16, - pub Owner: TypeOrMethodDef, - pub Name: u32, -} - -#[derive(Default)] -pub struct ImplMap { - pub MappingFlags: u16, - pub MemberForwarded: u32, - pub ImportName: u32, - pub ImportScope: u32, -} - -pub struct InterfaceImpl { - pub Class: u32, - pub Interface: TypeDefOrRef, -} - -pub struct MemberRef { - pub Class: MemberRefParent, - pub Name: u32, - pub Signature: u32, -} - -#[derive(Default)] -pub struct MethodDef { - pub RVA: u32, - pub ImplFlags: u16, - pub Flags: u16, - pub Name: u32, - pub Signature: u32, - pub ParamList: u32, -} - -#[derive(Default)] -pub struct Module { - pub Generation: u16, - pub Name: u32, - pub Mvid: u32, - pub EncId: u32, - pub EncBaseId: u32, -} - -#[derive(Default)] -pub struct ModuleRef { - pub Name: u32, -} - -#[derive(Default)] -pub struct NestedClass { - pub NestedClass: u32, - pub EnclosingClass: u32, -} - -#[derive(Default)] -pub struct Param { - pub Flags: u16, - pub Sequence: u16, - pub Name: u32, -} - -#[derive(Default)] -pub struct Property { - pub Flags: u16, - pub Name: u32, - pub Type: u32, -} - -pub struct TypeDef { - pub Flags: u32, - pub TypeName: u32, - pub TypeNamespace: u32, - pub Extends: TypeDefOrRef, - pub FieldList: u32, - pub MethodList: u32, -} - -pub struct TypeRef { - pub ResolutionScope: ResolutionScope, - pub TypeName: u32, - pub TypeNamespace: u32, -} - -#[derive(Default)] -pub struct TypeSpec { - pub Signature: u32, -} - -impl Tables { - pub fn into_stream(self) -> Vec { - if [ - self.AssemblyRef.len(), - self.ClassLayout.len(), - self.Constant.len(), - self.CustomAttribute.len(), - self.Field.len(), - self.GenericParam.len(), - self.ImplMap.len(), - self.InterfaceImpl.len(), - self.MemberRef.len(), - self.MethodDef.len(), - self.Module.len(), - self.ModuleRef.len(), - self.NestedClass.len(), - self.Param.len(), - self.Property.len(), - self.TypeDef.len(), - self.TypeRef.len(), - self.TypeSpec.len(), - ] - .iter() - .any(|len| *len > u32::MAX as usize) - { - panic!("metadata table too large"); - } - - let resolution_scope = metadata::coded_index_size(&[ - self.Module.len(), - self.ModuleRef.len(), - self.AssemblyRef.len(), - self.TypeRef.len(), - ]); - let type_def_or_ref = metadata::coded_index_size(&[ - self.TypeDef.len(), - self.TypeRef.len(), - self.TypeSpec.len(), - ]); - let has_constant = - metadata::coded_index_size(&[self.Field.len(), self.Param.len(), self.Property.len()]); - let type_or_method_def = - metadata::coded_index_size(&[self.TypeDef.len(), self.MethodDef.len()]); - let member_ref_parent = metadata::coded_index_size(&[ - self.TypeDef.len(), - self.TypeRef.len(), - self.ModuleRef.len(), - self.MethodDef.len(), - self.TypeSpec.len(), - ]); - let custom_attribute_type = - metadata::coded_index_size(&[self.MethodDef.len(), self.MemberRef.len(), 0, 0, 0]); - let has_custom_attribute = metadata::coded_index_size(&[ - self.MethodDef.len(), - self.Field.len(), - self.TypeRef.len(), - self.TypeDef.len(), - self.Param.len(), - self.InterfaceImpl.len(), - self.MemberRef.len(), - self.Module.len(), - 0, - 0, - 0, - self.ModuleRef.len(), - self.TypeSpec.len(), - 0, - self.AssemblyRef.len(), - 0, - 0, - 0, - self.GenericParam.len(), - 0, - 0, - ]); - - let valid_tables: u64 = 1 << 0 | // Module - 1 << 0x01 | // TypeRef - 1 << 0x02 | // TypeDef - 1 << 0x04 | // Field - 1 << 0x06 | // MethodDef - 1 << 0x08 | // Param - 1 << 0x09 | // InterfaceImpl - 1 << 0x0A | // MemberRef - 1 << 0x0B | // Constant - 1 << 0x0C | // CustomAttribute - 1 << 0x0F | // ClassLayout - 1 << 0x17 | // Property - 1 << 0x1A | // ModuleRef - 1 << 0x1B | // TypeSpec - 1 << 0x1C | // ImplMap - 1 << 0x20 | // Assembly - 1 << 0x23 | // AssemblyRef - 1 << 0x29 | // NestedClass - 1 << 0x2A; // GenericParam - - // The table stream header... - - let mut buffer = Vec::new(); - buffer.write_u32(0); // Reserved - buffer.write_u8(2); // MajorVersion - buffer.write_u8(0); // MinorVersion - buffer.write_u8(0b111); // HeapSizes - buffer.write_u8(0); // Reserved - buffer.write_u64(valid_tables); - buffer.write_u64(0); // Sorted - - // Followed by the length of each of the valid tables... - - buffer.write_u32(self.Module.len() as u32); - buffer.write_u32(self.TypeRef.len() as u32); - buffer.write_u32(self.TypeDef.len() as u32); - buffer.write_u32(self.Field.len() as u32); - buffer.write_u32(self.MethodDef.len() as u32); - buffer.write_u32(self.Param.len() as u32); - buffer.write_u32(self.InterfaceImpl.len() as u32); - buffer.write_u32(self.MemberRef.len() as u32); - buffer.write_u32(self.Constant.len() as u32); - buffer.write_u32(self.CustomAttribute.len() as u32); - buffer.write_u32(self.ClassLayout.len() as u32); - buffer.write_u32(self.Property.len() as u32); - buffer.write_u32(self.ModuleRef.len() as u32); - buffer.write_u32(self.TypeSpec.len() as u32); - buffer.write_u32(self.ImplMap.len() as u32); - buffer.write_u32(self.Assembly.len() as u32); - buffer.write_u32(self.AssemblyRef.len() as u32); - buffer.write_u32(self.NestedClass.len() as u32); - buffer.write_u32(self.GenericParam.len() as u32); - - // Followed by each table's rows... - - for x in self.Module { - buffer.write_u16(x.Generation); - buffer.write_u32(x.Name); - buffer.write_u32(x.Mvid); - buffer.write_u32(x.EncId); - buffer.write_u32(x.EncBaseId); - } - - for x in self.TypeRef { - buffer.write_code(x.ResolutionScope.encode(), resolution_scope); - buffer.write_u32(x.TypeName); - buffer.write_u32(x.TypeNamespace); - } - - for x in &self.TypeDef { - buffer.write_u32(x.Flags); - buffer.write_u32(x.TypeName); - buffer.write_u32(x.TypeNamespace); - buffer.write_code(x.Extends.encode(), type_def_or_ref); - buffer.write_index(x.FieldList, self.Field.len()); - buffer.write_index(x.MethodList, self.MethodDef.len()); - } - - for x in self.Field { - buffer.write_u16(x.Flags); - buffer.write_u32(x.Name); - buffer.write_u32(x.Signature); - } - - for x in self.MethodDef { - buffer.write_u32(x.RVA); - buffer.write_u16(x.ImplFlags); - buffer.write_u16(x.Flags); - buffer.write_u32(x.Name); - buffer.write_u32(x.Signature); - buffer.write_index(x.ParamList, self.Param.len()); - } - - for x in self.Param { - buffer.write_u16(x.Flags); - buffer.write_u16(x.Sequence); - buffer.write_u32(x.Name); - } - - for x in self.InterfaceImpl { - buffer.write_index(x.Class, self.TypeDef.len()); - buffer.write_code(x.Interface.encode(), type_def_or_ref); - } - - for x in self.MemberRef { - buffer.write_code(x.Class.encode(), member_ref_parent); - buffer.write_u32(x.Name); - buffer.write_u32(x.Signature); - } - - for x in self.Constant { - buffer.write_u16(x.Type); - buffer.write_code(x.Parent.encode(), has_constant); - buffer.write_u32(x.Value); - } - - for x in self.CustomAttribute { - buffer.write_code(x.Parent.encode(), has_custom_attribute); - buffer.write_code(x.Type.encode(), custom_attribute_type); - buffer.write_u32(x.Value); - } - - for x in self.TypeSpec { - buffer.write_u32(x.Signature); - } - - for x in self.Assembly { - buffer.write_u32(x.HashAlgId); - buffer.write_u16(x.MajorVersion); - buffer.write_u16(x.MinorVersion); - buffer.write_u16(x.BuildNumber); - buffer.write_u16(x.RevisionNumber); - buffer.write_u32(x.Flags); - buffer.write_u32(x.PublicKey); - buffer.write_u32(x.Name); - buffer.write_u32(x.Culture); - } - - for x in self.AssemblyRef { - buffer.write_u16(x.MajorVersion); - buffer.write_u16(x.MinorVersion); - buffer.write_u16(x.BuildNumber); - buffer.write_u16(x.RevisionNumber); - buffer.write_u32(x.Flags); - buffer.write_u32(x.PublicKeyOrToken); - buffer.write_u32(x.Name); - buffer.write_u32(x.Culture); - buffer.write_u32(x.HashValue); - } - - for x in self.GenericParam { - buffer.write_u16(x.Number); - buffer.write_u16(x.Flags); - buffer.write_code(x.Owner.encode(), type_or_method_def); - buffer.write_u32(x.Name); - } - - // TODO: sort GenericParam table prior to writing. This needs to be done for all tables with a primary index. See II.22 - - // TODO: do these get naturally sorted by virtue of how they're pushed into "tables" in type def order? - - // Table Primary Key Column - // ClassLayout Parent - // Constant Parent - // CustomAttribute Parent - // DeclSecurity Parent - // FieldLayout Field - // FieldMarshal Parent - // FieldRVA Field - // GenericParam Owner - // GenericParamConstraint Owner - // ImplMap MemberForwarded - // InterfaceImpl Class - // MethodImpl Class - // MethodSemantics Association - // NestedClass NestedClass - - buffer.into_stream() - } -} diff --git a/crates/libs/bindgen/src/winmd/writer/traits.rs b/crates/libs/bindgen/src/winmd/writer/traits.rs deleted file mode 100644 index 109b128939..0000000000 --- a/crates/libs/bindgen/src/winmd/writer/traits.rs +++ /dev/null @@ -1,69 +0,0 @@ -use super::*; - -pub trait Write { - unsafe fn write_header(&mut self, value: &T); - fn write_u8(&mut self, value: u8); - fn write_u16(&mut self, value: u16); - fn write_u32(&mut self, value: u32); - fn write_u64(&mut self, value: u64); - fn write_code(&mut self, value: u32, size: usize); - fn write_index(&mut self, index: u32, len: usize); - fn into_stream(self) -> Self; -} - -impl Write for Vec { - unsafe fn write_header(&mut self, value: &T) { - self.extend_from_slice(std::slice::from_raw_parts( - value as *const _ as _, - core::mem::size_of::(), - )); - } - - fn write_u8(&mut self, value: u8) { - self.extend_from_slice(&value.to_le_bytes()); - } - - fn write_u16(&mut self, value: u16) { - self.extend_from_slice(&value.to_le_bytes()); - } - - fn write_u32(&mut self, value: u32) { - self.extend_from_slice(&value.to_le_bytes()); - } - - fn write_u64(&mut self, value: u64) { - self.extend_from_slice(&value.to_le_bytes()); - } - - fn write_code(&mut self, value: u32, size: usize) { - if size == 2 { - self.write_u16(value as u16); - } else { - self.write_u32(value); - } - } - - fn write_index(&mut self, index: u32, len: usize) { - if len < (1 << 16) { - self.write_u16(index as u16 + 1); - } else { - self.write_u32(index + 1); - } - } - - fn into_stream(mut self) -> Self { - self.resize(round(self.len(), 4), 0); - self - } -} - -pub trait Push2 { - fn push2(&mut self, value: T) -> u32; -} - -impl Push2 for Vec { - fn push2(&mut self, value: T) -> u32 { - self.push(value); - (self.len() - 1) as u32 - } -} diff --git a/crates/libs/bindgen/src/winmd/writer/type.rs b/crates/libs/bindgen/src/winmd/writer/type.rs deleted file mode 100644 index f04f866367..0000000000 --- a/crates/libs/bindgen/src/winmd/writer/type.rs +++ /dev/null @@ -1,80 +0,0 @@ -#![allow(dead_code, clippy::upper_case_acronyms, clippy::enum_variant_names)] - -#[derive(Clone, Debug, Hash, PartialEq, Eq)] -pub struct TypeName { - pub namespace: String, - pub name: String, - pub generics: Vec, -} - -#[derive(Clone, Debug, Hash, PartialEq, Eq)] -pub enum Type { - Void, - Bool, - Char, - I8, - U8, - I16, - U16, - I32, - U32, - I64, - U64, - F32, - F64, - ISize, - USize, - String, - GUID, - IUnknown, - IInspectable, - HRESULT, - PSTR, - PWSTR, - PCSTR, - PCWSTR, - BSTR, - Type, - TypeRef(TypeName), - GenericParam(u16), - MutPtr(Box, usize), - ConstPtr(Box, usize), - Win32Array(Box, usize), - WinrtArray(Box), - WinrtArrayRef(Box), - ConstRef(Box), -} - -impl Type { - pub fn into_mut_ptr(self) -> Self { - match self { - Self::MutPtr(ty, count) => Self::MutPtr(ty, count + 1), - Self::ConstPtr(ty, count) => Self::MutPtr(ty, count + 1), - _ => Self::MutPtr(Box::new(self), 1), - } - } - - pub fn into_const_ptr(self) -> Self { - match self { - Self::MutPtr(ty, count) => Self::ConstPtr(ty, count + 1), - Self::ConstPtr(ty, count) => Self::ConstPtr(ty, count + 1), - _ => Self::ConstPtr(Box::new(self), 1), - } - } - - pub fn into_array(self, len: usize) -> Self { - 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, -} diff --git a/crates/libs/metadata/src/reader.rs b/crates/libs/metadata/src/reader.rs index 7e973cee9e..7f21fc0c74 100644 --- a/crates/libs/metadata/src/reader.rs +++ b/crates/libs/metadata/src/reader.rs @@ -13,7 +13,6 @@ pub struct Reader { // TODO: get rid of inner Vec - that's just a hack to support multi-arch structs in Win32 metadata. items: BTreeMap<&'static str, BTreeMap<&'static str, Vec>>, - // TODO: riddle should just avoid nested structs nested: HashMap>, // The reader needs to store the filter since standalone code generation needs more than just the filtered items diff --git a/crates/libs/metadata/src/tables.rs b/crates/libs/metadata/src/tables.rs index 73f23ed67c..b218d69e3f 100644 --- a/crates/libs/metadata/src/tables.rs +++ b/crates/libs/metadata/src/tables.rs @@ -177,7 +177,6 @@ impl Field { .next() } - // TODO: enclosing craziness is only needed for nested structs - get rid of those in riddle and this goes away. pub fn ty(&self, enclosing: Option) -> Type { let mut blob = self.blob(2); blob.read_usize(); diff --git a/crates/tests/misc/component/build.rs b/crates/tests/misc/component/build.rs index 86dcca4c49..32d7aa1dd3 100644 --- a/crates/tests/misc/component/build.rs +++ b/crates/tests/misc/component/build.rs @@ -35,10 +35,5 @@ fn main() { "no-bindgen-comment".to_owned(), ]; - windows_bindgen::bindgen(&command).unwrap_or_else(|e| { - panic!( - "Failed to run bindgen: {e:?}\nArgs: riddle.exe {args}", - args = command.join(" ") - ) - }); + windows_bindgen::bindgen(&command).unwrap(); } diff --git a/crates/tests/misc/component_client/build.rs b/crates/tests/misc/component_client/build.rs index 815c4e90d7..fb6bec328d 100644 --- a/crates/tests/misc/component_client/build.rs +++ b/crates/tests/misc/component_client/build.rs @@ -11,10 +11,5 @@ fn main() { "no-bindgen-comment".to_owned(), ]; - windows_bindgen::bindgen(&command).unwrap_or_else(|e| { - panic!( - "Failed to run bindgen: {e:?}\nArgs: riddle.exe {args}", - args = command.join(" ") - ) - }); + windows_bindgen::bindgen(&command).unwrap(); } diff --git a/crates/tests/misc/riddle/Cargo.toml b/crates/tests/misc/riddle/Cargo.toml deleted file mode 100644 index 393683c2fe..0000000000 --- a/crates/tests/misc/riddle/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "test_riddle" -version = "0.0.0" -edition = "2021" -publish = false - -[lib] -doc = false -doctest = false - -[dependencies.windows-core] -workspace = true - -[dependencies.windows-metadata] -workspace = true - -[dependencies.helpers] -workspace = true - -[dependencies.windows-bindgen] -workspace = true diff --git a/crates/tests/misc/riddle/src/composition.rs b/crates/tests/misc/riddle/src/composition.rs deleted file mode 100644 index 8b13789179..0000000000 --- a/crates/tests/misc/riddle/src/composition.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/tests/misc/riddle/src/generic_interfaces.rs b/crates/tests/misc/riddle/src/generic_interfaces.rs deleted file mode 100644 index 0426005dc5..0000000000 --- a/crates/tests/misc/riddle/src/generic_interfaces.rs +++ /dev/null @@ -1,378 +0,0 @@ -#![allow( - non_snake_case, - non_upper_case_globals, - non_camel_case_types, - dead_code, - clippy::all -)] -#[repr(transparent)] -#[derive(PartialEq, Eq, Debug, Clone)] -pub struct IIterable(windows_core::IUnknown, core::marker::PhantomData) -where - T: windows_core::RuntimeType + 'static; -impl core::ops::Deref for IIterable { - type Target = windows_core::IInspectable; - fn deref(&self) -> &Self::Target { - unsafe { core::mem::transmute(self) } - } -} -impl windows_core::imp::CanInto - for IIterable -{ -} -impl windows_core::imp::CanInto - for IIterable -{ -} -impl IIterable { - pub fn First(&self) -> windows_core::Result> { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).First)( - windows_core::Interface::as_raw(this), - &mut result__, - ) - .and_then(|| windows_core::Type::from_abi(result__)) - } - } -} -impl windows_core::RuntimeType for IIterable { - const SIGNATURE: windows_core::imp::ConstBuffer = { - windows_core::imp::ConstBuffer::new() - .push_slice(b"pinterface(") - .push_slice(b"TODO") - .push_slice(b";") - .push_other(T::SIGNATURE) - .push_slice(b")") - }; -} -unsafe impl windows_core::Interface for IIterable { - type Vtable = IIterable_Vtbl; - const IID: windows_core::GUID = - windows_core::GUID::from_signature(::SIGNATURE); -} -#[repr(C)] -pub struct IIterable_Vtbl -where - T: windows_core::RuntimeType + 'static, -{ - pub base__: windows_core::IInspectable_Vtbl, - pub First: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut *mut core::ffi::c_void, - ) -> windows_core::HRESULT, - pub T: core::marker::PhantomData, -} -#[repr(transparent)] -#[derive(PartialEq, Eq, Debug, Clone)] -pub struct IIterator(windows_core::IUnknown, core::marker::PhantomData) -where - T: windows_core::RuntimeType + 'static; -impl core::ops::Deref for IIterator { - type Target = windows_core::IInspectable; - fn deref(&self) -> &Self::Target { - unsafe { core::mem::transmute(self) } - } -} -impl windows_core::imp::CanInto - for IIterator -{ -} -impl windows_core::imp::CanInto - for IIterator -{ -} -impl IIterator { - pub fn get_Current(&self) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).get_Current)( - windows_core::Interface::as_raw(this), - &mut result__, - ) - .and_then(|| windows_core::Type::from_abi(result__)) - } - } - pub fn get_HasCurrent(&self) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).get_HasCurrent)( - windows_core::Interface::as_raw(this), - &mut result__, - ) - .map(|| result__) - } - } - pub fn MoveNext(&self) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).MoveNext)( - windows_core::Interface::as_raw(this), - &mut result__, - ) - .map(|| result__) - } - } -} -impl windows_core::RuntimeType for IIterator { - const SIGNATURE: windows_core::imp::ConstBuffer = { - windows_core::imp::ConstBuffer::new() - .push_slice(b"pinterface(") - .push_slice(b"TODO") - .push_slice(b";") - .push_other(T::SIGNATURE) - .push_slice(b")") - }; -} -unsafe impl windows_core::Interface for IIterator { - type Vtable = IIterator_Vtbl; - const IID: windows_core::GUID = - windows_core::GUID::from_signature(::SIGNATURE); -} -#[repr(C)] -pub struct IIterator_Vtbl -where - T: windows_core::RuntimeType + 'static, -{ - pub base__: windows_core::IInspectable_Vtbl, - pub get_Current: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut windows_core::AbiType, - ) -> windows_core::HRESULT, - pub get_HasCurrent: - unsafe extern "system" fn(*mut core::ffi::c_void, *mut bool) -> windows_core::HRESULT, - pub MoveNext: - unsafe extern "system" fn(*mut core::ffi::c_void, *mut bool) -> windows_core::HRESULT, - pub T: core::marker::PhantomData, -} -#[repr(transparent)] -#[derive(PartialEq, Eq, Debug, Clone)] -pub struct IKeyValuePair( - windows_core::IUnknown, - core::marker::PhantomData, - core::marker::PhantomData, -) -where - K: windows_core::RuntimeType + 'static, - V: windows_core::RuntimeType + 'static; -impl - core::ops::Deref for IKeyValuePair -{ - type Target = windows_core::IInspectable; - fn deref(&self) -> &Self::Target { - unsafe { core::mem::transmute(self) } - } -} -impl - windows_core::imp::CanInto for IKeyValuePair -{ -} -impl - windows_core::imp::CanInto for IKeyValuePair -{ -} -impl - IKeyValuePair -{ - pub fn get_Key(&self) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).get_Key)( - windows_core::Interface::as_raw(this), - &mut result__, - ) - .and_then(|| windows_core::Type::from_abi(result__)) - } - } - pub fn get_Value(&self) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).get_Value)( - windows_core::Interface::as_raw(this), - &mut result__, - ) - .and_then(|| windows_core::Type::from_abi(result__)) - } - } -} -impl - windows_core::RuntimeType for IKeyValuePair -{ - const SIGNATURE: windows_core::imp::ConstBuffer = { - windows_core::imp::ConstBuffer::new() - .push_slice(b"pinterface(") - .push_slice(b"TODO") - .push_slice(b";") - .push_other(K::SIGNATURE) - .push_slice(b";") - .push_other(V::SIGNATURE) - .push_slice(b")") - }; -} -unsafe impl - windows_core::Interface for IKeyValuePair -{ - type Vtable = IKeyValuePair_Vtbl; - const IID: windows_core::GUID = - windows_core::GUID::from_signature(::SIGNATURE); -} -#[repr(C)] -pub struct IKeyValuePair_Vtbl -where - K: windows_core::RuntimeType + 'static, - V: windows_core::RuntimeType + 'static, -{ - pub base__: windows_core::IInspectable_Vtbl, - pub get_Key: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut windows_core::AbiType, - ) -> windows_core::HRESULT, - pub get_Value: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut windows_core::AbiType, - ) -> windows_core::HRESULT, - pub K: core::marker::PhantomData, - pub V: core::marker::PhantomData, -} -#[repr(transparent)] -#[derive(PartialEq, Eq, Debug, Clone)] -pub struct IMapView( - windows_core::IUnknown, - core::marker::PhantomData, - core::marker::PhantomData, -) -where - K: windows_core::RuntimeType + 'static, - V: windows_core::RuntimeType + 'static; -impl - core::ops::Deref for IMapView -{ - type Target = windows_core::IInspectable; - fn deref(&self) -> &Self::Target { - unsafe { core::mem::transmute(self) } - } -} -impl - windows_core::imp::CanInto for IMapView -{ -} -impl - windows_core::imp::CanInto for IMapView -{ -} -impl - windows_core::imp::CanInto>> for IMapView -{ - const QUERY: bool = true; -} -impl - IMapView -{ - pub fn Lookup( - &self, - key: &mut >::Default, - ) -> windows_core::Result - where - P0: windows_core::Param, - { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).Lookup)( - windows_core::Interface::as_raw(this), - key as *mut _ as _, - &mut result__, - ) - .and_then(|| windows_core::Type::from_abi(result__)) - } - } - pub fn get_Size(&self) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).get_Size)( - windows_core::Interface::as_raw(this), - &mut result__, - ) - .map(|| result__) - } - } - pub fn HasKey( - &self, - key: &mut >::Default, - ) -> windows_core::Result - where - P0: windows_core::Param, - { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).HasKey)( - windows_core::Interface::as_raw(this), - key as *mut _ as _, - &mut result__, - ) - .map(|| result__) - } - } - pub fn First(&self) -> windows_core::Result>> { - let this = &windows_core::Interface::cast::>>(self)?; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).First)( - windows_core::Interface::as_raw(this), - &mut result__, - ) - .and_then(|| windows_core::Type::from_abi(result__)) - } - } -} -impl - windows_core::RuntimeType for IMapView -{ - const SIGNATURE: windows_core::imp::ConstBuffer = { - windows_core::imp::ConstBuffer::new() - .push_slice(b"pinterface(") - .push_slice(b"TODO") - .push_slice(b";") - .push_other(K::SIGNATURE) - .push_slice(b";") - .push_other(V::SIGNATURE) - .push_slice(b")") - }; -} -unsafe impl - windows_core::Interface for IMapView -{ - type Vtable = IMapView_Vtbl; - const IID: windows_core::GUID = - windows_core::GUID::from_signature(::SIGNATURE); -} -#[repr(C)] -pub struct IMapView_Vtbl -where - K: windows_core::RuntimeType + 'static, - V: windows_core::RuntimeType + 'static, -{ - pub base__: windows_core::IInspectable_Vtbl, - pub Lookup: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut windows_core::AbiType, - *mut windows_core::AbiType, - ) -> windows_core::HRESULT, - pub get_Size: - unsafe extern "system" fn(*mut core::ffi::c_void, *mut u32) -> windows_core::HRESULT, - pub HasKey: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut windows_core::AbiType, - *mut bool, - ) -> windows_core::HRESULT, - pub K: core::marker::PhantomData, - pub V: core::marker::PhantomData, -} diff --git a/crates/tests/misc/riddle/src/lib.rs b/crates/tests/misc/riddle/src/lib.rs deleted file mode 100644 index 3b95c6e762..0000000000 --- a/crates/tests/misc/riddle/src/lib.rs +++ /dev/null @@ -1,87 +0,0 @@ -mod composition; -mod generic_interfaces; -mod module_attributes; -mod nested_module; -mod nested_struct; -mod params; -mod r#struct; -mod win32_struct; -mod winrt_struct; - -pub fn run_riddle(name: &str, dialect: &str, etc: &[&str]) -> Vec { - let rdl = format!("tests/{name}.rdl"); - let winmd = format!("tests/{name}.winmd"); - let rs = format!("src/{name}.rs"); - - let before = std::fs::read_to_string(&rdl) - .unwrap_or_else(|e| panic!("Failed to read input: {rdl} : {e:?}")); - - // Convert .rdl to .winmd - _ = std::fs::remove_file(&winmd); - let command: Vec = vec![ - "--in".to_owned(), - rdl.to_owned(), - "--out".to_owned(), - winmd.to_owned(), - "--filter".to_owned(), - "Test".to_owned(), - ]; - run_one_bindgen(&command); - - // Convert .winmd back to .rdl - std::fs::remove_file(&rdl).unwrap_or_else(|e| panic!("Failed to delete output: {rdl} : {e:?}")); - let mut command: Vec = vec![ - "--in".to_owned(), - winmd.to_owned(), - "--out".to_owned(), - rdl.to_owned(), - "--filter".to_owned(), - "Test".to_owned(), - "--config".to_owned(), - ]; - command.push(format!("type={dialect}")); - run_one_bindgen(&command); - - // Check that .rdl is unchanged - let after = std::fs::read_to_string(&rdl) - .unwrap_or_else(|e| panic!("Failed to read output: {rdl} : {e:?}")); - assert_eq!(before, after, "no equal {}", rdl); - - // Convert .rdl to .rs - std::fs::remove_file(&rs).unwrap_or_else(|e| panic!("Failed to delete output: {rs} : {e:?}")); - - let mut command: Vec = vec![ - "--in".to_owned(), - rdl.to_owned(), - "--out".to_owned(), - rs.to_owned(), - "--filter".to_owned(), - "Test".to_owned(), - "--config".to_owned(), - "no-bindgen-comment".to_owned(), - ]; - command.extend(etc.iter().map(|&s| s.to_owned())); - run_one_bindgen(&command); - - // Return winmd file for validation - let mut files = helpers::default_metadata(); - let winmd_bytes = - std::fs::read(&winmd).unwrap_or_else(|e| panic!("Failed to read winmd: {winmd} : {e:?}")); - files.push( - windows_metadata::File::new(winmd_bytes) - .unwrap_or_else(|| panic!("failed to parse winmd: {winmd}")), - ); - files -} - -fn run_one_bindgen(args: &[String]) -> String { - match windows_bindgen::bindgen(args) { - Ok(s) => s, - Err(e) => { - panic!( - "Failed to run bindgen: {e:?}\nArgs: riddle.exe {args}", - args = args.join(" ") - ); - } - } -} diff --git a/crates/tests/misc/riddle/src/module_attributes.rs b/crates/tests/misc/riddle/src/module_attributes.rs deleted file mode 100644 index fbd81eea39..0000000000 --- a/crates/tests/misc/riddle/src/module_attributes.rs +++ /dev/null @@ -1,24 +0,0 @@ -#![allow( - non_snake_case, - non_upper_case_globals, - non_camel_case_types, - dead_code, - clippy::all -)] -#[repr(C)] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct Type { - pub field: i32, -} -impl windows_core::TypeKind for Type { - type TypeKind = windows_core::CopyType; -} -impl windows_core::RuntimeType for Type { - const SIGNATURE: windows_core::imp::ConstBuffer = - windows_core::imp::ConstBuffer::from_slice(b"struct(Test.Type;i4)"); -} -impl Default for Type { - fn default() -> Self { - unsafe { core::mem::zeroed() } - } -} diff --git a/crates/tests/misc/riddle/src/nested_module.rs b/crates/tests/misc/riddle/src/nested_module.rs deleted file mode 100644 index 6f13cd3181..0000000000 --- a/crates/tests/misc/riddle/src/nested_module.rs +++ /dev/null @@ -1,43 +0,0 @@ -#![allow( - non_snake_case, - non_upper_case_globals, - non_camel_case_types, - dead_code, - clippy::all -)] -pub mod NestedModule { - #[repr(C)] - #[derive(Clone, Copy, Debug, PartialEq)] - pub struct NestedType { - pub field: f32, - } - impl windows_core::TypeKind for NestedType { - type TypeKind = windows_core::CopyType; - } - impl windows_core::RuntimeType for NestedType { - const SIGNATURE: windows_core::imp::ConstBuffer = - windows_core::imp::ConstBuffer::from_slice(b"struct(Test.NestedModule.NestedType;f4)"); - } - impl Default for NestedType { - fn default() -> Self { - unsafe { core::mem::zeroed() } - } - } -} -#[repr(C)] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct TestType { - pub field: i32, -} -impl windows_core::TypeKind for TestType { - type TypeKind = windows_core::CopyType; -} -impl windows_core::RuntimeType for TestType { - const SIGNATURE: windows_core::imp::ConstBuffer = - windows_core::imp::ConstBuffer::from_slice(b"struct(Test.TestType;i4)"); -} -impl Default for TestType { - fn default() -> Self { - unsafe { core::mem::zeroed() } - } -} diff --git a/crates/tests/misc/riddle/src/nested_struct.rs b/crates/tests/misc/riddle/src/nested_struct.rs deleted file mode 100644 index a6be47ae26..0000000000 --- a/crates/tests/misc/riddle/src/nested_struct.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![allow( - non_snake_case, - non_upper_case_globals, - non_camel_case_types, - dead_code, - clippy::all -)] -#[repr(C)] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct Inner { - pub field_i32: i32, -} -impl windows_core::TypeKind for Inner { - type TypeKind = windows_core::CopyType; -} -impl windows_core::RuntimeType for Inner { - const SIGNATURE: windows_core::imp::ConstBuffer = - windows_core::imp::ConstBuffer::from_slice(b"struct(Test.Inner;i4)"); -} -impl Default for Inner { - fn default() -> Self { - unsafe { core::mem::zeroed() } - } -} -#[repr(C)] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct Outer { - pub field_bool: bool, - pub field_inner: Inner, - pub field_usize: usize, -} -impl windows_core::TypeKind for Outer { - type TypeKind = windows_core::CopyType; -} -impl windows_core::RuntimeType for Outer { - const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::from_slice( - b"struct(Test.Outer;b1;struct(Test.Inner;i4);us)", - ); -} -impl Default for Outer { - fn default() -> Self { - unsafe { core::mem::zeroed() } - } -} diff --git a/crates/tests/misc/riddle/src/params.rs b/crates/tests/misc/riddle/src/params.rs deleted file mode 100644 index 12798fb0ee..0000000000 --- a/crates/tests/misc/riddle/src/params.rs +++ /dev/null @@ -1,284 +0,0 @@ -#![allow( - non_snake_case, - non_upper_case_globals, - non_camel_case_types, - dead_code, - clippy::all -)] -windows_core::imp::define_interface!(IParams, IParams_Vtbl, 0); -impl core::ops::Deref for IParams { - type Target = windows_core::IInspectable; - fn deref(&self) -> &Self::Target { - unsafe { core::mem::transmute(self) } - } -} -windows_core::imp::interface_hierarchy!( - IParams, - windows_core::IUnknown, - windows_core::IInspectable -); -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__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).Bool)( - windows_core::Interface::as_raw(this), - a, - b, - &mut result__, - ) - .map(|| result__) - } - } - pub fn I8(&self, a: &mut i8, b: &mut i8) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).I8)( - windows_core::Interface::as_raw(this), - a, - b, - &mut result__, - ) - .map(|| result__) - } - } - pub fn U8(&self, a: &mut u8, b: &mut u8) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).U8)( - windows_core::Interface::as_raw(this), - a, - b, - &mut result__, - ) - .map(|| result__) - } - } - pub fn I16(&self, a: &mut i16, b: &mut i16) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).I16)( - windows_core::Interface::as_raw(this), - a, - b, - &mut result__, - ) - .map(|| result__) - } - } - pub fn U16(&self, a: &mut u16, b: &mut u16) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).U16)( - windows_core::Interface::as_raw(this), - a, - b, - &mut result__, - ) - .map(|| result__) - } - } - pub fn I32(&self, a: &mut i32, b: &mut i32) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).I32)( - windows_core::Interface::as_raw(this), - a, - b, - &mut result__, - ) - .map(|| result__) - } - } - pub fn U32(&self, a: &mut u32, b: &mut u32) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).U32)( - windows_core::Interface::as_raw(this), - a, - b, - &mut result__, - ) - .map(|| result__) - } - } - pub fn I64(&self, a: &mut i64, b: &mut i64) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).I64)( - windows_core::Interface::as_raw(this), - a, - b, - &mut result__, - ) - .map(|| result__) - } - } - pub fn U64(&self, a: &mut u64, b: &mut u64) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).U64)( - windows_core::Interface::as_raw(this), - a, - b, - &mut result__, - ) - .map(|| result__) - } - } - pub fn F32(&self, a: &mut f32, b: &mut f32) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).F32)( - windows_core::Interface::as_raw(this), - a, - b, - &mut result__, - ) - .map(|| result__) - } - } - pub fn F64(&self, a: &mut f64, b: &mut f64) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).F64)( - windows_core::Interface::as_raw(this), - a, - b, - &mut result__, - ) - .map(|| result__) - } - } - pub fn ISize(&self, a: &mut isize, b: &mut isize) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).ISize)( - windows_core::Interface::as_raw(this), - a, - b, - &mut result__, - ) - .map(|| result__) - } - } - pub fn USize(&self, a: &mut usize, b: &mut usize) -> windows_core::Result { - let this = self; - unsafe { - let mut result__ = core::mem::zeroed(); - (windows_core::Interface::vtable(this).USize)( - windows_core::Interface::as_raw(this), - a, - b, - &mut result__, - ) - .map(|| result__) - } - } -} -impl windows_core::RuntimeType for IParams { - const SIGNATURE: windows_core::imp::ConstBuffer = - windows_core::imp::ConstBuffer::for_interface::(); -} -#[repr(C)] -pub struct IParams_Vtbl { - pub base__: windows_core::IInspectable_Vtbl, - pub Nothing: unsafe extern "system" fn(*mut core::ffi::c_void) -> windows_core::HRESULT, - pub Bool: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut bool, - *mut bool, - *mut bool, - ) -> windows_core::HRESULT, - pub I8: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut i8, - *mut i8, - *mut i8, - ) -> windows_core::HRESULT, - pub U8: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut u8, - *mut u8, - *mut u8, - ) -> windows_core::HRESULT, - pub I16: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut i16, - *mut i16, - *mut i16, - ) -> windows_core::HRESULT, - pub U16: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut u16, - *mut u16, - *mut u16, - ) -> windows_core::HRESULT, - pub I32: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut i32, - *mut i32, - *mut i32, - ) -> windows_core::HRESULT, - pub U32: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut u32, - *mut u32, - *mut u32, - ) -> windows_core::HRESULT, - pub I64: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut i64, - *mut i64, - *mut i64, - ) -> windows_core::HRESULT, - pub U64: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut u64, - *mut u64, - *mut u64, - ) -> windows_core::HRESULT, - pub F32: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut f32, - *mut f32, - *mut f32, - ) -> windows_core::HRESULT, - pub F64: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut f64, - *mut f64, - *mut f64, - ) -> windows_core::HRESULT, - pub ISize: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut isize, - *mut isize, - *mut isize, - ) -> windows_core::HRESULT, - pub USize: unsafe extern "system" fn( - *mut core::ffi::c_void, - *mut usize, - *mut usize, - *mut usize, - ) -> windows_core::HRESULT, -} diff --git a/crates/tests/misc/riddle/src/struct.rs b/crates/tests/misc/riddle/src/struct.rs deleted file mode 100644 index e32d433c16..0000000000 --- a/crates/tests/misc/riddle/src/struct.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![allow( - non_snake_case, - non_upper_case_globals, - non_camel_case_types, - dead_code, - clippy::all -)] -#[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Primitives { - pub field_bool: bool, - pub field_i8: i8, - pub field_u8: u8, - pub field_i16: i16, - pub field_u16: u16, - pub field_i32: i32, - pub field_u32: u32, - pub field_i64: i64, - pub field_u64: u64, - pub field_f32: f32, - pub field_f64: f64, - pub field_isize: isize, - pub field_usize: usize, -} -impl windows_core::TypeKind for Primitives { - type TypeKind = windows_core::CopyType; -} -impl windows_core::RuntimeType for Primitives { - const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::from_slice( - b"struct(Test.Primitives;b1;i1;u1;i2;u2;i4;u4;i8;u8;f4;f8;is;us)", - ); -} -impl Default for Primitives { - fn default() -> Self { - unsafe { core::mem::zeroed() } - } -} diff --git a/crates/tests/misc/riddle/src/win32_struct.rs b/crates/tests/misc/riddle/src/win32_struct.rs deleted file mode 100644 index 41f2146eac..0000000000 --- a/crates/tests/misc/riddle/src/win32_struct.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![allow( - non_snake_case, - non_upper_case_globals, - non_camel_case_types, - dead_code, - clippy::all -)] -#[repr(C)] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct Type { - pub field: i32, -} -impl windows_core::TypeKind for Type { - type TypeKind = windows_core::CopyType; -} -impl Default for Type { - fn default() -> Self { - unsafe { core::mem::zeroed() } - } -} diff --git a/crates/tests/misc/riddle/src/winrt_struct.rs b/crates/tests/misc/riddle/src/winrt_struct.rs deleted file mode 100644 index fbd81eea39..0000000000 --- a/crates/tests/misc/riddle/src/winrt_struct.rs +++ /dev/null @@ -1,24 +0,0 @@ -#![allow( - non_snake_case, - non_upper_case_globals, - non_camel_case_types, - dead_code, - clippy::all -)] -#[repr(C)] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct Type { - pub field: i32, -} -impl windows_core::TypeKind for Type { - type TypeKind = windows_core::CopyType; -} -impl windows_core::RuntimeType for Type { - const SIGNATURE: windows_core::imp::ConstBuffer = - windows_core::imp::ConstBuffer::from_slice(b"struct(Test.Type;i4)"); -} -impl Default for Type { - fn default() -> Self { - unsafe { core::mem::zeroed() } - } -} diff --git a/crates/tests/misc/riddle/tests/composition.rdl b/crates/tests/misc/riddle/tests/composition.rdl deleted file mode 100644 index 8f0e37f87e..0000000000 --- a/crates/tests/misc/riddle/tests/composition.rdl +++ /dev/null @@ -1,24 +0,0 @@ -#![winrt] - -mod Test { - // TODO: maybe sort TypeDefs by kind at when writing out rdl from winmd - class CompositionObject : ICompositionObject; - class Compositor : ICompositor; - interface ICompositionObject { - fn get_Compositor() -> Compositor; - } - interface ICompositor { - fn CreateSpriteVisual() -> SpriteVisual; - } - interface ISpriteVisual { - fn get_Brush() -> bool; - } - interface IVisual { - fn get_IsVisible() -> bool; - } - interface IVisual2 { - fn get_Opacity(value: bool); - } - class SpriteVisual : class Visual, ISpriteVisual; - class Visual : class CompositionObject, IVisual, IVisual2; -} diff --git a/crates/tests/misc/riddle/tests/composition.rs b/crates/tests/misc/riddle/tests/composition.rs deleted file mode 100644 index 61a2566342..0000000000 --- a/crates/tests/misc/riddle/tests/composition.rs +++ /dev/null @@ -1,11 +0,0 @@ -// TODO: this test won't work until we have support for writing attributes -// since we need the DefaultAttribute for classes. - -// use test_riddle::run_riddle; -// use windows_metadata::*; - -// #[test] -// fn test() { -// let files = run_riddle("composition", "winrt", &[]); -// let reader = Reader::new(files); -// } diff --git a/crates/tests/misc/riddle/tests/generic_interfaces.rdl b/crates/tests/misc/riddle/tests/generic_interfaces.rdl deleted file mode 100644 index 16457b1bf7..0000000000 --- a/crates/tests/misc/riddle/tests/generic_interfaces.rdl +++ /dev/null @@ -1,21 +0,0 @@ -#![winrt] - -mod Test { - interface IIterable { - fn First() -> IIterator; - } - interface IIterator { - fn get_Current() -> T; - fn get_HasCurrent() -> bool; - fn MoveNext() -> bool; - } - interface IKeyValuePair { - fn get_Key() -> K; - fn get_Value() -> V; - } - interface IMapView : IIterable> { - fn Lookup(key: K) -> V; - fn get_Size() -> u32; - fn HasKey(key: K) -> bool; - } -} diff --git a/crates/tests/misc/riddle/tests/generic_interfaces.rs b/crates/tests/misc/riddle/tests/generic_interfaces.rs deleted file mode 100644 index 94e09db151..0000000000 --- a/crates/tests/misc/riddle/tests/generic_interfaces.rs +++ /dev/null @@ -1,28 +0,0 @@ -use test_riddle::run_riddle; -use windows_metadata::*; - -#[test] -fn test() { - let files = run_riddle("generic_interfaces", "winrt", &[]); - let reader = Reader::new(files); - - let types: Vec = reader.namespace_items("Test").collect(); - - assert_eq!(types.len(), 4); - - let def = reader.get_type_def("Test", "IIterable").next().unwrap(); - - assert_eq!(def.interface_impls().count(), 0); - let generics: Vec = def.generics().collect(); - assert_eq!(generics.len(), 1); - assert_eq!(generics[0].name(), "T"); - - let def = reader.get_type_def("Test", "IMapView").next().unwrap(); - - let impls: Vec = def.interface_impls().collect(); - assert_eq!(impls.len(), 1); - let generics: Vec = def.generics().collect(); - assert_eq!(generics.len(), 2); - assert_eq!(generics[0].name(), "K"); - assert_eq!(generics[1].name(), "V"); -} diff --git a/crates/tests/misc/riddle/tests/module_attributes.rdl b/crates/tests/misc/riddle/tests/module_attributes.rdl deleted file mode 100644 index cf969519d1..0000000000 --- a/crates/tests/misc/riddle/tests/module_attributes.rdl +++ /dev/null @@ -1,7 +0,0 @@ -#![winrt] - -mod Test { - struct Type { - field: i32, - } -} diff --git a/crates/tests/misc/riddle/tests/module_attributes.rs b/crates/tests/misc/riddle/tests/module_attributes.rs deleted file mode 100644 index 41b7d9ef31..0000000000 --- a/crates/tests/misc/riddle/tests/module_attributes.rs +++ /dev/null @@ -1,8 +0,0 @@ -use test_riddle::run_riddle; -use windows_metadata::*; - -#[test] -fn test() { - let files = run_riddle("module_attributes", "winrt", &[]); - let _reader = Reader::new(files); -} diff --git a/crates/tests/misc/riddle/tests/nested_module.rdl b/crates/tests/misc/riddle/tests/nested_module.rdl deleted file mode 100644 index aaec92fa8b..0000000000 --- a/crates/tests/misc/riddle/tests/nested_module.rdl +++ /dev/null @@ -1,12 +0,0 @@ -#![winrt] - -mod Test { - mod NestedModule { - struct NestedType { - field: f32, - } - } - struct TestType { - field: i32, - } -} diff --git a/crates/tests/misc/riddle/tests/nested_module.rs b/crates/tests/misc/riddle/tests/nested_module.rs deleted file mode 100644 index c95402862b..0000000000 --- a/crates/tests/misc/riddle/tests/nested_module.rs +++ /dev/null @@ -1,36 +0,0 @@ -use test_riddle::run_riddle; -use windows_metadata::*; - -#[test] -fn test() { - let files = run_riddle("nested_module", "winrt", &[]); - let reader = Reader::new(files); - - let types: Vec = reader.namespace_items("Test").collect(); - - assert_eq!(types.len(), 1); - let Item::Type(def) = types[0] else { - panic!("type expected") - }; - - assert_eq!(def.name(), "TestType"); - assert_eq!(def.kind(), TypeKind::Struct); - let fields: Vec = def.fields().collect(); - assert_eq!(fields.len(), 1); - assert_eq!(fields[0].name(), "field"); - assert!(matches!(fields[0].ty(None), Type::I32)); - - let types: Vec = reader.namespace_items("Test.NestedModule").collect(); - - assert_eq!(types.len(), 1); - let Item::Type(def) = types[0] else { - panic!("type expected") - }; - - assert_eq!(def.name(), "NestedType"); - assert_eq!(def.kind(), TypeKind::Struct); - let fields: Vec = def.fields().collect(); - assert_eq!(fields.len(), 1); - assert_eq!(fields[0].name(), "field"); - assert!(matches!(fields[0].ty(None), Type::F32)); -} diff --git a/crates/tests/misc/riddle/tests/nested_struct.rdl b/crates/tests/misc/riddle/tests/nested_struct.rdl deleted file mode 100644 index 2a1df87d4a..0000000000 --- a/crates/tests/misc/riddle/tests/nested_struct.rdl +++ /dev/null @@ -1,12 +0,0 @@ -#![winrt] - -mod Test { - struct Inner { - field_i32: i32, - } - struct Outer { - field_bool: bool, - field_inner: Inner, - field_usize: usize, - } -} diff --git a/crates/tests/misc/riddle/tests/nested_struct.rs b/crates/tests/misc/riddle/tests/nested_struct.rs deleted file mode 100644 index 4e62683a07..0000000000 --- a/crates/tests/misc/riddle/tests/nested_struct.rs +++ /dev/null @@ -1,41 +0,0 @@ -use test_riddle::run_riddle; -use windows_metadata::*; - -#[test] -fn test() { - let files = run_riddle("nested_struct", "winrt", &[]); - let reader = Reader::new(files); - - let def = reader - .get_type_def("Test", "Inner") - .next() - .expect("Type missing"); - - assert_eq!(def.kind(), TypeKind::Struct); - let fields: Vec = def.fields().collect(); - assert_eq!(fields.len(), 1); - assert_eq!(fields[0].name(), "field_i32"); - assert!(matches!(fields[0].ty(None), Type::I32)); - - let def = reader - .get_type_def("Test", "Outer") - .next() - .expect("Type missing"); - - assert_eq!(def.kind(), TypeKind::Struct); - let fields: Vec = def.fields().collect(); - assert_eq!(fields.len(), 3); - assert_eq!(fields[0].name(), "field_bool"); - assert_eq!(fields[1].name(), "field_inner"); - assert_eq!(fields[2].name(), "field_usize"); - assert!(matches!(fields[0].ty(None), Type::Bool)); - assert!(matches!(fields[2].ty(None), Type::USize)); - - let Type::TypeDef(def, generics) = fields[1].ty(None) else { - panic!("wrong type") - }; - - assert_eq!(def.namespace(), "Test"); - assert_eq!(def.name(), "Inner"); - assert!(generics.is_empty()); -} diff --git a/crates/tests/misc/riddle/tests/params.rdl b/crates/tests/misc/riddle/tests/params.rdl deleted file mode 100644 index 4b7d40073d..0000000000 --- a/crates/tests/misc/riddle/tests/params.rdl +++ /dev/null @@ -1,20 +0,0 @@ -#![winrt] - -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; - } -} diff --git a/crates/tests/misc/riddle/tests/params.rs b/crates/tests/misc/riddle/tests/params.rs deleted file mode 100644 index 9f779b04e5..0000000000 --- a/crates/tests/misc/riddle/tests/params.rs +++ /dev/null @@ -1,61 +0,0 @@ -use test_riddle::run_riddle; -use windows_metadata::*; - -#[test] -fn test() { - let files = run_riddle("params", "winrt", &[]); - let reader = Reader::new(files); - - let def = reader - .get_type_def("Test", "IParams") - .next() - .expect("Type missing"); - - assert_eq!(def.kind(), TypeKind::Interface); - let generics = &vec![]; - - assert!(def.fields().next().is_none()); - let methods: Vec = def.methods().collect(); - assert_eq!(methods.len(), 14); - - assert_eq!(methods[0].name(), "Nothing"); - let sig = methods[0].signature(generics); - assert_eq!(sig.return_type, Type::Void); - assert!(sig.params.is_empty()); - - assert_eq!(methods[1].name(), "Bool"); - assert_eq!(methods[2].name(), "I8"); - assert_eq!(methods[3].name(), "U8"); - assert_eq!(methods[4].name(), "I16"); - assert_eq!(methods[5].name(), "U16"); - assert_eq!(methods[6].name(), "I32"); - assert_eq!(methods[7].name(), "U32"); - assert_eq!(methods[8].name(), "I64"); - assert_eq!(methods[9].name(), "U64"); - assert_eq!(methods[10].name(), "F32"); - assert_eq!(methods[11].name(), "F64"); - assert_eq!(methods[12].name(), "ISize"); - assert_eq!(methods[13].name(), "USize"); - - method(generics, methods[1], Type::Bool); - method(generics, methods[2], Type::I8); - method(generics, methods[3], Type::U8); - method(generics, methods[4], Type::I16); - method(generics, methods[5], Type::U16); - method(generics, methods[6], Type::I32); - method(generics, methods[7], Type::U32); - method(generics, methods[8], Type::I64); - method(generics, methods[9], Type::U64); - method(generics, methods[10], Type::F32); - method(generics, methods[11], Type::F64); - method(generics, methods[12], Type::ISize); - method(generics, methods[13], Type::USize); -} - -fn method(generics: &[Type], method: MethodDef, expected: Type) { - let sig = method.signature(generics); - assert_eq!(sig.return_type, expected); - assert_eq!(sig.params.len(), 2); - assert_eq!(sig.params[0], expected); - assert_eq!(sig.params[1], expected); -} diff --git a/crates/tests/misc/riddle/tests/struct.rdl b/crates/tests/misc/riddle/tests/struct.rdl deleted file mode 100644 index 99c3d224ec..0000000000 --- a/crates/tests/misc/riddle/tests/struct.rdl +++ /dev/null @@ -1,19 +0,0 @@ -#![winrt] - -mod Test { - struct Primitives { - field_bool: bool, - field_i8: i8, - field_u8: u8, - field_i16: i16, - field_u16: u16, - field_i32: i32, - field_u32: u32, - field_i64: i64, - field_u64: u64, - field_f32: f32, - field_f64: f64, - field_isize: isize, - field_usize: usize, - } -} diff --git a/crates/tests/misc/riddle/tests/struct.rs b/crates/tests/misc/riddle/tests/struct.rs deleted file mode 100644 index 81918f4f69..0000000000 --- a/crates/tests/misc/riddle/tests/struct.rs +++ /dev/null @@ -1,46 +0,0 @@ -use test_riddle::run_riddle; -use windows_metadata::*; - -#[test] -fn test() { - let files = run_riddle("struct", "winrt", &[]); - let reader = Reader::new(files); - - let def = reader - .get_type_def("Test", "Primitives") - .next() - .expect("Type missing"); - - assert_eq!(def.kind(), TypeKind::Struct); - - let fields: Vec = def.fields().collect(); - assert_eq!(fields.len(), 13); - - assert_eq!(fields[0].name(), "field_bool"); - assert_eq!(fields[1].name(), "field_i8"); - assert_eq!(fields[2].name(), "field_u8"); - assert_eq!(fields[3].name(), "field_i16"); - assert_eq!(fields[4].name(), "field_u16"); - assert_eq!(fields[5].name(), "field_i32"); - assert_eq!(fields[6].name(), "field_u32"); - assert_eq!(fields[7].name(), "field_i64"); - assert_eq!(fields[8].name(), "field_u64"); - assert_eq!(fields[9].name(), "field_f32"); - assert_eq!(fields[10].name(), "field_f64"); - assert_eq!(fields[11].name(), "field_isize"); - assert_eq!(fields[12].name(), "field_usize"); - - assert!(matches!(fields[0].ty(None), Type::Bool)); - assert!(matches!(fields[1].ty(None), Type::I8)); - assert!(matches!(fields[2].ty(None), Type::U8)); - assert!(matches!(fields[3].ty(None), Type::I16)); - assert!(matches!(fields[4].ty(None), Type::U16)); - assert!(matches!(fields[5].ty(None), Type::I32)); - assert!(matches!(fields[6].ty(None), Type::U32)); - assert!(matches!(fields[7].ty(None), Type::I64)); - assert!(matches!(fields[8].ty(None), Type::U64)); - assert!(matches!(fields[9].ty(None), Type::F32)); - assert!(matches!(fields[10].ty(None), Type::F64)); - assert!(matches!(fields[11].ty(None), Type::ISize)); - assert!(matches!(fields[12].ty(None), Type::USize)); -} diff --git a/crates/tests/misc/riddle/tests/win32_struct.rdl b/crates/tests/misc/riddle/tests/win32_struct.rdl deleted file mode 100644 index 9b7c758d07..0000000000 --- a/crates/tests/misc/riddle/tests/win32_struct.rdl +++ /dev/null @@ -1,7 +0,0 @@ -#![win32] - -mod Test { - struct Type { - field: i32, - } -} diff --git a/crates/tests/misc/riddle/tests/win32_struct.rs b/crates/tests/misc/riddle/tests/win32_struct.rs deleted file mode 100644 index 1cd78935f7..0000000000 --- a/crates/tests/misc/riddle/tests/win32_struct.rs +++ /dev/null @@ -1,22 +0,0 @@ -use test_riddle::run_riddle; -use windows_metadata::*; - -#[test] -fn test() { - let files = run_riddle("win32_struct", "win32", &[]); - let reader = Reader::new(files); - - let def = reader - .get_type_def("Test", "Type") - .next() - .expect("Type missing"); - - let flags = def.flags(); - assert!(!flags.contains(TypeAttributes::WindowsRuntime)); - - assert_eq!(def.kind(), TypeKind::Struct); - let fields: Vec = def.fields().collect(); - assert_eq!(fields.len(), 1); - assert_eq!(fields[0].name(), "field"); - assert!(matches!(fields[0].ty(None), Type::I32)); -} diff --git a/crates/tests/misc/riddle/tests/winrt_struct.rdl b/crates/tests/misc/riddle/tests/winrt_struct.rdl deleted file mode 100644 index cf969519d1..0000000000 --- a/crates/tests/misc/riddle/tests/winrt_struct.rdl +++ /dev/null @@ -1,7 +0,0 @@ -#![winrt] - -mod Test { - struct Type { - field: i32, - } -} diff --git a/crates/tests/misc/riddle/tests/winrt_struct.rs b/crates/tests/misc/riddle/tests/winrt_struct.rs deleted file mode 100644 index f72d9926eb..0000000000 --- a/crates/tests/misc/riddle/tests/winrt_struct.rs +++ /dev/null @@ -1,22 +0,0 @@ -use test_riddle::run_riddle; -use windows_metadata::*; - -#[test] -fn test() { - let files = run_riddle("winrt_struct", "winrt", &[]); - let reader = Reader::new(files); - - let def = reader - .get_type_def("Test", "Type") - .next() - .expect("Type missing"); - - let flags = def.flags(); - assert!(flags.contains(TypeAttributes::WindowsRuntime)); - - assert_eq!(def.kind(), TypeKind::Struct); - let fields: Vec = def.fields().collect(); - assert_eq!(fields.len(), 1); - assert_eq!(fields[0].name(), "field"); - assert!(matches!(fields[0].ty(None), Type::I32)); -} diff --git a/crates/tools/riddle/Cargo.toml b/crates/tools/riddle/Cargo.toml deleted file mode 100644 index 31f4bfda36..0000000000 --- a/crates/tools/riddle/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "riddle" -version = "0.58.0" -authors = ["Microsoft"] -edition = "2021" -rust-version = "1.60" -license = "MIT OR Apache-2.0" -description = "Windows metadata compiler" -repository = "https://github.com/microsoft/windows-rs" -readme = "readme.md" - -[dependencies.windows-bindgen] -path = "../../libs/bindgen" -version = "0.58.0" -default-features = false diff --git a/crates/tools/riddle/readme.md b/crates/tools/riddle/readme.md deleted file mode 100644 index 8b14a81479..0000000000 --- a/crates/tools/riddle/readme.md +++ /dev/null @@ -1,28 +0,0 @@ -## Generate Rust bindings for Windows - -The [riddle](https://crates.io/crates/riddle) tool automatically generates Rust bindings from Windows metadata. - -* [Getting started](https://kennykerr.ca/rust-getting-started/) -* [Samples](https://github.com/microsoft/windows-rs/tree/0.58.0/crates/samples) -* [Releases](https://github.com/microsoft/windows-rs/releases) - -Start by installing `riddle`: - -``` -> cargo install riddle -``` - -Generates Rust bindings as needed: - -``` -> riddle -Usage: riddle.exe [options...] - -Options: - --in Path to files and directories containing .winmd and .rdl files - --out Path to .winmd, .rdl, or .rs file to generate - --filter Namespaces to include or !exclude in output - --config Override a configuration value - --format Format .rdl files only - --etc File containing command line options -``` diff --git a/crates/tools/riddle/src/main.rs b/crates/tools/riddle/src/main.rs deleted file mode 100644 index 65185952a0..0000000000 --- a/crates/tools/riddle/src/main.rs +++ /dev/null @@ -1,26 +0,0 @@ -fn main() { - let args: Vec = std::env::args().skip(1).collect(); - - if args.is_empty() { - println!( - r#"Usage: riddle.exe [options...] - -Options: - --in Path to files and directories containing .winmd and .rdl files - --out Path to .winmd, .rdl, or .rs file to generate - --filter Namespaces to include or !exclude in output - --config Override a configuration value - --format Format .rdl files only - --etc File containing command line options -"# - ); - } else { - match windows_bindgen::bindgen(args) { - Ok(ok) => println!("{ok}"), - Err(error) => { - eprintln!("{error}"); - std::process::exit(1); - } - } - } -} diff --git a/crates/tools/standalone/src/main.rs b/crates/tools/standalone/src/main.rs index 1676ea1b80..e9b7524692 100644 --- a/crates/tools/standalone/src/main.rs +++ b/crates/tools/standalone/src/main.rs @@ -204,7 +204,7 @@ fn main() { &["Windows.Win32.System.Com.IPersistFile"], ); - riddle( + bindgen( &src.join("b_prepend.rs"), &["Windows.Foundation.DateTime"], &[ @@ -216,15 +216,15 @@ fn main() { } fn write_sys(output: &Path, filter: &[&str]) { - riddle(output, filter, &["flatten", "sys", "minimal"]); + bindgen(output, filter, &["flatten", "sys", "minimal"]); } fn write_win(output: &Path, filter: &[&str]) { - riddle(output, filter, &["flatten", "minimal"]); + bindgen(output, filter, &["flatten", "minimal"]); } fn write_no_inner_attr(output: &Path, filter: &[&str]) { - riddle( + bindgen( output, filter, &["flatten", "no-inner-attributes", "minimal"], @@ -232,15 +232,15 @@ fn write_no_inner_attr(output: &Path, filter: &[&str]) { } fn write_vtbl(output: &Path, filter: &[&str]) { - riddle(output, filter, &["flatten", "sys", "minimal", "vtbl"]); + bindgen(output, filter, &["flatten", "sys", "minimal", "vtbl"]); } -fn riddle(output: &Path, filter: &[&str], config: &[&str]) { +fn bindgen(output: &Path, filter: &[&str], config: &[&str]) { let output: &str = output.as_os_str().to_str().unwrap(); let mut args = vec!["--out", output, "--filter"]; args.extend_from_slice(filter); args.extend_from_slice(&["--config", "no-bindgen-comment"]); args.extend_from_slice(config); - println!("running: riddle {}", args.join(" ")); + println!("running: bindgen {}", args.join(" ")); windows_bindgen::bindgen(args).unwrap(); } diff --git a/docs/readme.md b/docs/readme.md index 99df78f4dc..72e4bb2591 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -23,4 +23,3 @@ This repo is the home of the following crates (and other supporting crates): * [windows-version](https://crates.io/crates/windows-version) - Windows version information. * [cppwinrt](https://crates.io/crates/cppwinrt) - Bundles the C++/WinRT compiler for use in Rust. -* [riddle](https://crates.io/crates/riddle) - Windows metadata compiler tool.