blob: dbb1d7396da7fc39542181d6c8bba8db278312ac [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 Tolnaydab7e802020-08-28 18:54:48 -070015 bytes: String,
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() {
David Tolnaydab7e802020-08-28 18:54:48 -070045 content.bytes.push_str("} // ");
46 content.bytes.push_str(block);
47 content.bytes.push('\n');
David Tolnay7ece56f2020-03-29 21:21:38 -070048 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();
David Tolnaydab7e802020-08-28 18:54:48 -070061 let mut out = String::with_capacity(len);
62 out.push_str(front);
David Tolnay54702b92020-07-31 11:50:09 -070063 if !front.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -070064 out.push('\n');
David Tolnay54702b92020-07-31 11:50:09 -070065 }
David Tolnaydab7e802020-08-28 18:54:48 -070066 out.push_str(content);
67 out.into_bytes()
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 Tolnaydab7e802020-08-28 18:54:48 -070073 self.write(s);
David Tolnayf4632de2020-07-31 10:46:55 -070074 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 {
David Tolnaydab7e802020-08-28 18:54:48 -070085 bytes: String::new(),
David Tolnay54702b92020-07-31 11:50:09 -070086 section_pending: false,
87 blocks_pending: Vec::new(),
88 }
89 }
90
David Tolnaydab7e802020-08-28 18:54:48 -070091 fn write(&mut self, b: &str) {
David Tolnayf4632de2020-07-31 10:46:55 -070092 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() {
David Tolnaydab7e802020-08-28 18:54:48 -070095 self.bytes.push('\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 Tolnaydab7e802020-08-28 18:54:48 -070098 self.bytes.push_str(block);
99 self.bytes.push_str(" {\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() {
David Tolnaydab7e802020-08-28 18:54:48 -0700104 self.bytes.push('\n');
David Tolnay3577d452020-03-17 21:48:13 -0700105 }
David Tolnay7db73692019-10-20 14:51:12 -0400106 self.section_pending = false;
107 }
David Tolnaydab7e802020-08-28 18:54:48 -0700108 self.bytes.push_str(b);
David Tolnay7db73692019-10-20 14:51:12 -0400109 }
David Tolnay7db73692019-10-20 14:51:12 -0400110 }
111}