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(#[automatically_derived]
impl<'a> ::core::default::Default for Content<'a> {
#[inline]
fn default() -> Content<'a> {
Content {
bytes: ::core::default::Default::default(),
namespace: ::core::default::Default::default(),
blocks: ::core::default::Default::default(),
suppress_next_section: ::core::default::Default::default(),
section_pending: ::core::default::Default::default(),
blocks_pending: ::core::default::Default::default(),
}
}
}Default)]
22pub(crate) struct Content<'a> {
23 bytes: String,
24 namespace: &'a Namespace,
25 blocks: Vec<BlockBoundary<'a>>,
26 suppress_next_section: bool,
27 section_pending: bool,
28 blocks_pending: usize,
29}
30
31#[derive(#[automatically_derived]
impl<'a> ::core::marker::Copy for BlockBoundary<'a> { }Copy, #[automatically_derived]
impl<'a> ::core::clone::Clone for BlockBoundary<'a> {
#[inline]
fn clone(&self) -> BlockBoundary<'a> {
let _: ::core::clone::AssertParamIsClone<Block<'a>>;
let _: ::core::clone::AssertParamIsClone<Block<'a>>;
*self
}
}Clone, #[automatically_derived]
impl<'a> ::core::cmp::PartialEq for BlockBoundary<'a> {
#[inline]
fn eq(&self, other: &BlockBoundary<'a>) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(BlockBoundary::Begin(__self_0),
BlockBoundary::Begin(__arg1_0)) => __self_0 == __arg1_0,
(BlockBoundary::End(__self_0), BlockBoundary::End(__arg1_0))
=> __self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]
impl<'a> ::core::fmt::Debug for BlockBoundary<'a> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
BlockBoundary::Begin(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Begin",
&__self_0),
BlockBoundary::End(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "End",
&__self_0),
}
}
}Debug)]
32enum BlockBoundary<'a> {
33 Begin(Block<'a>),
34 End(Block<'a>),
35}
36
37impl<'a> OutFile<'a> {
38 pub(crate) fn new(header: bool, opt: &'a Opt, types: &'a Types) -> Self {
39 OutFile {
40 header,
41 opt,
42 types,
43 include: Includes::new(),
44 pragma: Pragma::new(),
45 builtin: Builtins::new(),
46 content: RefCell::new(Content::new()),
47 }
48 }
49
50 pub(crate) fn next_section(&mut self) {
52 self.content.get_mut().next_section();
53 }
54
55 pub(crate) fn suppress_next_section(&mut self) {
56 self.content.get_mut().suppress_next_section();
57 }
58
59 pub(crate) fn begin_block(&mut self, block: Block<'a>) {
60 self.content.get_mut().begin_block(block);
61 }
62
63 pub(crate) fn end_block(&mut self, block: Block<'a>) {
64 self.content.get_mut().end_block(block);
65 }
66
67 pub(crate) fn set_namespace(&mut self, namespace: &'a Namespace) {
68 self.content.get_mut().set_namespace(namespace);
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 = !self.suppress_next_section;
133 }
134
135 pub(crate) fn suppress_next_section(&mut self) {
136 self.suppress_next_section = true;
137 }
138
139 pub(crate) fn begin_block(&mut self, block: Block<'a>) {
140 self.push_block_boundary(BlockBoundary::Begin(block));
141 }
142
143 pub(crate) fn end_block(&mut self, block: Block<'a>) {
144 self.push_block_boundary(BlockBoundary::End(block));
145 }
146
147 pub(crate) fn set_namespace(&mut self, namespace: &'a Namespace) {
148 for name in self.namespace.iter().rev() {
149 self.end_block(Block::UserDefinedNamespace(name));
150 }
151 for name in namespace {
152 self.begin_block(Block::UserDefinedNamespace(name));
153 }
154 self.namespace = namespace;
155 }
156
157 pub(crate) fn write_fmt(&mut self, args: Arguments) {
158 Write::write_fmt(self, args).unwrap();
159 }
160
161 fn write(&mut self, b: &str) {
162 if !b.is_empty() {
163 if self.blocks_pending > 0 {
164 self.flush_blocks();
165 }
166 if self.section_pending && !self.bytes.is_empty() {
167 self.bytes.push('\n');
168 }
169 self.bytes.push_str(b);
170 self.suppress_next_section = false;
171 self.section_pending = false;
172 self.blocks_pending = 0;
173 }
174 }
175
176 fn push_block_boundary(&mut self, boundary: BlockBoundary<'a>) {
177 if self.blocks_pending > 0 && boundary == self.blocks.last().unwrap().rev() {
178 self.blocks.pop();
179 self.blocks_pending -= 1;
180 } else {
181 self.blocks.push(boundary);
182 self.blocks_pending += 1;
183 }
184 }
185
186 fn flush(&mut self) {
187 self.set_namespace(Default::default());
188 if self.blocks_pending > 0 {
189 self.flush_blocks();
190 }
191 }
192
193 fn flush_blocks(&mut self) {
194 self.section_pending = !self.bytes.is_empty();
195 let mut read = self.blocks.len() - self.blocks_pending;
196 let mut write = read;
197
198 while read < self.blocks.len() {
199 match self.blocks[read] {
200 BlockBoundary::Begin(begin_block) => {
201 if self.section_pending {
202 self.bytes.push('\n');
203 self.section_pending = false;
204 }
205 Block::write_begin(begin_block, &mut self.bytes);
206 self.blocks[write] = BlockBoundary::Begin(begin_block);
207 write += 1;
208 }
209 BlockBoundary::End(end_block) => {
210 write = write.checked_sub(1).unwrap();
211 let begin_block = self.blocks[write];
212 match (&begin_block, &BlockBoundary::Begin(end_block)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(begin_block, BlockBoundary::Begin(end_block));
213 Block::write_end(end_block, &mut self.bytes);
214 self.section_pending = true;
215 }
216 }
217 read += 1;
218 }
219
220 self.blocks.truncate(write);
221 }
222}
223
224impl<'a> BlockBoundary<'a> {
225 fn rev(self) -> BlockBoundary<'a> {
226 match self {
227 BlockBoundary::Begin(block) => BlockBoundary::End(block),
228 BlockBoundary::End(block) => BlockBoundary::Begin(block),
229 }
230 }
231}
232
233pub(crate) trait InfallibleWrite {
234 fn write_fmt(&mut self, args: Arguments);
235}
236
237impl InfallibleWrite for String {
238 fn write_fmt(&mut self, args: Arguments) {
239 Write::write_fmt(self, args).unwrap();
240 }
241}
242
243impl<'a> InfallibleWrite for Content<'a> {
244 fn write_fmt(&mut self, args: Arguments) {
245 Write::write_fmt(self, args).unwrap();
246 }
247}
248
249impl<'a> InfallibleWrite for OutFile<'a> {
250 fn write_fmt(&mut self, args: Arguments) {
251 InfallibleWrite::write_fmt(self.content.get_mut(), args);
252 }
253}