blob: 6d475fc7ef315926e06396a35ee65c35be8b4745 [file] [log] [blame]
David Tolnay3be0e1f2020-10-31 20:53:00 -07001use crate::gen::builtin::Builtins;
David Tolnay9c68b1a2020-03-06 11:12:55 -08002use crate::gen::include::Includes;
David Tolnayb560a0f2020-10-30 21:28:45 -07003use crate::syntax::Types;
David Tolnay7ece56f2020-03-29 21:21:38 -07004use std::cell::RefCell;
David Tolnay7db73692019-10-20 14:51:12 -04005use std::fmt::{self, Arguments, Write};
6
David Tolnayb560a0f2020-10-30 21:28:45 -07007pub(crate) struct OutFile<'a> {
David Tolnay7db73692019-10-20 14:51:12 -04008 pub header: bool,
David Tolnayb560a0f2020-10-30 21:28:45 -07009 pub types: &'a Types<'a>,
David Tolnay9c68b1a2020-03-06 11:12:55 -080010 pub include: Includes,
David Tolnay3be0e1f2020-10-31 20:53:00 -070011 pub builtin: Builtins,
David Tolnay7ece56f2020-03-29 21:21:38 -070012 content: RefCell<Content>,
13}
14
David Tolnay8810a542020-10-31 21:39:22 -070015#[derive(Default)]
David Tolnay54702b92020-07-31 11:50:09 -070016pub struct Content {
David Tolnaydab7e802020-08-28 18:54:48 -070017 bytes: String,
David Tolnay7db73692019-10-20 14:51:12 -040018 section_pending: bool,
David Tolnay9ad1fbc2020-03-01 14:01:24 -080019 blocks_pending: Vec<&'static str>,
David Tolnay7db73692019-10-20 14:51:12 -040020}
21
David Tolnayb560a0f2020-10-30 21:28:45 -070022impl<'a> OutFile<'a> {
23 pub fn new(header: bool, types: &'a Types) -> Self {
David Tolnay7db73692019-10-20 14:51:12 -040024 OutFile {
David Tolnay7db73692019-10-20 14:51:12 -040025 header,
David Tolnayb560a0f2020-10-30 21:28:45 -070026 types,
David Tolnay9c68b1a2020-03-06 11:12:55 -080027 include: Includes::new(),
David Tolnay3be0e1f2020-10-31 20:53:00 -070028 builtin: Builtins::new(),
David Tolnay54702b92020-07-31 11:50:09 -070029 content: RefCell::new(Content::new()),
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 Tolnaycb2189f2020-10-31 21:23:08 -070035 self.content.get_mut().next_section();
David Tolnay7db73692019-10-20 14:51:12 -040036 }
37
38 pub fn begin_block(&mut self, block: &'static str) {
David Tolnaycb2189f2020-10-31 21:23:08 -070039 self.content.get_mut().begin_block(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 Tolnaycb2189f2020-10-31 21:23:08 -070043 self.content.get_mut().end_block(block);
David Tolnay7db73692019-10-20 14:51:12 -040044 }
45
David Tolnay7ece56f2020-03-29 21:21:38 -070046 pub fn write_fmt(&self, args: Arguments) {
47 let content = &mut *self.content.borrow_mut();
48 Write::write_fmt(content, args).unwrap();
49 }
50
51 pub fn content(&self) -> Vec<u8> {
David Tolnay8810a542020-10-31 21:39:22 -070052 let include = &self.include.content.bytes;
David Tolnay54702b92020-07-31 11:50:09 -070053 let content = &self.content.borrow().bytes;
David Tolnay8810a542020-10-31 21:39:22 -070054 let len = include.len() + content.len() + 1;
David Tolnaydab7e802020-08-28 18:54:48 -070055 let mut out = String::with_capacity(len);
David Tolnay8810a542020-10-31 21:39:22 -070056 out.push_str(include);
57 if !include.is_empty() && !content.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -070058 out.push('\n');
David Tolnay54702b92020-07-31 11:50:09 -070059 }
David Tolnaydab7e802020-08-28 18:54:48 -070060 out.push_str(content);
David Tolnay91489ec2020-09-03 12:48:46 -070061 if out.is_empty() {
62 out.push_str("// empty\n");
63 }
David Tolnaydab7e802020-08-28 18:54:48 -070064 out.into_bytes()
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 Tolnaydab7e802020-08-28 18:54:48 -070070 self.write(s);
David Tolnayf4632de2020-07-31 10:46:55 -070071 Ok(())
72 }
73}
74
David Tolnay8810a542020-10-31 21:39:22 -070075impl PartialEq for Content {
76 fn eq(&self, _other: &Content) -> bool {
77 true
78 }
79}
80
David Tolnayf4632de2020-07-31 10:46:55 -070081impl Content {
David Tolnay54702b92020-07-31 11:50:09 -070082 fn new() -> Self {
David Tolnay8810a542020-10-31 21:39:22 -070083 Content::default()
David Tolnay54702b92020-07-31 11:50:09 -070084 }
85
David Tolnaycb2189f2020-10-31 21:23:08 -070086 pub fn next_section(&mut self) {
87 self.section_pending = true;
88 }
89
90 pub fn begin_block(&mut self, block: &'static str) {
91 self.blocks_pending.push(block);
92 }
93
94 pub fn end_block(&mut self, block: &'static str) {
95 if self.blocks_pending.pop().is_none() {
96 self.bytes.push_str("} // ");
97 self.bytes.push_str(block);
98 self.bytes.push('\n');
99 self.section_pending = true;
100 }
101 }
102
103 pub fn write_fmt(&mut self, args: Arguments) {
104 Write::write_fmt(self, args).unwrap();
105 }
106
David Tolnaydab7e802020-08-28 18:54:48 -0700107 fn write(&mut self, b: &str) {
David Tolnayf4632de2020-07-31 10:46:55 -0700108 if !b.is_empty() {
David Tolnay9ad1fbc2020-03-01 14:01:24 -0800109 if !self.blocks_pending.is_empty() {
David Tolnay7ece56f2020-03-29 21:21:38 -0700110 if !self.bytes.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -0700111 self.bytes.push('\n');
David Tolnay3577d452020-03-17 21:48:13 -0700112 }
David Tolnay9ad1fbc2020-03-01 14:01:24 -0800113 for block in self.blocks_pending.drain(..) {
David Tolnaydab7e802020-08-28 18:54:48 -0700114 self.bytes.push_str(block);
115 self.bytes.push_str(" {\n");
David Tolnayb92e66f2020-03-01 13:36:55 -0800116 }
David Tolnay7db73692019-10-20 14:51:12 -0400117 self.section_pending = false;
118 } else if self.section_pending {
David Tolnay7ece56f2020-03-29 21:21:38 -0700119 if !self.bytes.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -0700120 self.bytes.push('\n');
David Tolnay3577d452020-03-17 21:48:13 -0700121 }
David Tolnay7db73692019-10-20 14:51:12 -0400122 self.section_pending = false;
123 }
David Tolnaydab7e802020-08-28 18:54:48 -0700124 self.bytes.push_str(b);
David Tolnay7db73692019-10-20 14:51:12 -0400125 }
David Tolnay7db73692019-10-20 14:51:12 -0400126 }
127}