• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![allow(
2     clippy::cast_sign_loss,
3     clippy::cognitive_complexity,
4     clippy::default_trait_access,
5     clippy::enum_glob_use,
6     clippy::if_same_then_else,
7     clippy::inherent_to_string,
8     clippy::items_after_statements,
9     clippy::large_enum_variant,
10     clippy::match_bool,
11     clippy::match_on_vec_items,
12     clippy::match_same_arms,
13     clippy::module_name_repetitions,
14     clippy::needless_pass_by_value,
15     clippy::new_without_default,
16     clippy::nonminimal_bool,
17     clippy::option_if_let_else,
18     clippy::or_fun_call,
19     clippy::redundant_else,
20     clippy::shadow_unrelated,
21     clippy::similar_names,
22     clippy::single_match_else,
23     clippy::struct_excessive_bools,
24     clippy::too_many_arguments,
25     clippy::too_many_lines,
26     clippy::toplevel_ref_arg,
27     // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6983
28     clippy::wrong_self_convention
29 )]
30 
31 mod app;
32 mod gen;
33 mod output;
34 mod syntax;
35 
36 use crate::gen::error::{report, Result};
37 use crate::gen::fs;
38 use crate::gen::include::{self, Include};
39 use crate::output::Output;
40 use std::io::{self, Write};
41 use std::path::PathBuf;
42 use std::process;
43 
44 #[derive(Debug)]
45 struct Opt {
46     input: Option<PathBuf>,
47     header: bool,
48     cxx_impl_annotations: Option<String>,
49     include: Vec<Include>,
50     outputs: Vec<Output>,
51 }
52 
main()53 fn main() {
54     if let Err(err) = try_main() {
55         let _ = writeln!(io::stderr(), "cxxbridge: {}", report(err));
56         process::exit(1);
57     }
58 }
59 
60 enum Kind {
61     GeneratedHeader,
62     GeneratedImplementation,
63     Header,
64 }
65 
try_main() -> Result<()>66 fn try_main() -> Result<()> {
67     let opt = app::from_args();
68 
69     let mut outputs = Vec::new();
70     let mut gen_header = false;
71     let mut gen_implementation = false;
72     for output in opt.outputs {
73         let kind = if opt.input.is_none() {
74             Kind::Header
75         } else if opt.header
76             || output.ends_with(".h")
77             || output.ends_with(".hh")
78             || output.ends_with(".hpp")
79         {
80             gen_header = true;
81             Kind::GeneratedHeader
82         } else {
83             gen_implementation = true;
84             Kind::GeneratedImplementation
85         };
86         outputs.push((output, kind));
87     }
88 
89     let gen = gen::Opt {
90         include: opt.include,
91         cxx_impl_annotations: opt.cxx_impl_annotations,
92         gen_header,
93         gen_implementation,
94         ..Default::default()
95     };
96 
97     let generated_code = if let Some(input) = opt.input {
98         gen::generate_from_path(&input, &gen)
99     } else {
100         Default::default()
101     };
102 
103     for (output, kind) in outputs {
104         let content = match kind {
105             Kind::GeneratedHeader => &generated_code.header,
106             Kind::GeneratedImplementation => &generated_code.implementation,
107             Kind::Header => include::HEADER.as_bytes(),
108         };
109         match output {
110             Output::Stdout => drop(io::stdout().write_all(content)),
111             Output::File(path) => fs::write(path, content)?,
112         }
113     }
114 
115     Ok(())
116 }
117