blob: 8a6bd8610878a003207c12bd8771e987dbe35514 [file] [log] [blame]
David Tolnay9c68b1a2020-03-06 11:12:55 -08001use crate::gen::include::Includes;
David Tolnay7ece56f2020-03-29 21:21:38 -07002use std::cell::RefCell;
David Tolnay7db73692019-10-20 14:51:12 -04003use std::fmt::{self, Arguments, Write};
4
5pub(crate) struct OutFile {
David Tolnay7db73692019-10-20 14:51:12 -04006 pub header: bool,
David Tolnay9c68b1a2020-03-06 11:12:55 -08007 pub include: Includes,
David Tolnay54702b92020-07-31 11:50:09 -07008 pub front: Content,
David Tolnay7ece56f2020-03-29 21:21:38 -07009 content: RefCell<Content>,
10}
11
David Tolnay54702b92020-07-31 11:50:09 -070012pub struct Content {
David Tolnaydab7e802020-08-28 18:54:48 -070013 bytes: String,
David Tolnay7db73692019-10-20 14:51:12 -040014 section_pending: bool,
David Tolnay9ad1fbc2020-03-01 14:01:24 -080015 blocks_pending: Vec<&'static str>,
David Tolnay7db73692019-10-20 14:51:12 -040016}
17
18impl OutFile {
Adrian Taylorc8713432020-10-21 18:20:55 -070019 pub fn new(header: bool) -> Self {
David Tolnay7db73692019-10-20 14:51:12 -040020 OutFile {
David Tolnay7db73692019-10-20 14:51:12 -040021 header,
David Tolnay9c68b1a2020-03-06 11:12:55 -080022 include: Includes::new(),
David Tolnay54702b92020-07-31 11:50:09 -070023 front: Content::new(),
24 content: RefCell::new(Content::new()),
David Tolnay7db73692019-10-20 14:51:12 -040025 }
26 }
27
28 // Write a blank line if the preceding section had any contents.
29 pub fn next_section(&mut self) {
David Tolnay7ece56f2020-03-29 21:21:38 -070030 let content = self.content.get_mut();
31 content.section_pending = true;
David Tolnay7db73692019-10-20 14:51:12 -040032 }
33
34 pub fn begin_block(&mut self, block: &'static str) {
David Tolnay7ece56f2020-03-29 21:21:38 -070035 let content = self.content.get_mut();
36 content.blocks_pending.push(block);
David Tolnay7db73692019-10-20 14:51:12 -040037 }
38
David Tolnay9ad1fbc2020-03-01 14:01:24 -080039 pub fn end_block(&mut self, block: &'static str) {
David Tolnay7ece56f2020-03-29 21:21:38 -070040 let content = self.content.get_mut();
41 if content.blocks_pending.pop().is_none() {
David Tolnaydab7e802020-08-28 18:54:48 -070042 content.bytes.push_str("} // ");
43 content.bytes.push_str(block);
44 content.bytes.push('\n');
David Tolnay7ece56f2020-03-29 21:21:38 -070045 content.section_pending = true;
David Tolnay7db73692019-10-20 14:51:12 -040046 }
47 }
48
David Tolnay7ece56f2020-03-29 21:21:38 -070049 pub fn write_fmt(&self, args: Arguments) {
50 let content = &mut *self.content.borrow_mut();
51 Write::write_fmt(content, args).unwrap();
52 }
53
54 pub fn content(&self) -> Vec<u8> {
David Tolnay54702b92020-07-31 11:50:09 -070055 let front = &self.front.bytes;
56 let content = &self.content.borrow().bytes;
David Tolnay91489ec2020-09-03 12:48:46 -070057 let len = front.len() + content.len() + 1;
David Tolnaydab7e802020-08-28 18:54:48 -070058 let mut out = String::with_capacity(len);
59 out.push_str(front);
David Tolnay91489ec2020-09-03 12:48:46 -070060 if !front.is_empty() && !content.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -070061 out.push('\n');
David Tolnay54702b92020-07-31 11:50:09 -070062 }
David Tolnaydab7e802020-08-28 18:54:48 -070063 out.push_str(content);
David Tolnay91489ec2020-09-03 12:48:46 -070064 if out.is_empty() {
65 out.push_str("// empty\n");
66 }
David Tolnaydab7e802020-08-28 18:54:48 -070067 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}