blob: 99aecc283077b45bc4a3e4a2bc3dd47e0f096337 [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 Tolnay8c14d9a2020-10-31 21:52:38 -070053 let builtin = &self.builtin.content.bytes;
David Tolnay54702b92020-07-31 11:50:09 -070054 let content = &self.content.borrow().bytes;
David Tolnay8c14d9a2020-10-31 21:52:38 -070055 let len = include.len() + builtin.len() + content.len() + 2;
David Tolnaydab7e802020-08-28 18:54:48 -070056 let mut out = String::with_capacity(len);
David Tolnay8810a542020-10-31 21:39:22 -070057 out.push_str(include);
David Tolnay8c14d9a2020-10-31 21:52:38 -070058 if !out.is_empty() && !builtin.is_empty() {
59 out.push('\n');
60 }
61 out.push_str(builtin);
62 if !out.is_empty() && !content.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -070063 out.push('\n');
David Tolnay54702b92020-07-31 11:50:09 -070064 }
David Tolnaydab7e802020-08-28 18:54:48 -070065 out.push_str(content);
David Tolnay91489ec2020-09-03 12:48:46 -070066 if out.is_empty() {
67 out.push_str("// empty\n");
68 }
David Tolnaydab7e802020-08-28 18:54:48 -070069 out.into_bytes()
David Tolnay7db73692019-10-20 14:51:12 -040070 }
71}
72
David Tolnay7ece56f2020-03-29 21:21:38 -070073impl Write for Content {
David Tolnay7db73692019-10-20 14:51:12 -040074 fn write_str(&mut self, s: &str) -> fmt::Result {
David Tolnaydab7e802020-08-28 18:54:48 -070075 self.write(s);
David Tolnayf4632de2020-07-31 10:46:55 -070076 Ok(())
77 }
78}
79
David Tolnay8810a542020-10-31 21:39:22 -070080impl PartialEq for Content {
81 fn eq(&self, _other: &Content) -> bool {
82 true
83 }
84}
85
David Tolnayf4632de2020-07-31 10:46:55 -070086impl Content {
David Tolnay54702b92020-07-31 11:50:09 -070087 fn new() -> Self {
David Tolnay8810a542020-10-31 21:39:22 -070088 Content::default()
David Tolnay54702b92020-07-31 11:50:09 -070089 }
90
David Tolnaycb2189f2020-10-31 21:23:08 -070091 pub fn next_section(&mut self) {
92 self.section_pending = true;
93 }
94
95 pub fn begin_block(&mut self, block: &'static str) {
96 self.blocks_pending.push(block);
97 }
98
99 pub fn end_block(&mut self, block: &'static str) {
100 if self.blocks_pending.pop().is_none() {
101 self.bytes.push_str("} // ");
102 self.bytes.push_str(block);
103 self.bytes.push('\n');
104 self.section_pending = true;
105 }
106 }
107
108 pub fn write_fmt(&mut self, args: Arguments) {
109 Write::write_fmt(self, args).unwrap();
110 }
111
David Tolnaydab7e802020-08-28 18:54:48 -0700112 fn write(&mut self, b: &str) {
David Tolnayf4632de2020-07-31 10:46:55 -0700113 if !b.is_empty() {
David Tolnay9ad1fbc2020-03-01 14:01:24 -0800114 if !self.blocks_pending.is_empty() {
David Tolnay7ece56f2020-03-29 21:21:38 -0700115 if !self.bytes.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -0700116 self.bytes.push('\n');
David Tolnay3577d452020-03-17 21:48:13 -0700117 }
David Tolnay9ad1fbc2020-03-01 14:01:24 -0800118 for block in self.blocks_pending.drain(..) {
David Tolnaydab7e802020-08-28 18:54:48 -0700119 self.bytes.push_str(block);
120 self.bytes.push_str(" {\n");
David Tolnayb92e66f2020-03-01 13:36:55 -0800121 }
David Tolnay7db73692019-10-20 14:51:12 -0400122 self.section_pending = false;
123 } else if self.section_pending {
David Tolnay7ece56f2020-03-29 21:21:38 -0700124 if !self.bytes.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -0700125 self.bytes.push('\n');
David Tolnay3577d452020-03-17 21:48:13 -0700126 }
David Tolnay7db73692019-10-20 14:51:12 -0400127 self.section_pending = false;
128 }
David Tolnaydab7e802020-08-28 18:54:48 -0700129 self.bytes.push_str(b);
David Tolnay7db73692019-10-20 14:51:12 -0400130 }
David Tolnay7db73692019-10-20 14:51:12 -0400131 }
132}