blob: 8783dc212772c47a20ed00f66a13b0c386592e44 [file] [log] [blame]
David Tolnay9c68b1a2020-03-06 11:12:55 -08001use crate::gen::include::Includes;
David Tolnay754e21c2020-03-29 20:58:46 -07002use crate::gen::namespace::Namespace;
David Tolnay7db73692019-10-20 14:51:12 -04003use std::fmt::{self, Arguments, Write};
4
5pub(crate) struct OutFile {
David Tolnay754e21c2020-03-29 20:58:46 -07006 pub namespace: Namespace,
David Tolnay7db73692019-10-20 14:51:12 -04007 pub header: bool,
David Tolnay9c68b1a2020-03-06 11:12:55 -08008 pub include: Includes,
David Tolnay7db73692019-10-20 14:51:12 -04009 content: Vec<u8>,
10 section_pending: bool,
David Tolnay9ad1fbc2020-03-01 14:01:24 -080011 blocks_pending: Vec<&'static str>,
David Tolnay7db73692019-10-20 14:51:12 -040012}
13
14impl OutFile {
David Tolnay754e21c2020-03-29 20:58:46 -070015 pub fn new(namespace: Namespace, header: bool) -> Self {
David Tolnay7db73692019-10-20 14:51:12 -040016 OutFile {
17 namespace,
18 header,
David Tolnay9c68b1a2020-03-06 11:12:55 -080019 include: Includes::new(),
David Tolnay7db73692019-10-20 14:51:12 -040020 content: Vec::new(),
21 section_pending: false,
David Tolnay9ad1fbc2020-03-01 14:01:24 -080022 blocks_pending: Vec::new(),
David Tolnay7db73692019-10-20 14:51:12 -040023 }
24 }
25
26 // Write a blank line if the preceding section had any contents.
27 pub fn next_section(&mut self) {
28 self.section_pending = true;
29 }
30
31 pub fn begin_block(&mut self, block: &'static str) {
David Tolnay9ad1fbc2020-03-01 14:01:24 -080032 self.blocks_pending.push(block);
David Tolnay7db73692019-10-20 14:51:12 -040033 }
34
David Tolnay9ad1fbc2020-03-01 14:01:24 -080035 pub fn end_block(&mut self, block: &'static str) {
36 if self.blocks_pending.pop().is_none() {
David Tolnay7db73692019-10-20 14:51:12 -040037 self.content.extend_from_slice(b"} // ");
David Tolnay9ad1fbc2020-03-01 14:01:24 -080038 self.content.extend_from_slice(block.as_bytes());
David Tolnay7db73692019-10-20 14:51:12 -040039 self.content.push(b'\n');
David Tolnay7db73692019-10-20 14:51:12 -040040 self.section_pending = true;
41 }
42 }
43
David Tolnay9c68b1a2020-03-06 11:12:55 -080044 pub fn prepend(&mut self, section: String) {
45 self.content.splice(..0, section.into_bytes());
46 }
47
David Tolnay7db73692019-10-20 14:51:12 -040048 pub fn write_fmt(&mut self, args: Arguments) {
49 Write::write_fmt(self, args).unwrap();
50 }
51}
52
53impl Write for OutFile {
54 fn write_str(&mut self, s: &str) -> fmt::Result {
55 if !s.is_empty() {
David Tolnay9ad1fbc2020-03-01 14:01:24 -080056 if !self.blocks_pending.is_empty() {
David Tolnay3577d452020-03-17 21:48:13 -070057 if !self.content.is_empty() {
58 self.content.push(b'\n');
59 }
David Tolnay9ad1fbc2020-03-01 14:01:24 -080060 for block in self.blocks_pending.drain(..) {
David Tolnayb92e66f2020-03-01 13:36:55 -080061 self.content.extend_from_slice(block.as_bytes());
62 self.content.extend_from_slice(b" {\n");
63 }
David Tolnay7db73692019-10-20 14:51:12 -040064 self.section_pending = false;
65 } else if self.section_pending {
David Tolnay3577d452020-03-17 21:48:13 -070066 if !self.content.is_empty() {
67 self.content.push(b'\n');
68 }
David Tolnay7db73692019-10-20 14:51:12 -040069 self.section_pending = false;
70 }
71 self.content.extend_from_slice(s.as_bytes());
72 }
73 Ok(())
74 }
75}
76
77impl AsRef<[u8]> for OutFile {
78 fn as_ref(&self) -> &[u8] {
79 &self.content
80 }
81}