blob: 2a5b17de1fa8bdce4f20e451272078124078ab7b [file] [log] [blame]
David Tolnay9c68b1a2020-03-06 11:12:55 -08001use crate::gen::include::Includes;
David Tolnay7db73692019-10-20 14:51:12 -04002use std::fmt::{self, Arguments, Write};
3
4pub(crate) struct OutFile {
5 pub namespace: Vec<String>,
6 pub header: bool,
David Tolnay9c68b1a2020-03-06 11:12:55 -08007 pub include: Includes,
David Tolnay7db73692019-10-20 14:51:12 -04008 content: Vec<u8>,
9 section_pending: bool,
David Tolnay9ad1fbc2020-03-01 14:01:24 -080010 blocks_pending: Vec<&'static str>,
David Tolnay7db73692019-10-20 14:51:12 -040011}
12
13impl OutFile {
14 pub fn new(namespace: Vec<String>, header: bool) -> Self {
15 OutFile {
16 namespace,
17 header,
David Tolnay9c68b1a2020-03-06 11:12:55 -080018 include: Includes::new(),
David Tolnay7db73692019-10-20 14:51:12 -040019 content: Vec::new(),
20 section_pending: false,
David Tolnay9ad1fbc2020-03-01 14:01:24 -080021 blocks_pending: Vec::new(),
David Tolnay7db73692019-10-20 14:51:12 -040022 }
23 }
24
25 // Write a blank line if the preceding section had any contents.
26 pub fn next_section(&mut self) {
27 self.section_pending = true;
28 }
29
30 pub fn begin_block(&mut self, block: &'static str) {
David Tolnay9ad1fbc2020-03-01 14:01:24 -080031 self.blocks_pending.push(block);
David Tolnay7db73692019-10-20 14:51:12 -040032 }
33
David Tolnay9ad1fbc2020-03-01 14:01:24 -080034 pub fn end_block(&mut self, block: &'static str) {
35 if self.blocks_pending.pop().is_none() {
David Tolnay7db73692019-10-20 14:51:12 -040036 self.content.extend_from_slice(b"} // ");
David Tolnay9ad1fbc2020-03-01 14:01:24 -080037 self.content.extend_from_slice(block.as_bytes());
David Tolnay7db73692019-10-20 14:51:12 -040038 self.content.push(b'\n');
David Tolnay7db73692019-10-20 14:51:12 -040039 self.section_pending = true;
40 }
41 }
42
David Tolnay9c68b1a2020-03-06 11:12:55 -080043 pub fn prepend(&mut self, section: String) {
44 self.content.splice(..0, section.into_bytes());
45 }
46
David Tolnay7db73692019-10-20 14:51:12 -040047 pub fn write_fmt(&mut self, args: Arguments) {
48 Write::write_fmt(self, args).unwrap();
49 }
50}
51
52impl Write for OutFile {
53 fn write_str(&mut self, s: &str) -> fmt::Result {
54 if !s.is_empty() {
David Tolnay9ad1fbc2020-03-01 14:01:24 -080055 if !self.blocks_pending.is_empty() {
David Tolnay3577d452020-03-17 21:48:13 -070056 if !self.content.is_empty() {
57 self.content.push(b'\n');
58 }
David Tolnay9ad1fbc2020-03-01 14:01:24 -080059 for block in self.blocks_pending.drain(..) {
David Tolnayb92e66f2020-03-01 13:36:55 -080060 self.content.extend_from_slice(block.as_bytes());
61 self.content.extend_from_slice(b" {\n");
62 }
David Tolnay7db73692019-10-20 14:51:12 -040063 self.section_pending = false;
64 } else if self.section_pending {
David Tolnay3577d452020-03-17 21:48:13 -070065 if !self.content.is_empty() {
66 self.content.push(b'\n');
67 }
David Tolnay7db73692019-10-20 14:51:12 -040068 self.section_pending = false;
69 }
70 self.content.extend_from_slice(s.as_bytes());
71 }
72 Ok(())
73 }
74}
75
76impl AsRef<[u8]> for OutFile {
77 fn as_ref(&self) -> &[u8] {
78 &self.content
79 }
80}