1 use crate::gen::block::Block;
2 use crate::gen::builtin::Builtins;
3 use crate::gen::include::Includes;
4 use crate::gen::Opt;
5 use crate::syntax::namespace::Namespace;
6 use crate::syntax::Types;
7 use std::cell::RefCell;
8 use std::fmt::{self, Arguments, Write};
9 
10 pub(crate) struct OutFile<'a> {
11     pub header: bool,
12     pub opt: &'a Opt,
13     pub types: &'a Types<'a>,
14     pub include: Includes<'a>,
15     pub builtin: Builtins<'a>,
16     content: RefCell<Content<'a>>,
17 }
18 
19 #[derive(Default)]
20 pub struct Content<'a> {
21     bytes: String,
22     namespace: &'a Namespace,
23     blocks: Vec<BlockBoundary<'a>>,
24     section_pending: bool,
25     blocks_pending: usize,
26 }
27 
28 #[derive(Copy, Clone, PartialEq, Debug)]
29 enum BlockBoundary<'a> {
30     Begin(Block<'a>),
31     End(Block<'a>),
32 }
33 
34 impl<'a> OutFile<'a> {
new(header: bool, opt: &'a Opt, types: &'a Types) -> Self35     pub fn new(header: bool, opt: &'a Opt, types: &'a Types) -> Self {
36         OutFile {
37             header,
38             opt,
39             types,
40             include: Includes::new(),
41             builtin: Builtins::new(),
42             content: RefCell::new(Content::new()),
43         }
44     }
45 
46     // Write a blank line if the preceding section had any contents.
next_section(&mut self)47     pub fn next_section(&mut self) {
48         self.content.get_mut().next_section();
49     }
50 
begin_block(&mut self, block: Block<'a>)51     pub fn begin_block(&mut self, block: Block<'a>) {
52         self.content.get_mut().begin_block(block);
53     }
54 
end_block(&mut self, block: Block<'a>)55     pub fn end_block(&mut self, block: Block<'a>) {
56         self.content.get_mut().end_block(block);
57     }
58 
set_namespace(&mut self, namespace: &'a Namespace)59     pub fn set_namespace(&mut self, namespace: &'a Namespace) {
60         self.content.get_mut().set_namespace(namespace);
61     }
62 
write_fmt(&self, args: Arguments)63     pub fn write_fmt(&self, args: Arguments) {
64         let content = &mut *self.content.borrow_mut();
65         Write::write_fmt(content, args).unwrap();
66     }
67 
content(&mut self) -> Vec<u8>68     pub fn content(&mut self) -> Vec<u8> {
69         self.flush();
70         let include = &self.include.content.bytes;
71         let builtin = &self.builtin.content.bytes;
72         let content = &self.content.get_mut().bytes;
73         let len = include.len() + builtin.len() + content.len() + 2;
74         let mut out = String::with_capacity(len);
75         out.push_str(include);
76         if !out.is_empty() && !builtin.is_empty() {
77             out.push('\n');
78         }
79         out.push_str(builtin);
80         if !out.is_empty() && !content.is_empty() {
81             out.push('\n');
82         }
83         out.push_str(content);
84         if out.is_empty() {
85             out.push_str("// empty\n");
86         }
87         out.into_bytes()
88     }
89 
flush(&mut self)90     fn flush(&mut self) {
91         self.include.content.flush();
92         self.builtin.content.flush();
93         self.content.get_mut().flush();
94     }
95 }
96 
97 impl<'a> Write for Content<'a> {
write_str(&mut self, s: &str) -> fmt::Result98     fn write_str(&mut self, s: &str) -> fmt::Result {
99         self.write(s);
100         Ok(())
101     }
102 }
103 
104 impl<'a> PartialEq for Content<'a> {
eq(&self, _other: &Self) -> bool105     fn eq(&self, _other: &Self) -> bool {
106         true
107     }
108 }
109 
110 impl<'a> Content<'a> {
new() -> Self111     fn new() -> Self {
112         Content::default()
113     }
114 
next_section(&mut self)115     pub fn next_section(&mut self) {
116         self.section_pending = true;
117     }
118 
begin_block(&mut self, block: Block<'a>)119     pub fn begin_block(&mut self, block: Block<'a>) {
120         self.push_block_boundary(BlockBoundary::Begin(block));
121     }
122 
end_block(&mut self, block: Block<'a>)123     pub fn end_block(&mut self, block: Block<'a>) {
124         self.push_block_boundary(BlockBoundary::End(block));
125     }
126 
set_namespace(&mut self, namespace: &'a Namespace)127     pub fn set_namespace(&mut self, namespace: &'a Namespace) {
128         for name in self.namespace.iter().rev() {
129             self.end_block(Block::UserDefinedNamespace(name));
130         }
131         for name in namespace {
132             self.begin_block(Block::UserDefinedNamespace(name));
133         }
134         self.namespace = namespace;
135     }
136 
write_fmt(&mut self, args: Arguments)137     pub fn write_fmt(&mut self, args: Arguments) {
138         Write::write_fmt(self, args).unwrap();
139     }
140 
write(&mut self, b: &str)141     fn write(&mut self, b: &str) {
142         if !b.is_empty() {
143             if self.blocks_pending > 0 {
144                 self.flush_blocks();
145             }
146             if self.section_pending && !self.bytes.is_empty() {
147                 self.bytes.push('\n');
148             }
149             self.bytes.push_str(b);
150             self.section_pending = false;
151             self.blocks_pending = 0;
152         }
153     }
154 
push_block_boundary(&mut self, boundary: BlockBoundary<'a>)155     fn push_block_boundary(&mut self, boundary: BlockBoundary<'a>) {
156         if self.blocks_pending > 0 && boundary == self.blocks.last().unwrap().rev() {
157             self.blocks.pop();
158             self.blocks_pending -= 1;
159         } else {
160             self.blocks.push(boundary);
161             self.blocks_pending += 1;
162         }
163     }
164 
flush(&mut self)165     fn flush(&mut self) {
166         self.set_namespace(Default::default());
167         if self.blocks_pending > 0 {
168             self.flush_blocks();
169         }
170     }
171 
flush_blocks(&mut self)172     fn flush_blocks(&mut self) {
173         self.section_pending = !self.bytes.is_empty();
174         let mut read = self.blocks.len() - self.blocks_pending;
175         let mut write = read;
176 
177         while read < self.blocks.len() {
178             match self.blocks[read] {
179                 BlockBoundary::Begin(begin_block) => {
180                     if self.section_pending {
181                         self.bytes.push('\n');
182                         self.section_pending = false;
183                     }
184                     Block::write_begin(begin_block, &mut self.bytes);
185                     self.blocks[write] = BlockBoundary::Begin(begin_block);
186                     write += 1;
187                 }
188                 BlockBoundary::End(end_block) => {
189                     write = write.checked_sub(1).unwrap();
190                     let begin_block = self.blocks[write];
191                     assert_eq!(begin_block, BlockBoundary::Begin(end_block));
192                     Block::write_end(end_block, &mut self.bytes);
193                     self.section_pending = true;
194                 }
195             }
196             read += 1;
197         }
198 
199         self.blocks.truncate(write);
200     }
201 }
202 
203 impl<'a> BlockBoundary<'a> {
rev(self) -> BlockBoundary<'a>204     fn rev(self) -> BlockBoundary<'a> {
205         match self {
206             BlockBoundary::Begin(block) => BlockBoundary::End(block),
207             BlockBoundary::End(block) => BlockBoundary::Begin(block),
208         }
209     }
210 }
211