blob: d42ea7475350b93b1b5b51e598abe45cb43ea4b3 [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;
David Tolnay91489ec2020-09-03 12:48:46 -070060 let len = front.len() + content.len() + 1;
David Tolnaydab7e802020-08-28 18:54:48 -070061 let mut out = String::with_capacity(len);
62 out.push_str(front);
David Tolnay91489ec2020-09-03 12:48:46 -070063 if !front.is_empty() && !content.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);
David Tolnay91489ec2020-09-03 12:48:46 -070067 if out.is_empty() {
68 out.push_str("// empty\n");
69 }
David Tolnaydab7e802020-08-28 18:54:48 -070070 out.into_bytes()
David Tolnay7db73692019-10-20 14:51:12 -040071 }
72}
73
David Tolnay7ece56f2020-03-29 21:21:38 -070074impl Write for Content {
David Tolnay7db73692019-10-20 14:51:12 -040075 fn write_str(&mut self, s: &str) -> fmt::Result {
David Tolnaydab7e802020-08-28 18:54:48 -070076 self.write(s);
David Tolnayf4632de2020-07-31 10:46:55 -070077 Ok(())
78 }
79}
80
81impl Content {
David Tolnay54702b92020-07-31 11:50:09 -070082 pub fn write_fmt(&mut self, args: Arguments) {
83 Write::write_fmt(self, args).unwrap();
84 }
85
86 fn new() -> Self {
87 Content {
David Tolnaydab7e802020-08-28 18:54:48 -070088 bytes: String::new(),
David Tolnay54702b92020-07-31 11:50:09 -070089 section_pending: false,
90 blocks_pending: Vec::new(),
91 }
92 }
93
David Tolnaydab7e802020-08-28 18:54:48 -070094 fn write(&mut self, b: &str) {
David Tolnayf4632de2020-07-31 10:46:55 -070095 if !b.is_empty() {
David Tolnay9ad1fbc2020-03-01 14:01:24 -080096 if !self.blocks_pending.is_empty() {
David Tolnay7ece56f2020-03-29 21:21:38 -070097 if !self.bytes.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -070098 self.bytes.push('\n');
David Tolnay3577d452020-03-17 21:48:13 -070099 }
David Tolnay9ad1fbc2020-03-01 14:01:24 -0800100 for block in self.blocks_pending.drain(..) {
David Tolnaydab7e802020-08-28 18:54:48 -0700101 self.bytes.push_str(block);
102 self.bytes.push_str(" {\n");
David Tolnayb92e66f2020-03-01 13:36:55 -0800103 }
David Tolnay7db73692019-10-20 14:51:12 -0400104 self.section_pending = false;
105 } else if self.section_pending {
David Tolnay7ece56f2020-03-29 21:21:38 -0700106 if !self.bytes.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -0700107 self.bytes.push('\n');
David Tolnay3577d452020-03-17 21:48:13 -0700108 }
David Tolnay7db73692019-10-20 14:51:12 -0400109 self.section_pending = false;
110 }
David Tolnaydab7e802020-08-28 18:54:48 -0700111 self.bytes.push_str(b);
David Tolnay7db73692019-10-20 14:51:12 -0400112 }
David Tolnay7db73692019-10-20 14:51:12 -0400113 }
114}