blob: c21ad78ff0f7b2bd271a89caad16b8812a775304 [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 Tolnay54702b92020-07-31 11:50:09 -070010 pub front: Content,
David Tolnay7ece56f2020-03-29 21:21:38 -070011 content: RefCell<Content>,
12}
13
David Tolnay54702b92020-07-31 11:50:09 -070014pub struct Content {
David Tolnay7ece56f2020-03-29 21:21:38 -070015 bytes: Vec<u8>,
David Tolnay7db73692019-10-20 14:51:12 -040016 section_pending: bool,
David Tolnay9ad1fbc2020-03-01 14:01:24 -080017 blocks_pending: Vec<&'static str>,
David Tolnay7db73692019-10-20 14:51:12 -040018}
19
20impl OutFile {
David Tolnay754e21c2020-03-29 20:58:46 -070021 pub fn new(namespace: Namespace, header: bool) -> Self {
David Tolnay7db73692019-10-20 14:51:12 -040022 OutFile {
23 namespace,
24 header,
David Tolnay9c68b1a2020-03-06 11:12:55 -080025 include: Includes::new(),
David Tolnay54702b92020-07-31 11:50:09 -070026 front: Content::new(),
27 content: RefCell::new(Content::new()),
David Tolnay7db73692019-10-20 14:51:12 -040028 }
29 }
30
31 // Write a blank line if the preceding section had any contents.
32 pub fn next_section(&mut self) {
David Tolnay7ece56f2020-03-29 21:21:38 -070033 let content = self.content.get_mut();
34 content.section_pending = true;
David Tolnay7db73692019-10-20 14:51:12 -040035 }
36
37 pub fn begin_block(&mut self, block: &'static str) {
David Tolnay7ece56f2020-03-29 21:21:38 -070038 let content = self.content.get_mut();
39 content.blocks_pending.push(block);
David Tolnay7db73692019-10-20 14:51:12 -040040 }
41
David Tolnay9ad1fbc2020-03-01 14:01:24 -080042 pub fn end_block(&mut self, block: &'static str) {
David Tolnay7ece56f2020-03-29 21:21:38 -070043 let content = self.content.get_mut();
44 if content.blocks_pending.pop().is_none() {
45 content.bytes.extend_from_slice(b"} // ");
46 content.bytes.extend_from_slice(block.as_bytes());
47 content.bytes.push(b'\n');
48 content.section_pending = true;
David Tolnay7db73692019-10-20 14:51:12 -040049 }
50 }
51
David Tolnay7ece56f2020-03-29 21:21:38 -070052 pub fn write_fmt(&self, args: Arguments) {
53 let content = &mut *self.content.borrow_mut();
54 Write::write_fmt(content, args).unwrap();
55 }
56
57 pub fn content(&self) -> Vec<u8> {
David Tolnay54702b92020-07-31 11:50:09 -070058 let front = &self.front.bytes;
59 let content = &self.content.borrow().bytes;
60 let len = front.len() + !front.is_empty() as usize + content.len();
61 let mut out = Vec::with_capacity(len);
62 out.extend_from_slice(front);
63 if !front.is_empty() {
64 out.push(b'\n');
65 }
66 out.extend_from_slice(content);
67 out
David Tolnay7db73692019-10-20 14:51:12 -040068 }
69}
70
David Tolnay7ece56f2020-03-29 21:21:38 -070071impl Write for Content {
David Tolnay7db73692019-10-20 14:51:12 -040072 fn write_str(&mut self, s: &str) -> fmt::Result {
David Tolnayf4632de2020-07-31 10:46:55 -070073 self.write_bytes(s.as_bytes());
74 Ok(())
75 }
76}
77
78impl Content {
David Tolnay54702b92020-07-31 11:50:09 -070079 pub fn write_fmt(&mut self, args: Arguments) {
80 Write::write_fmt(self, args).unwrap();
81 }
82
83 fn new() -> Self {
84 Content {
85 bytes: Vec::new(),
86 section_pending: false,
87 blocks_pending: Vec::new(),
88 }
89 }
90
David Tolnayf4632de2020-07-31 10:46:55 -070091 fn write_bytes(&mut self, b: &[u8]) {
92 if !b.is_empty() {
David Tolnay9ad1fbc2020-03-01 14:01:24 -080093 if !self.blocks_pending.is_empty() {
David Tolnay7ece56f2020-03-29 21:21:38 -070094 if !self.bytes.is_empty() {
95 self.bytes.push(b'\n');
David Tolnay3577d452020-03-17 21:48:13 -070096 }
David Tolnay9ad1fbc2020-03-01 14:01:24 -080097 for block in self.blocks_pending.drain(..) {
David Tolnay7ece56f2020-03-29 21:21:38 -070098 self.bytes.extend_from_slice(block.as_bytes());
99 self.bytes.extend_from_slice(b" {\n");
David Tolnayb92e66f2020-03-01 13:36:55 -0800100 }
David Tolnay7db73692019-10-20 14:51:12 -0400101 self.section_pending = false;
102 } else if self.section_pending {
David Tolnay7ece56f2020-03-29 21:21:38 -0700103 if !self.bytes.is_empty() {
104 self.bytes.push(b'\n');
David Tolnay3577d452020-03-17 21:48:13 -0700105 }
David Tolnay7db73692019-10-20 14:51:12 -0400106 self.section_pending = false;
107 }
David Tolnayf4632de2020-07-31 10:46:55 -0700108 self.bytes.extend_from_slice(b);
David Tolnay7db73692019-10-20 14:51:12 -0400109 }
David Tolnay7db73692019-10-20 14:51:12 -0400110 }
111}