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