blob: f07a0d3c638482ad000574ba188b4c515c84204c [file] [log] [blame]
David Tolnay9c68b1a2020-03-06 11:12:55 -08001use crate::gen::include::Includes;
David Tolnay08419302020-04-19 20:38:20 -07002use crate::syntax::namespace::Namespace;
David Tolnay7ece56f2020-03-29 21:21:38 -07003use std::cell::RefCell;
David Tolnay7db73692019-10-20 14:51:12 -04004use std::fmt::{self, Arguments, Write};
5
6pub(crate) struct OutFile {
David Tolnay754e21c2020-03-29 20:58:46 -07007 pub namespace: Namespace,
David Tolnay7db73692019-10-20 14:51:12 -04008 pub header: bool,
David Tolnay9c68b1a2020-03-06 11:12:55 -08009 pub include: Includes,
David Tolnay7ece56f2020-03-29 21:21:38 -070010 content: RefCell<Content>,
11}
12
13struct Content {
14 bytes: Vec<u8>,
David Tolnay7db73692019-10-20 14:51:12 -040015 section_pending: bool,
David Tolnay9ad1fbc2020-03-01 14:01:24 -080016 blocks_pending: Vec<&'static str>,
David Tolnay7db73692019-10-20 14:51:12 -040017}
18
19impl OutFile {
David Tolnay754e21c2020-03-29 20:58:46 -070020 pub fn new(namespace: Namespace, header: bool) -> Self {
David Tolnay7db73692019-10-20 14:51:12 -040021 OutFile {
22 namespace,
23 header,
David Tolnay9c68b1a2020-03-06 11:12:55 -080024 include: Includes::new(),
David Tolnay7ece56f2020-03-29 21:21:38 -070025 content: RefCell::new(Content {
26 bytes: Vec::new(),
27 section_pending: false,
28 blocks_pending: Vec::new(),
29 }),
David Tolnay7db73692019-10-20 14:51:12 -040030 }
31 }
32
33 // Write a blank line if the preceding section had any contents.
34 pub fn next_section(&mut self) {
David Tolnay7ece56f2020-03-29 21:21:38 -070035 let content = self.content.get_mut();
36 content.section_pending = true;
David Tolnay7db73692019-10-20 14:51:12 -040037 }
38
39 pub fn begin_block(&mut self, block: &'static str) {
David Tolnay7ece56f2020-03-29 21:21:38 -070040 let content = self.content.get_mut();
41 content.blocks_pending.push(block);
David Tolnay7db73692019-10-20 14:51:12 -040042 }
43
David Tolnay9ad1fbc2020-03-01 14:01:24 -080044 pub fn end_block(&mut self, block: &'static str) {
David Tolnay7ece56f2020-03-29 21:21:38 -070045 let content = self.content.get_mut();
46 if content.blocks_pending.pop().is_none() {
47 content.bytes.extend_from_slice(b"} // ");
48 content.bytes.extend_from_slice(block.as_bytes());
49 content.bytes.push(b'\n');
50 content.section_pending = true;
David Tolnay7db73692019-10-20 14:51:12 -040051 }
52 }
53
David Tolnay7ece56f2020-03-29 21:21:38 -070054 pub fn write_fmt(&self, args: Arguments) {
55 let content = &mut *self.content.borrow_mut();
56 Write::write_fmt(content, args).unwrap();
57 }
58
David Tolnayf4632de2020-07-31 10:46:55 -070059 pub fn extend(&self, other: &Self) {
60 self.content.borrow_mut().write_bytes(&other.content.borrow().bytes);
61 }
62
David Tolnay7ece56f2020-03-29 21:21:38 -070063 pub fn content(&self) -> Vec<u8> {
64 self.content.borrow().bytes.clone()
David Tolnay7db73692019-10-20 14:51:12 -040065 }
66}
67
David Tolnay7ece56f2020-03-29 21:21:38 -070068impl Write for Content {
David Tolnay7db73692019-10-20 14:51:12 -040069 fn write_str(&mut self, s: &str) -> fmt::Result {
David Tolnayf4632de2020-07-31 10:46:55 -070070 self.write_bytes(s.as_bytes());
71 Ok(())
72 }
73}
74
75impl Content {
76 fn write_bytes(&mut self, b: &[u8]) {
77 if !b.is_empty() {
David Tolnay9ad1fbc2020-03-01 14:01:24 -080078 if !self.blocks_pending.is_empty() {
David Tolnay7ece56f2020-03-29 21:21:38 -070079 if !self.bytes.is_empty() {
80 self.bytes.push(b'\n');
David Tolnay3577d452020-03-17 21:48:13 -070081 }
David Tolnay9ad1fbc2020-03-01 14:01:24 -080082 for block in self.blocks_pending.drain(..) {
David Tolnay7ece56f2020-03-29 21:21:38 -070083 self.bytes.extend_from_slice(block.as_bytes());
84 self.bytes.extend_from_slice(b" {\n");
David Tolnayb92e66f2020-03-01 13:36:55 -080085 }
David Tolnay7db73692019-10-20 14:51:12 -040086 self.section_pending = false;
87 } else if self.section_pending {
David Tolnay7ece56f2020-03-29 21:21:38 -070088 if !self.bytes.is_empty() {
89 self.bytes.push(b'\n');
David Tolnay3577d452020-03-17 21:48:13 -070090 }
David Tolnay7db73692019-10-20 14:51:12 -040091 self.section_pending = false;
92 }
David Tolnayf4632de2020-07-31 10:46:55 -070093 self.bytes.extend_from_slice(b);
David Tolnay7db73692019-10-20 14:51:12 -040094 }
David Tolnay7db73692019-10-20 14:51:12 -040095 }
96}