You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

195 lines
7.3 KiB

  1. /*
  2. * meli -
  3. *
  4. * Copyright Manos Pitsidianakis
  5. *
  6. * This file is part of meli.
  7. *
  8. * meli is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * meli is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with meli. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. use std::fs::File;
  22. use std::io::prelude::*;
  23. use std::process::{Command, Stdio};
  24. use quote::{format_ident, quote};
  25. // Write ConfigStructOverride to overrides.rs
  26. pub fn override_derive(filenames: &[(&str, &str)]) {
  27. let mut output_file =
  28. File::create("src/conf/overrides.rs").expect("Unable to open output file");
  29. let mut output_string = r##"/*
  30. * meli - conf/overrides.rs
  31. *
  32. * Copyright 2020 Manos Pitsidianakis
  33. *
  34. * This file is part of meli.
  35. *
  36. * meli is free software: you can redistribute it and/or modify
  37. * it under the terms of the GNU General Public License as published by
  38. * the Free Software Foundation, either version 3 of the License, or
  39. * (at your option) any later version.
  40. *
  41. * meli is distributed in the hope that it will be useful,
  42. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  43. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  44. * GNU General Public License for more details.
  45. *
  46. * You should have received a copy of the GNU General Public License
  47. * along with meli. If not, see <http://www.gnu.org/licenses/>.
  48. */
  49. //! This module is automatically generated by build.rs.
  50. use super::*;
  51. "##
  52. .to_string();
  53. 'file_loop: for (filename, ident) in filenames {
  54. println!("cargo:rerun-if-changed={}", filename);
  55. let mut file = File::open(&filename).expect(&format!("Unable to open file `{}`", filename));
  56. let mut src = String::new();
  57. file.read_to_string(&mut src).expect("Unable to read file");
  58. let syntax = syn::parse_file(&src).expect("Unable to parse file");
  59. if syntax.items.iter().any(|item| {
  60. if let syn::Item::Struct(s) = item {
  61. if s.ident.to_string().ends_with("Override") {
  62. println!("ident {} exists, skipping {}", ident, filename);
  63. return true;
  64. }
  65. }
  66. false
  67. }) {
  68. continue 'file_loop;
  69. }
  70. for item in syntax.items.iter() {
  71. if let syn::Item::Struct(s) = item {
  72. if s.ident != ident {
  73. continue;
  74. }
  75. if s.ident.to_string().ends_with("Override") {
  76. unreachable!();
  77. }
  78. let override_ident: syn::Ident = format_ident!("{}Override", s.ident);
  79. let mut field_tokentrees = vec![];
  80. let mut field_idents = vec![];
  81. for f in &s.fields {
  82. let ident = &f.ident;
  83. let ty = &f.ty;
  84. let attrs = f
  85. .attrs
  86. .iter()
  87. .filter_map(|f| {
  88. let mut new_attr = f.clone();
  89. if let quote::__private::TokenTree::Group(g) =
  90. f.tokens.clone().into_iter().next().unwrap()
  91. {
  92. let attr_inner_value = f.tokens.to_string();
  93. if !attr_inner_value.starts_with("( default")
  94. && !attr_inner_value.starts_with("( default =")
  95. {
  96. return Some(new_attr);
  97. }
  98. if attr_inner_value.starts_with("( default =") {
  99. let rest = g.stream().into_iter().skip(4);
  100. new_attr.tokens = quote! { ( #(#rest)*) };
  101. if new_attr.tokens.to_string().as_str() == "( )" {
  102. return None;
  103. }
  104. } else if attr_inner_value.starts_with("( default") {
  105. let rest = g.stream().into_iter().skip(2);
  106. new_attr.tokens = quote! { ( #(#rest)*) };
  107. if new_attr.tokens.to_string().as_str() == "( )" {
  108. return None;
  109. }
  110. }
  111. }
  112. Some(new_attr)
  113. })
  114. .collect::<Vec<_>>();
  115. let t = quote! {
  116. #(#attrs)*
  117. #[serde(default)]
  118. pub #ident : Option<#ty>
  119. };
  120. field_idents.push(ident);
  121. field_tokentrees.push(t);
  122. }
  123. //let fields = &s.fields;
  124. let literal_struct = quote! {
  125. #[derive(Debug, Serialize, Deserialize, Clone)]
  126. pub struct #override_ident {
  127. #(#field_tokentrees),*
  128. }
  129. impl Default for #override_ident {
  130. fn default() -> Self {
  131. #override_ident {
  132. #(#field_idents: None),*
  133. }
  134. }
  135. }
  136. };
  137. output_string.extend(literal_struct.to_string().chars());
  138. output_string.push_str("\n\n");
  139. }
  140. }
  141. }
  142. let rustfmt_closure = move |output_file: &mut File, output_string: &str| {
  143. let mut rustfmt = Command::new("rustfmt")
  144. .stdin(Stdio::piped())
  145. .stdout(Stdio::piped())
  146. .stderr(Stdio::piped())
  147. .spawn()
  148. .map_err(|err| format!("failed to execute rustfmt {}", err))?;
  149. {
  150. // limited borrow of stdin
  151. let stdin = rustfmt
  152. .stdin
  153. .as_mut()
  154. .ok_or("failed to get rustfmt stdin")?;
  155. stdin
  156. .write_all(output_string.as_bytes())
  157. .map_err(|err| format!("failed to write to rustfmt stdin {}", err))?;
  158. }
  159. let output = rustfmt
  160. .wait_with_output()
  161. .map_err(|err| format!("failed to wait on rustfmt child {}", err))?;
  162. if !output.stderr.is_empty() {
  163. return Err(format!(
  164. "rustfmt invocation replied with: `{}`",
  165. String::from_utf8_lossy(&output.stderr)
  166. ));
  167. }
  168. output_file
  169. .write_all(&output.stdout)
  170. .expect("failed to write to src/conf/overrides.rs");
  171. Ok(())
  172. };
  173. if let Err(err) = rustfmt_closure(&mut output_file, &output_string) {
  174. println!("Tried rustfmt on overrides module, got error: {}", err);
  175. output_file.write_all(output_string.as_bytes()).unwrap();
  176. }
  177. }