blob: 7498c69f0c67e490011705f0e033dc4bddbb9649 [file] [log] [blame]
David Tolnay0c033e32020-11-01 15:15:48 -08001use crate::gen::block::Block;
David Tolnay3be0e1f2020-10-31 20:53:00 -07002use crate::gen::builtin::Builtins;
David Tolnay9c68b1a2020-03-06 11:12:55 -08003use crate::gen::include::Includes;
David Tolnaye1476af2020-11-01 13:47:25 -08004use crate::gen::Opt;
David Tolnayb560a0f2020-10-30 21:28:45 -07005use crate::syntax::Types;
David Tolnay7ece56f2020-03-29 21:21:38 -07006use std::cell::RefCell;
David Tolnay7db73692019-10-20 14:51:12 -04007use std::fmt::{self, Arguments, Write};
8
David Tolnayb560a0f2020-10-30 21:28:45 -07009pub(crate) struct OutFile<'a> {
David Tolnay7db73692019-10-20 14:51:12 -040010 pub header: bool,
David Tolnaye1476af2020-11-01 13:47:25 -080011 pub opt: &'a Opt,
David Tolnayb560a0f2020-10-30 21:28:45 -070012 pub types: &'a Types<'a>,
David Tolnay97c5b862020-11-01 14:59:01 -080013 pub include: Includes<'a>,
14 pub builtin: Builtins<'a>,
15 content: RefCell<Content<'a>>,
David Tolnay7ece56f2020-03-29 21:21:38 -070016}
17
David Tolnay8810a542020-10-31 21:39:22 -070018#[derive(Default)]
David Tolnay97c5b862020-11-01 14:59:01 -080019pub struct Content<'a> {
David Tolnaydab7e802020-08-28 18:54:48 -070020 bytes: String,
David Tolnay7db73692019-10-20 14:51:12 -040021 section_pending: bool,
David Tolnay97c5b862020-11-01 14:59:01 -080022 blocks_pending: Vec<Block<'a>>,
David Tolnay7db73692019-10-20 14:51:12 -040023}
24
David Tolnayb560a0f2020-10-30 21:28:45 -070025impl<'a> OutFile<'a> {
David Tolnaye1476af2020-11-01 13:47:25 -080026 pub fn new(header: bool, opt: &'a Opt, types: &'a Types) -> Self {
David Tolnay7db73692019-10-20 14:51:12 -040027 OutFile {
David Tolnay7db73692019-10-20 14:51:12 -040028 header,
David Tolnaye1476af2020-11-01 13:47:25 -080029 opt,
David Tolnayb560a0f2020-10-30 21:28:45 -070030 types,
David Tolnay9c68b1a2020-03-06 11:12:55 -080031 include: Includes::new(),
David Tolnay3be0e1f2020-10-31 20:53:00 -070032 builtin: Builtins::new(),
David Tolnay54702b92020-07-31 11:50:09 -070033 content: RefCell::new(Content::new()),
David Tolnay7db73692019-10-20 14:51:12 -040034 }
35 }
36
37 // Write a blank line if the preceding section had any contents.
38 pub fn next_section(&mut self) {
David Tolnaycb2189f2020-10-31 21:23:08 -070039 self.content.get_mut().next_section();
David Tolnay7db73692019-10-20 14:51:12 -040040 }
41
David Tolnay97c5b862020-11-01 14:59:01 -080042 pub fn begin_block(&mut self, block: Block<'a>) {
David Tolnaycb2189f2020-10-31 21:23:08 -070043 self.content.get_mut().begin_block(block);
David Tolnay7db73692019-10-20 14:51:12 -040044 }
45
David Tolnay97c5b862020-11-01 14:59:01 -080046 pub fn end_block(&mut self, block: Block<'a>) {
David Tolnaycb2189f2020-10-31 21:23:08 -070047 self.content.get_mut().end_block(block);
David Tolnay7db73692019-10-20 14:51:12 -040048 }
49
David Tolnay7ece56f2020-03-29 21:21:38 -070050 pub fn write_fmt(&self, args: Arguments) {
51 let content = &mut *self.content.borrow_mut();
52 Write::write_fmt(content, args).unwrap();
53 }
54
55 pub fn content(&self) -> Vec<u8> {
David Tolnay8810a542020-10-31 21:39:22 -070056 let include = &self.include.content.bytes;
David Tolnay8c14d9a2020-10-31 21:52:38 -070057 let builtin = &self.builtin.content.bytes;
David Tolnay54702b92020-07-31 11:50:09 -070058 let content = &self.content.borrow().bytes;
David Tolnay8c14d9a2020-10-31 21:52:38 -070059 let len = include.len() + builtin.len() + content.len() + 2;
David Tolnaydab7e802020-08-28 18:54:48 -070060 let mut out = String::with_capacity(len);
David Tolnay8810a542020-10-31 21:39:22 -070061 out.push_str(include);
David Tolnay8c14d9a2020-10-31 21:52:38 -070062 if !out.is_empty() && !builtin.is_empty() {
63 out.push('\n');
64 }
65 out.push_str(builtin);
66 if !out.is_empty() && !content.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -070067 out.push('\n');
David Tolnay54702b92020-07-31 11:50:09 -070068 }
David Tolnaydab7e802020-08-28 18:54:48 -070069 out.push_str(content);
David Tolnay91489ec2020-09-03 12:48:46 -070070 if out.is_empty() {
71 out.push_str("// empty\n");
72 }
David Tolnaydab7e802020-08-28 18:54:48 -070073 out.into_bytes()
David Tolnay7db73692019-10-20 14:51:12 -040074 }
75}
76
David Tolnay97c5b862020-11-01 14:59:01 -080077impl<'a> Write for Content<'a> {
David Tolnay7db73692019-10-20 14:51:12 -040078 fn write_str(&mut self, s: &str) -> fmt::Result {
David Tolnaydab7e802020-08-28 18:54:48 -070079 self.write(s);
David Tolnayf4632de2020-07-31 10:46:55 -070080 Ok(())
81 }
82}
83
David Tolnay97c5b862020-11-01 14:59:01 -080084impl<'a> PartialEq for Content<'a> {
David Tolnay8810a542020-10-31 21:39:22 -070085 fn eq(&self, _other: &Content) -> bool {
86 true
87 }
88}
89
David Tolnay97c5b862020-11-01 14:59:01 -080090impl<'a> Content<'a> {
David Tolnay54702b92020-07-31 11:50:09 -070091 fn new() -> Self {
David Tolnay8810a542020-10-31 21:39:22 -070092 Content::default()
David Tolnay54702b92020-07-31 11:50:09 -070093 }
94
David Tolnaycb2189f2020-10-31 21:23:08 -070095 pub fn next_section(&mut self) {
96 self.section_pending = true;
97 }
98
David Tolnay97c5b862020-11-01 14:59:01 -080099 pub fn begin_block(&mut self, block: Block<'a>) {
David Tolnay0c033e32020-11-01 15:15:48 -0800100 self.blocks_pending.push(block);
David Tolnaycb2189f2020-10-31 21:23:08 -0700101 }
102
David Tolnay97c5b862020-11-01 14:59:01 -0800103 pub fn end_block(&mut self, block: Block<'a>) {
David Tolnaycb2189f2020-10-31 21:23:08 -0700104 if self.blocks_pending.pop().is_none() {
David Tolnay2a160e42020-11-01 15:40:20 -0800105 Block::write_end(block, &mut self.bytes);
David Tolnaycb2189f2020-10-31 21:23:08 -0700106 self.section_pending = true;
107 }
108 }
109
110 pub fn write_fmt(&mut self, args: Arguments) {
111 Write::write_fmt(self, args).unwrap();
112 }
113
David Tolnaydab7e802020-08-28 18:54:48 -0700114 fn write(&mut self, b: &str) {
David Tolnayf4632de2020-07-31 10:46:55 -0700115 if !b.is_empty() {
David Tolnay9ad1fbc2020-03-01 14:01:24 -0800116 if !self.blocks_pending.is_empty() {
David Tolnay7ece56f2020-03-29 21:21:38 -0700117 if !self.bytes.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -0700118 self.bytes.push('\n');
David Tolnay3577d452020-03-17 21:48:13 -0700119 }
David Tolnay9ad1fbc2020-03-01 14:01:24 -0800120 for block in self.blocks_pending.drain(..) {
David Tolnay2a160e42020-11-01 15:40:20 -0800121 Block::write_begin(block, &mut self.bytes);
David Tolnayb92e66f2020-03-01 13:36:55 -0800122 }
David Tolnay7db73692019-10-20 14:51:12 -0400123 self.section_pending = false;
124 } else if self.section_pending {
David Tolnay7ece56f2020-03-29 21:21:38 -0700125 if !self.bytes.is_empty() {
David Tolnaydab7e802020-08-28 18:54:48 -0700126 self.bytes.push('\n');
David Tolnay3577d452020-03-17 21:48:13 -0700127 }
David Tolnay7db73692019-10-20 14:51:12 -0400128 self.section_pending = false;
129 }
David Tolnaydab7e802020-08-28 18:54:48 -0700130 self.bytes.push_str(b);
David Tolnay7db73692019-10-20 14:51:12 -0400131 }
David Tolnay7db73692019-10-20 14:51:12 -0400132 }
133}