1use crate::gen::block::Block;
2use crate::gen::builtin::Builtins;
3use crate::gen::include::Includes;
4use crate::gen::Opt;
5use crate::syntax::namespace::Namespace;
6use crate::syntax::Types;
7use std::cell::RefCell;
8use std::fmt::{self, Arguments, Write};
9
10pub(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)]
20pub(crate) 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)]
29enum BlockBoundary<'a> {
30 Begin(Block<'a>),
31 End(Block<'a>),
32}
33
34impl<'a> OutFile<'a> {
35 pub(crate) 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 pub(crate) fn next_section(&mut self) {
48 self.content.get_mut().next_section();
49 }
50
51 pub(crate) fn begin_block(&mut self, block: Block<'a>) {
52 self.content.get_mut().begin_block(block);
53 }
54
55 pub(crate) fn end_block(&mut self, block: Block<'a>) {
56 self.content.get_mut().end_block(block);
57 }
58
59 pub(crate) fn set_namespace(&mut self, namespace: &'a Namespace) {
60 self.content.get_mut().set_namespace(namespace);
61 }
62
63 pub(crate) fn write_fmt(&self, args: Arguments) {
64 let content = &mut *self.content.borrow_mut();
65 Write::write_fmt(content, args).unwrap();
66 }
67
68 pub(crate) 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
90 fn flush(&mut self) {
91 self.include.content.flush();
92 self.builtin.content.flush();
93 self.content.get_mut().flush();
94 }
95}
96
97impl<'a> Write for Content<'a> {
98 fn write_str(&mut self, s: &str) -> fmt::Result {
99 self.write(s);
100 Ok(())
101 }
102}
103
104impl<'a> PartialEq for Content<'a> {
105 fn eq(&self, _other: &Self) -> bool {
106 true
107 }
108}
109
110impl<'a> Content<'a> {
111 fn new() -> Self {
112 Content::default()
113 }
114
115 pub(crate) fn next_section(&mut self) {
116 self.section_pending = true;
117 }
118
119 pub(crate) fn begin_block(&mut self, block: Block<'a>) {
120 self.push_block_boundary(BlockBoundary::Begin(block));
121 }
122
123 pub(crate) fn end_block(&mut self, block: Block<'a>) {
124 self.push_block_boundary(BlockBoundary::End(block));
125 }
126
127 pub(crate) 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
137 pub(crate) fn write_fmt(&mut self, args: Arguments) {
138 Write::write_fmt(self, args).unwrap();
139 }
140
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
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
165 fn flush(&mut self) {
166 self.set_namespace(Default::default());
167 if self.blocks_pending > 0 {
168 self.flush_blocks();
169 }
170 }
171
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
203impl<'a> 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}