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