Lazily compute include set
diff --git a/gen/include.rs b/gen/include.rs
index ef741af..e34d9d0 100644
--- a/gen/include.rs
+++ b/gen/include.rs
@@ -1,3 +1,5 @@
+use std::fmt::{self, Display};
+
pub static HEADER: &str = include_str!("include/cxxbridge.h");
pub fn get(guard: &str) -> &'static str {
@@ -11,3 +13,43 @@
panic!("not found in cxxbridge.h header: {}", guard)
}
}
+
+#[derive(Default)]
+pub struct Includes {
+ custom: Vec<String>,
+ pub cstdint: bool,
+ pub memory: bool,
+ pub string: bool,
+ pub type_traits: bool,
+}
+
+impl Includes {
+ pub fn new() -> Self {
+ Includes::default()
+ }
+
+ pub fn insert(&mut self, include: String) {
+ self.custom.push(include);
+ }
+}
+
+impl Display for Includes {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ for include in &self.custom {
+ writeln!(f, "#include \"{}\"", include.escape_default())?;
+ }
+ if self.cstdint {
+ writeln!(f, "#include <cstdint>")?;
+ }
+ if self.memory {
+ writeln!(f, "#include <memory>")?;
+ }
+ if self.string {
+ writeln!(f, "#include <string>")?;
+ }
+ if self.type_traits {
+ writeln!(f, "#include <type_traits>")?;
+ }
+ Ok(())
+ }
+}
diff --git a/gen/out.rs b/gen/out.rs
index 506ce6c..124816f 100644
--- a/gen/out.rs
+++ b/gen/out.rs
@@ -1,8 +1,10 @@
+use crate::gen::include::Includes;
use std::fmt::{self, Arguments, Write};
pub(crate) struct OutFile {
pub namespace: Vec<String>,
pub header: bool,
+ pub include: Includes,
content: Vec<u8>,
section_pending: bool,
blocks_pending: Vec<&'static str>,
@@ -13,6 +15,7 @@
OutFile {
namespace,
header,
+ include: Includes::new(),
content: Vec::new(),
section_pending: false,
blocks_pending: Vec::new(),
@@ -37,6 +40,10 @@
}
}
+ pub fn prepend(&mut self, section: String) {
+ self.content.splice(..0, section.into_bytes());
+ }
+
pub fn write_fmt(&mut self, args: Arguments) {
Write::write_fmt(self, args).unwrap();
}
diff --git a/gen/write.rs b/gen/write.rs
index 68f0315..24c9c09 100644
--- a/gen/write.rs
+++ b/gen/write.rs
@@ -14,7 +14,7 @@
for api in apis {
if let Api::Include(include) = api {
- writeln!(out, "#include \"{}\"", include.value().escape_default());
+ out.include.insert(include.value());
}
}
@@ -74,41 +74,25 @@
write_generic_instantiations(out, types);
}
+ out.prepend(out.include.to_string());
+
out_file
}
fn write_includes(out: &mut OutFile, types: &Types) {
- let mut has_int = false;
- let mut has_box = false;
- let mut has_unique_ptr = false;
- let mut has_string = false;
-
for ty in types {
match ty {
Type::Ident(ident) => match Atom::from(ident) {
Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
- | Some(I16) | Some(I32) | Some(I64) | Some(Isize) => has_int = true,
- Some(CxxString) => has_string = true,
+ | Some(I16) | Some(I32) | Some(I64) | Some(Isize) => out.include.cstdint = true,
+ Some(CxxString) => out.include.string = true,
Some(Bool) | Some(RustString) | None => {}
},
- Type::RustBox(_) => has_box = true,
- Type::UniquePtr(_) => has_unique_ptr = true,
+ Type::RustBox(_) => out.include.type_traits = true,
+ Type::UniquePtr(_) => out.include.memory = true,
_ => {}
}
}
-
- if has_int {
- writeln!(out, "#include <cstdint>");
- }
- if has_unique_ptr {
- writeln!(out, "#include <memory>");
- }
- if has_string {
- writeln!(out, "#include <string>");
- }
- if has_box {
- writeln!(out, "#include <type_traits>");
- }
}
fn write_include_cxxbridge(out: &mut OutFile, types: &Types) {