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