blob: 6ba44aa3203f8a67b3ecfa8dc80af2f3a2f718de [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 Tolnaye1476af2020-11-01 13:47:25 -08003use crate::gen::Opt;
David Tolnayb560a0f2020-10-30 21:28:45 -07004use crate::syntax::Types;
David Tolnay7ece56f2020-03-29 21:21:38 -07005use std::cell::RefCell;
David Tolnay7db73692019-10-20 14:51:12 -04006use std::fmt::{self, Arguments, Write};
7
David Tolnayb560a0f2020-10-30 21:28:45 -07008pub(crate) struct OutFile<'a> {
David Tolnay7db73692019-10-20 14:51:12 -04009 pub header: bool,
David Tolnaye1476af2020-11-01 13:47:25 -080010 pub opt: &'a Opt,
David Tolnayb560a0f2020-10-30 21:28:45 -070011 pub types: &'a Types<'a>,
David Tolnay9c68b1a2020-03-06 11:12:55 -080012 pub include: Includes,
David Tolnay3be0e1f2020-10-31 20:53:00 -070013 pub builtin: Builtins,
David Tolnay7ece56f2020-03-29 21:21:38 -070014 content: RefCell<Content>,
15}
16
David Tolnay8810a542020-10-31 21:39:22 -070017#[derive(Default)]
David Tolnay54702b92020-07-31 11:50:09 -070018pub struct Content {
David Tolnaydab7e802020-08-28 18:54:48 -070019 bytes: String,
David Tolnay7db73692019-10-20 14:51:12 -040020 section_pending: bool,
David Tolnayf9d34a12020-11-01 12:20:39 -080021 blocks_pending: Vec<String>,
David Tolnay7db73692019-10-20 14:51:12 -040022}
23
David Tolnayb560a0f2020-10-30 21:28:45 -070024impl<'a> OutFile<'a> {
David Tolnaye1476af2020-11-01 13:47:25 -080025 pub fn new(header: bool, opt: &'a Opt, types: &'a Types) -> Self {
David Tolnay7db73692019-10-20 14:51:12 -040026 OutFile {
David Tolnay7db73692019-10-20 14:51:12 -040027 header,
David Tolnaye1476af2020-11-01 13:47:25 -080028 opt,
David Tolnayb560a0f2020-10-30 21:28:45 -070029 types,
David Tolnay9c68b1a2020-03-06 11:12:55 -080030 include: Includes::new(),
David Tolnay3be0e1f2020-10-31 20:53:00 -070031 builtin: Builtins::new(),
David Tolnay54702b92020-07-31 11:50:09 -070032 content: RefCell::new(Content::new()),
David Tolnay7db73692019-10-20 14:51:12 -040033 }
34 }
35
36 // Write a blank line if the preceding section had any contents.
37 pub fn next_section(&mut self) {
David Tolnaycb2189f2020-10-31 21:23:08 -070038 self.content.get_mut().next_section();
David Tolnay7db73692019-10-20 14:51:12 -040039 }
40
David Tolnayf9d34a12020-11-01 12:20:39 -080041 pub fn begin_block(&mut self, block: &str) {
David Tolnaycb2189f2020-10-31 21:23:08 -070042 self.content.get_mut().begin_block(block);
David Tolnay7db73692019-10-20 14:51:12 -040043 }
44
David Tolnayf9d34a12020-11-01 12:20:39 -080045 pub fn end_block(&mut self, block: &str) {
David Tolnaycb2189f2020-10-31 21:23:08 -070046 self.content.get_mut().end_block(block);
David Tolnay7db73692019-10-20 14:51:12 -040047 }
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 Tolnay8810a542020-10-31 21:39:22 -070055 let include = &self.include.content.bytes;
David Tolnay8c14d9a2020-10-31 21:52:38 -070056 let builtin = &self.builtin.content.bytes;
David Tolnay54702b92020-07-31 11:50:09 -070057 let content = &self.content.borrow().bytes;
David Tolnay8c14d9a2020-10-31 21:52:38 -070058 let len = include.len() + builtin.len() + content.len() + 2;
David Tolnaydab7e802020-08-28 18:54:48 -070059 let mut out = String::with_capacity(len);
David Tolnay8810a542020-10-31 21:39:22 -070060 out.push_str(include);
David Tolnay8c14d9a2020-10-31 21:52:38 -070061 if !out.is_empty() && !builtin.is_empty() {
62 out.push('\n');
63 }
64 out.push_str(builtin);
65 if !out.is_empty() && !content.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -070066 out.push('\n');
David Tolnay54702b92020-07-31 11:50:09 -070067 }
David Tolnaydab7e802020-08-28 18:54:48 -070068 out.push_str(content);
David Tolnay91489ec2020-09-03 12:48:46 -070069 if out.is_empty() {
70 out.push_str("// empty\n");
71 }
David Tolnaydab7e802020-08-28 18:54:48 -070072 out.into_bytes()
David Tolnay7db73692019-10-20 14:51:12 -040073 }
74}
75
David Tolnay7ece56f2020-03-29 21:21:38 -070076impl Write for Content {
David Tolnay7db73692019-10-20 14:51:12 -040077 fn write_str(&mut self, s: &str) -> fmt::Result {
David Tolnaydab7e802020-08-28 18:54:48 -070078 self.write(s);
David Tolnayf4632de2020-07-31 10:46:55 -070079 Ok(())
80 }
81}
82
David Tolnay8810a542020-10-31 21:39:22 -070083impl PartialEq for Content {
84 fn eq(&self, _other: &Content) -> bool {
85 true
86 }
87}
88
David Tolnayf4632de2020-07-31 10:46:55 -070089impl Content {
David Tolnay54702b92020-07-31 11:50:09 -070090 fn new() -> Self {
David Tolnay8810a542020-10-31 21:39:22 -070091 Content::default()
David Tolnay54702b92020-07-31 11:50:09 -070092 }
93
David Tolnaycb2189f2020-10-31 21:23:08 -070094 pub fn next_section(&mut self) {
95 self.section_pending = true;
96 }
97
David Tolnayf9d34a12020-11-01 12:20:39 -080098 pub fn begin_block(&mut self, block: &str) {
99 self.blocks_pending.push(block.to_owned());
David Tolnaycb2189f2020-10-31 21:23:08 -0700100 }
101
David Tolnayf9d34a12020-11-01 12:20:39 -0800102 pub fn end_block(&mut self, block: &str) {
David Tolnaycb2189f2020-10-31 21:23:08 -0700103 if self.blocks_pending.pop().is_none() {
104 self.bytes.push_str("} // ");
105 self.bytes.push_str(block);
106 self.bytes.push('\n');
107 self.section_pending = true;
108 }
109 }
110
111 pub fn write_fmt(&mut self, args: Arguments) {
112 Write::write_fmt(self, args).unwrap();
113 }
114
David Tolnaydab7e802020-08-28 18:54:48 -0700115 fn write(&mut self, b: &str) {
David Tolnayf4632de2020-07-31 10:46:55 -0700116 if !b.is_empty() {
David Tolnay9ad1fbc2020-03-01 14:01:24 -0800117 if !self.blocks_pending.is_empty() {
David Tolnay7ece56f2020-03-29 21:21:38 -0700118 if !self.bytes.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -0700119 self.bytes.push('\n');
David Tolnay3577d452020-03-17 21:48:13 -0700120 }
David Tolnay9ad1fbc2020-03-01 14:01:24 -0800121 for block in self.blocks_pending.drain(..) {
David Tolnayf9d34a12020-11-01 12:20:39 -0800122 self.bytes.push_str(&block);
David Tolnaydab7e802020-08-28 18:54:48 -0700123 self.bytes.push_str(" {\n");
David Tolnayb92e66f2020-03-01 13:36:55 -0800124 }
David Tolnay7db73692019-10-20 14:51:12 -0400125 self.section_pending = false;
126 } else if self.section_pending {
David Tolnay7ece56f2020-03-29 21:21:38 -0700127 if !self.bytes.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -0700128 self.bytes.push('\n');
David Tolnay3577d452020-03-17 21:48:13 -0700129 }
David Tolnay7db73692019-10-20 14:51:12 -0400130 self.section_pending = false;
131 }
David Tolnaydab7e802020-08-28 18:54:48 -0700132 self.bytes.push_str(b);
David Tolnay7db73692019-10-20 14:51:12 -0400133 }
David Tolnay7db73692019-10-20 14:51:12 -0400134 }
135}