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