2020-03-06 19:12:55 +00:00
|
|
|
use crate::gen::include::Includes;
|
2020-04-20 03:38:20 +00:00
|
|
|
use crate::syntax::namespace::Namespace;
|
2020-03-30 04:21:38 +00:00
|
|
|
use std::cell::RefCell;
|
2019-10-20 18:51:12 +00:00
|
|
|
use std::fmt::{self, Arguments, Write};
|
|
|
|
|
|
|
|
pub(crate) struct OutFile {
|
2020-03-30 03:58:46 +00:00
|
|
|
pub namespace: Namespace,
|
2019-10-20 18:51:12 +00:00
|
|
|
pub header: bool,
|
2020-03-06 19:12:55 +00:00
|
|
|
pub include: Includes,
|
2020-03-30 04:21:38 +00:00
|
|
|
content: RefCell<Content>,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Content {
|
|
|
|
bytes: Vec<u8>,
|
2019-10-20 18:51:12 +00:00
|
|
|
section_pending: bool,
|
2020-03-01 22:01:24 +00:00
|
|
|
blocks_pending: Vec<&'static str>,
|
2019-10-20 18:51:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl OutFile {
|
2020-03-30 03:58:46 +00:00
|
|
|
pub fn new(namespace: Namespace, header: bool) -> Self {
|
2019-10-20 18:51:12 +00:00
|
|
|
OutFile {
|
|
|
|
namespace,
|
|
|
|
header,
|
2020-03-06 19:12:55 +00:00
|
|
|
include: Includes::new(),
|
2020-03-30 04:21:38 +00:00
|
|
|
content: RefCell::new(Content {
|
|
|
|
bytes: Vec::new(),
|
|
|
|
section_pending: false,
|
|
|
|
blocks_pending: Vec::new(),
|
|
|
|
}),
|
2019-10-20 18:51:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write a blank line if the preceding section had any contents.
|
|
|
|
pub fn next_section(&mut self) {
|
2020-03-30 04:21:38 +00:00
|
|
|
let content = self.content.get_mut();
|
|
|
|
content.section_pending = true;
|
2019-10-20 18:51:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn begin_block(&mut self, block: &'static str) {
|
2020-03-30 04:21:38 +00:00
|
|
|
let content = self.content.get_mut();
|
|
|
|
content.blocks_pending.push(block);
|
2019-10-20 18:51:12 +00:00
|
|
|
}
|
|
|
|
|
2020-03-01 22:01:24 +00:00
|
|
|
pub fn end_block(&mut self, block: &'static str) {
|
2020-03-30 04:21:38 +00:00
|
|
|
let content = self.content.get_mut();
|
|
|
|
if content.blocks_pending.pop().is_none() {
|
|
|
|
content.bytes.extend_from_slice(b"} // ");
|
|
|
|
content.bytes.extend_from_slice(block.as_bytes());
|
|
|
|
content.bytes.push(b'\n');
|
|
|
|
content.section_pending = true;
|
2019-10-20 18:51:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-06 19:12:55 +00:00
|
|
|
pub fn prepend(&mut self, section: String) {
|
2020-03-30 04:21:38 +00:00
|
|
|
let content = self.content.get_mut();
|
|
|
|
content.bytes.splice(..0, section.into_bytes());
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn write_fmt(&self, args: Arguments) {
|
|
|
|
let content = &mut *self.content.borrow_mut();
|
|
|
|
Write::write_fmt(content, args).unwrap();
|
2020-03-06 19:12:55 +00:00
|
|
|
}
|
|
|
|
|
2020-03-30 04:21:38 +00:00
|
|
|
pub fn content(&self) -> Vec<u8> {
|
|
|
|
self.content.borrow().bytes.clone()
|
2019-10-20 18:51:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-30 04:21:38 +00:00
|
|
|
impl Write for Content {
|
2019-10-20 18:51:12 +00:00
|
|
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
|
|
|
if !s.is_empty() {
|
2020-03-01 22:01:24 +00:00
|
|
|
if !self.blocks_pending.is_empty() {
|
2020-03-30 04:21:38 +00:00
|
|
|
if !self.bytes.is_empty() {
|
|
|
|
self.bytes.push(b'\n');
|
2020-03-18 04:48:13 +00:00
|
|
|
}
|
2020-03-01 22:01:24 +00:00
|
|
|
for block in self.blocks_pending.drain(..) {
|
2020-03-30 04:21:38 +00:00
|
|
|
self.bytes.extend_from_slice(block.as_bytes());
|
|
|
|
self.bytes.extend_from_slice(b" {\n");
|
2020-03-01 21:36:55 +00:00
|
|
|
}
|
2019-10-20 18:51:12 +00:00
|
|
|
self.section_pending = false;
|
|
|
|
} else if self.section_pending {
|
2020-03-30 04:21:38 +00:00
|
|
|
if !self.bytes.is_empty() {
|
|
|
|
self.bytes.push(b'\n');
|
2020-03-18 04:48:13 +00:00
|
|
|
}
|
2019-10-20 18:51:12 +00:00
|
|
|
self.section_pending = false;
|
|
|
|
}
|
2020-03-30 04:21:38 +00:00
|
|
|
self.bytes.extend_from_slice(s.as_bytes());
|
2019-10-20 18:51:12 +00:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|