| 1 | mod cfg; |
| 2 | mod cpp_handle; |
| 3 | mod format; |
| 4 | mod names; |
| 5 | mod value; |
| 6 | |
| 7 | use super::*; |
| 8 | use rayon::prelude::*; |
| 9 | |
| 10 | #[derive (Clone)] |
| 11 | pub struct Writer { |
| 12 | pub config: &'static Config, |
| 13 | pub namespace: &'static str, |
| 14 | } |
| 15 | |
| 16 | impl Writer { |
| 17 | fn with_namespace(&self, namespace: &'static str) -> Self { |
| 18 | let mut clone = self.clone(); |
| 19 | clone.namespace = namespace; |
| 20 | clone |
| 21 | } |
| 22 | |
| 23 | #[track_caller ] |
| 24 | pub fn write(&self, tree: TypeTree) { |
| 25 | if self.config.package { |
| 26 | self.write_package(&tree); |
| 27 | } else { |
| 28 | self.write_file(tree); |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | #[track_caller ] |
| 33 | fn write_file(&self, tree: TypeTree) { |
| 34 | let tokens = if self.config.flat { |
| 35 | self.write_flat(tree) |
| 36 | } else { |
| 37 | self.write_modules(&tree) |
| 38 | }; |
| 39 | |
| 40 | write_to_file(&self.config.output, self.format(&tokens.into_string())); |
| 41 | } |
| 42 | |
| 43 | fn write_flat(&self, tree: TypeTree) -> TokenStream { |
| 44 | let mut tokens = TokenStream::new(); |
| 45 | |
| 46 | for ty in tree.flatten_types() { |
| 47 | tokens.combine(ty.write(self)); |
| 48 | } |
| 49 | |
| 50 | tokens |
| 51 | } |
| 52 | |
| 53 | fn write_modules(&self, tree: &TypeTree) -> TokenStream { |
| 54 | let mut tokens = TokenStream::new(); |
| 55 | |
| 56 | for ty in &tree.types { |
| 57 | tokens.combine(ty.write(self)); |
| 58 | } |
| 59 | |
| 60 | for (name, tree) in &tree.nested { |
| 61 | let name = to_ident(name); |
| 62 | let nested = self.with_namespace(tree.namespace).write_modules(tree); |
| 63 | tokens.combine(quote! { pub mod #name { #nested } }); |
| 64 | } |
| 65 | |
| 66 | tokens |
| 67 | } |
| 68 | |
| 69 | fn write_package(&self, tree: &TypeTree) { |
| 70 | for name in tree.nested.keys() { |
| 71 | _ = std::fs::remove_dir_all(format!(" {}/src/ {name}" , &self.config.output)); |
| 72 | } |
| 73 | |
| 74 | let trees = tree.flatten_trees(); |
| 75 | |
| 76 | trees.par_iter().for_each(|tree| { |
| 77 | let directory = format!( |
| 78 | " {}/src/ {}" , |
| 79 | &self.config.output, |
| 80 | tree.namespace.replace('.' , "/" ) |
| 81 | ); |
| 82 | |
| 83 | let mut tokens = TokenStream::new(); |
| 84 | |
| 85 | for (name, tree) in &tree.nested { |
| 86 | let name = to_ident(name); |
| 87 | let feature = tree.feature(); |
| 88 | |
| 89 | tokens.combine(quote! { |
| 90 | #[cfg(feature = #feature)] |
| 91 | pub mod #name; |
| 92 | }); |
| 93 | } |
| 94 | |
| 95 | let writer = self.with_namespace(tree.namespace); |
| 96 | |
| 97 | for ty in &tree.types { |
| 98 | tokens.combine(ty.write(&writer)); |
| 99 | } |
| 100 | |
| 101 | let output = format!(" {directory}/mod.rs" ); |
| 102 | write_to_file(&output, self.format(&tokens.into_string())); |
| 103 | }); |
| 104 | |
| 105 | if self.config.no_toml { |
| 106 | return; |
| 107 | } |
| 108 | |
| 109 | let toml_path = format!(" {}/Cargo.toml" , &self.config.output); |
| 110 | let mut toml = String::new(); |
| 111 | |
| 112 | for line in read_file_lines(&toml_path) { |
| 113 | toml.push_str(&line); |
| 114 | toml.push(' \n' ); |
| 115 | |
| 116 | if line == "# generated features" { |
| 117 | break; |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | for tree in trees.iter().skip(1) { |
| 122 | let feature = tree.feature(); |
| 123 | |
| 124 | if let Some(pos) = feature.rfind('_' ) { |
| 125 | let dependency = &feature[..pos]; |
| 126 | |
| 127 | toml.push_str(&format!(" {feature} = [ \"{dependency}\"] \n" )); |
| 128 | } else if namespace_starts_with(tree.namespace, "Windows.Win32" ) |
| 129 | || namespace_starts_with(tree.namespace, "Windows.Wdk" ) |
| 130 | { |
| 131 | toml.push_str(&format!(" {feature} = [ \"Win32_Foundation \"] \n" )); |
| 132 | } else if tree.namespace != "Windows.Foundation" { |
| 133 | toml.push_str(&format!(" {feature} = [ \"Foundation \"] \n" )); |
| 134 | } else { |
| 135 | toml.push_str(&format!(" {feature} = [] \n" )); |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | write_to_file(&toml_path, toml); |
| 140 | } |
| 141 | } |
| 142 | |