diff options
Diffstat (limited to 'vendor/windows-bindgen/src/lib.rs')
-rw-r--r-- | vendor/windows-bindgen/src/lib.rs | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/vendor/windows-bindgen/src/lib.rs b/vendor/windows-bindgen/src/lib.rs new file mode 100644 index 000000000..0957a4f64 --- /dev/null +++ b/vendor/windows-bindgen/src/lib.rs @@ -0,0 +1,225 @@ +/*! +Learn more about Rust for Windows here: <https://github.com/microsoft/windows-rs> +*/ + +mod classes; +mod com_methods; +mod constants; +mod delegates; +mod enums; +mod extensions; +mod functions; +mod gen; +mod handles; +mod implements; +mod interfaces; +mod iterators; +mod method_names; +mod standalone; +mod structs; +mod try_format; +mod winrt_methods; + +use metadata::reader::*; +use method_names::*; +pub use standalone::*; +use std::collections::*; +use std::fmt::Write; +use tokens::*; +use try_format::*; + +#[doc(hidden)] +pub use gen::*; + +#[doc(hidden)] +pub fn namespace(gen: &Gen, tree: &Tree) -> String { + let mut tokens = TokenStream::new(); + + if tree.namespace == "Windows" || !tree.namespace.starts_with("Windows.") { + tokens.combine(&allow()); + } + + for (name, tree) in &tree.nested { + let name = to_ident(name); + let namespace = tree.namespace[tree.namespace.find('.').unwrap() + 1..].replace('.', "_"); + if !gen.component { + tokens.combine("e! { #[cfg(feature = #namespace)] }); + } + tokens.combine("e! { pub mod #name; }); + } + + let mut functions = BTreeMap::<&str, TokenStream>::new(); + let mut types = BTreeMap::<TypeKind, BTreeMap<&str, TokenStream>>::new(); + + for method in gen.reader.namespace_functions(tree.namespace) { + let name = gen.reader.method_def_name(method); + functions + .entry(name) + .or_default() + .combine(&functions::gen(gen, method)); + } + + for field in gen.reader.namespace_constants(tree.namespace) { + let name = gen.reader.field_name(field); + types + .entry(TypeKind::Class) + .or_default() + .entry(name) + .or_default() + .combine(&constants::gen(gen, field)); + } + + for def in gen + .reader + .namespace_types(tree.namespace, &Default::default()) + { + let type_name = gen.reader.type_def_type_name(def); + if REMAP_TYPES.iter().any(|(x, _)| x == &type_name) { + continue; + } + if CORE_TYPES.iter().any(|(x, _)| x == &type_name) { + continue; + } + let name = type_name.name; + let kind = gen.reader.type_def_kind(def); + match kind { + TypeKind::Class => { + if gen + .reader + .type_def_flags(def) + .contains(TypeAttributes::WINRT) + { + types + .entry(kind) + .or_default() + .insert(name, classes::gen(gen, def)); + } + } + TypeKind::Interface => types + .entry(kind) + .or_default() + .entry(name) + .or_default() + .combine(&interfaces::gen(gen, def)), + TypeKind::Enum => types + .entry(kind) + .or_default() + .entry(name) + .or_default() + .combine(&enums::gen(gen, def)), + TypeKind::Struct => { + if gen.reader.type_def_fields(def).next().is_none() { + if let Some(guid) = gen.reader.type_def_guid(def) { + let ident = to_ident(name); + let value = gen.guid(&guid); + let guid = gen.type_name(&Type::GUID); + let cfg = gen.reader.type_def_cfg(def, &[]); + let doc = gen.cfg_doc(&cfg); + let constant = quote! { + #doc + pub const #ident: #guid = #value; + }; + types + .entry(TypeKind::Class) + .or_default() + .entry(name) + .or_default() + .combine(&constant); + continue; + } + } + types + .entry(kind) + .or_default() + .entry(name) + .or_default() + .combine(&structs::gen(gen, def)); + } + TypeKind::Delegate => types + .entry(kind) + .or_default() + .entry(name) + .or_default() + .combine(&delegates::gen(gen, def)), + } + } + + for function in functions.values() { + tokens.combine(function); + } + + for ty in types.values().flat_map(|v| v.values()) { + tokens.combine(ty); + } + + tokens.combine(&extensions::gen_mod(gen, tree.namespace)); + try_format(tokens.into_string()) +} + +#[doc(hidden)] +pub fn namespace_impl(gen: &Gen, tree: &Tree) -> String { + let mut types = BTreeMap::<&str, TokenStream>::new(); + + for def in gen + .reader + .namespace_types(tree.namespace, &Default::default()) + { + let type_name = gen.reader.type_def_type_name(def); + if CORE_TYPES.iter().any(|(x, _)| x == &type_name) { + continue; + } + if gen.reader.type_def_kind(def) != TypeKind::Interface { + continue; + } + let tokens = implements::gen(gen, def); + + if !tokens.is_empty() { + types.insert(type_name.name, tokens); + } + } + + let types = types.values(); + + let mut tokens = quote! { + #(#types)* + }; + + tokens.combine(&extensions::gen_impl(tree.namespace)); + try_format(tokens.into_string()) +} + +/// Generates bindings for a specific component namespace. +pub fn component(namespace: &str, files: &[File]) -> String { + let reader = &Reader::new(files); + let tree = reader.tree(namespace, &Default::default()); + let mut gen = Gen::new(reader); + gen.namespace = tree.namespace; + gen.component = true; + let mut bindings = crate::namespace(&gen, &tree); + bindings.push_str(&namespace_impl(&gen, &tree)); + try_format(bindings) +} + +fn allow() -> TokenStream { + quote! { + #![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] + } +} + +/// Expand a possibly empty generics list with a new generic +fn expand_generics(generics: TokenStream, new: TokenStream) -> TokenStream { + if generics.is_empty() { + quote!(#new) + } else { + quote!(#generics, #new) + } +} + +/// Expand a possibly emppty where clause with a new generic constraint +fn expand_where_clause(where_clause: TokenStream, generic: TokenStream) -> TokenStream { + if where_clause.is_empty() { + quote!(where #generic) + } else { + quote!(#where_clause #generic) + } +} |