cxx_build/gen/
out.rs

1use crate::gen::block::Block;
2use crate::gen::builtin::Builtins;
3use crate::gen::include::Includes;
4use crate::gen::pragma::Pragma;
5use crate::gen::Opt;
6use crate::syntax::namespace::Namespace;
7use crate::syntax::Types;
8use std::cell::RefCell;
9use std::fmt::{self, Arguments, Write};
10
11pub(crate) struct OutFile<'a> {
12    pub header: bool,
13    pub opt: &'a Opt,
14    pub types: &'a Types<'a>,
15    pub include: Includes<'a>,
16    pub pragma: Pragma<'a>,
17    pub builtin: Builtins<'a>,
18    content: RefCell<Content<'a>>,
19}
20
21#[derive(#[automatically_derived]
impl<'a> ::core::default::Default for Content<'a> {
    #[inline]
    fn default() -> Content<'a> {
        Content {
            bytes: ::core::default::Default::default(),
            namespace: ::core::default::Default::default(),
            blocks: ::core::default::Default::default(),
            suppress_next_section: ::core::default::Default::default(),
            section_pending: ::core::default::Default::default(),
            blocks_pending: ::core::default::Default::default(),
        }
    }
}Default)]
22pub(crate) struct Content<'a> {
23    bytes: String,
24    namespace: &'a Namespace,
25    blocks: Vec<BlockBoundary<'a>>,
26    suppress_next_section: bool,
27    section_pending: bool,
28    blocks_pending: usize,
29}
30
31#[derive(#[automatically_derived]
impl<'a> ::core::marker::Copy for BlockBoundary<'a> { }Copy, #[automatically_derived]
impl<'a> ::core::clone::Clone for BlockBoundary<'a> {
    #[inline]
    fn clone(&self) -> BlockBoundary<'a> {
        let _: ::core::clone::AssertParamIsClone<Block<'a>>;
        let _: ::core::clone::AssertParamIsClone<Block<'a>>;
        *self
    }
}Clone, #[automatically_derived]
impl<'a> ::core::cmp::PartialEq for BlockBoundary<'a> {
    #[inline]
    fn eq(&self, other: &BlockBoundary<'a>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (BlockBoundary::Begin(__self_0),
                    BlockBoundary::Begin(__arg1_0)) => __self_0 == __arg1_0,
                (BlockBoundary::End(__self_0), BlockBoundary::End(__arg1_0))
                    => __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl<'a> ::core::fmt::Debug for BlockBoundary<'a> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            BlockBoundary::Begin(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Begin",
                    &__self_0),
            BlockBoundary::End(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "End",
                    &__self_0),
        }
    }
}Debug)]
32enum BlockBoundary<'a> {
33    Begin(Block<'a>),
34    End(Block<'a>),
35}
36
37impl<'a> OutFile<'a> {
38    pub(crate) fn new(header: bool, opt: &'a Opt, types: &'a Types) -> Self {
39        OutFile {
40            header,
41            opt,
42            types,
43            include: Includes::new(),
44            pragma: Pragma::new(),
45            builtin: Builtins::new(),
46            content: RefCell::new(Content::new()),
47        }
48    }
49
50    // Write a blank line if the preceding section had any contents.
51    pub(crate) fn next_section(&mut self) {
52        self.content.get_mut().next_section();
53    }
54
55    pub(crate) fn suppress_next_section(&mut self) {
56        self.content.get_mut().suppress_next_section();
57    }
58
59    pub(crate) fn begin_block(&mut self, block: Block<'a>) {
60        self.content.get_mut().begin_block(block);
61    }
62
63    pub(crate) fn end_block(&mut self, block: Block<'a>) {
64        self.content.get_mut().end_block(block);
65    }
66
67    pub(crate) fn set_namespace(&mut self, namespace: &'a Namespace) {
68        self.content.get_mut().set_namespace(namespace);
69    }
70
71    pub(crate) fn content(&mut self) -> Vec<u8> {
72        self.flush();
73
74        let include = &self.include.content.bytes;
75        let pragma_begin = &self.pragma.begin.bytes;
76        let builtin = &self.builtin.content.bytes;
77        let content = &self.content.get_mut().bytes;
78        let pragma_end = &self.pragma.end.bytes;
79
80        let mut out = String::new();
81        out.push_str(include);
82        if !out.is_empty() && !pragma_begin.is_empty() {
83            out.push('\n');
84        }
85        out.push_str(pragma_begin);
86        if !out.is_empty() && !builtin.is_empty() {
87            out.push('\n');
88        }
89        out.push_str(builtin);
90        if !out.is_empty() && !content.is_empty() {
91            out.push('\n');
92        }
93        out.push_str(content);
94        if !out.is_empty() && !pragma_end.is_empty() {
95            out.push('\n');
96        }
97        out.push_str(pragma_end);
98        if out.is_empty() {
99            out.push_str("// empty\n");
100        }
101        out.into_bytes()
102    }
103
104    fn flush(&mut self) {
105        self.include.content.flush();
106        self.pragma.begin.flush();
107        self.builtin.content.flush();
108        self.content.get_mut().flush();
109        self.pragma.end.flush();
110    }
111}
112
113impl<'a> Write for Content<'a> {
114    fn write_str(&mut self, s: &str) -> fmt::Result {
115        self.write(s);
116        Ok(())
117    }
118}
119
120impl<'a> PartialEq for Content<'a> {
121    fn eq(&self, _other: &Self) -> bool {
122        true
123    }
124}
125
126impl<'a> Content<'a> {
127    pub(crate) fn new() -> Self {
128        Content::default()
129    }
130
131    pub(crate) fn next_section(&mut self) {
132        self.section_pending = !self.suppress_next_section;
133    }
134
135    pub(crate) fn suppress_next_section(&mut self) {
136        self.suppress_next_section = true;
137    }
138
139    pub(crate) fn begin_block(&mut self, block: Block<'a>) {
140        self.push_block_boundary(BlockBoundary::Begin(block));
141    }
142
143    pub(crate) fn end_block(&mut self, block: Block<'a>) {
144        self.push_block_boundary(BlockBoundary::End(block));
145    }
146
147    pub(crate) fn set_namespace(&mut self, namespace: &'a Namespace) {
148        for name in self.namespace.iter().rev() {
149            self.end_block(Block::UserDefinedNamespace(name));
150        }
151        for name in namespace {
152            self.begin_block(Block::UserDefinedNamespace(name));
153        }
154        self.namespace = namespace;
155    }
156
157    pub(crate) fn write_fmt(&mut self, args: Arguments) {
158        Write::write_fmt(self, args).unwrap();
159    }
160
161    fn write(&mut self, b: &str) {
162        if !b.is_empty() {
163            if self.blocks_pending > 0 {
164                self.flush_blocks();
165            }
166            if self.section_pending && !self.bytes.is_empty() {
167                self.bytes.push('\n');
168            }
169            self.bytes.push_str(b);
170            self.suppress_next_section = false;
171            self.section_pending = false;
172            self.blocks_pending = 0;
173        }
174    }
175
176    fn push_block_boundary(&mut self, boundary: BlockBoundary<'a>) {
177        if self.blocks_pending > 0 && boundary == self.blocks.last().unwrap().rev() {
178            self.blocks.pop();
179            self.blocks_pending -= 1;
180        } else {
181            self.blocks.push(boundary);
182            self.blocks_pending += 1;
183        }
184    }
185
186    fn flush(&mut self) {
187        self.set_namespace(Default::default());
188        if self.blocks_pending > 0 {
189            self.flush_blocks();
190        }
191    }
192
193    fn flush_blocks(&mut self) {
194        self.section_pending = !self.bytes.is_empty();
195        let mut read = self.blocks.len() - self.blocks_pending;
196        let mut write = read;
197
198        while read < self.blocks.len() {
199            match self.blocks[read] {
200                BlockBoundary::Begin(begin_block) => {
201                    if self.section_pending {
202                        self.bytes.push('\n');
203                        self.section_pending = false;
204                    }
205                    Block::write_begin(begin_block, &mut self.bytes);
206                    self.blocks[write] = BlockBoundary::Begin(begin_block);
207                    write += 1;
208                }
209                BlockBoundary::End(end_block) => {
210                    write = write.checked_sub(1).unwrap();
211                    let begin_block = self.blocks[write];
212                    match (&begin_block, &BlockBoundary::Begin(end_block)) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(begin_block, BlockBoundary::Begin(end_block));
213                    Block::write_end(end_block, &mut self.bytes);
214                    self.section_pending = true;
215                }
216            }
217            read += 1;
218        }
219
220        self.blocks.truncate(write);
221    }
222}
223
224impl<'a> BlockBoundary<'a> {
225    fn rev(self) -> BlockBoundary<'a> {
226        match self {
227            BlockBoundary::Begin(block) => BlockBoundary::End(block),
228            BlockBoundary::End(block) => BlockBoundary::Begin(block),
229        }
230    }
231}
232
233pub(crate) trait InfallibleWrite {
234    fn write_fmt(&mut self, args: Arguments);
235}
236
237impl InfallibleWrite for String {
238    fn write_fmt(&mut self, args: Arguments) {
239        Write::write_fmt(self, args).unwrap();
240    }
241}
242
243impl<'a> InfallibleWrite for Content<'a> {
244    fn write_fmt(&mut self, args: Arguments) {
245        Write::write_fmt(self, args).unwrap();
246    }
247}
248
249impl<'a> InfallibleWrite for OutFile<'a> {
250    fn write_fmt(&mut self, args: Arguments) {
251        InfallibleWrite::write_fmt(self.content.get_mut(), args);
252    }
253}