Safe FFI between Rust and C++
diff --git a/gen/out.rs b/gen/out.rs
new file mode 100644
index 0000000..d6735be
--- /dev/null
+++ b/gen/out.rs
@@ -0,0 +1,74 @@
+use std::fmt::{self, Arguments, Write};
+
+pub(crate) struct OutFile {
+ pub namespace: Vec<String>,
+ pub header: bool,
+ content: Vec<u8>,
+ section_pending: bool,
+ block: &'static str,
+ block_pending: bool,
+}
+
+impl OutFile {
+ pub fn new(namespace: Vec<String>, header: bool) -> Self {
+ OutFile {
+ namespace,
+ header,
+ content: Vec::new(),
+ section_pending: false,
+ block: "",
+ block_pending: false,
+ }
+ }
+
+ // Write a blank line if the preceding section had any contents.
+ pub fn next_section(&mut self) {
+ self.section_pending = true;
+ }
+
+ pub fn begin_block(&mut self, block: &'static str) {
+ self.block = block;
+ self.block_pending = true;
+ }
+
+ pub fn end_block(&mut self) {
+ if self.block_pending {
+ self.block_pending = false;
+ } else {
+ self.content.extend_from_slice(b"} // ");
+ self.content.extend_from_slice(self.block.as_bytes());
+ self.content.push(b'\n');
+ self.block = "";
+ self.section_pending = true;
+ }
+ }
+
+ pub fn write_fmt(&mut self, args: Arguments) {
+ Write::write_fmt(self, args).unwrap();
+ }
+}
+
+impl Write for OutFile {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ if !s.is_empty() {
+ if self.block_pending {
+ self.content.push(b'\n');
+ self.content.extend_from_slice(self.block.as_bytes());
+ self.content.extend_from_slice(b" {\n");
+ self.block_pending = false;
+ self.section_pending = false;
+ } else if self.section_pending {
+ self.content.push(b'\n');
+ self.section_pending = false;
+ }
+ self.content.extend_from_slice(s.as_bytes());
+ }
+ Ok(())
+ }
+}
+
+impl AsRef<[u8]> for OutFile {
+ fn as_ref(&self) -> &[u8] {
+ &self.content
+ }
+}