codegen/
block.rs

1use std::fmt::{self, Write};
2
3use crate::body::Body;
4use crate::formatter::Formatter;
5
6/// Defines a code block. This is used to define a function body.
7#[derive(Debug, Clone)]
8pub struct Block {
9    before: Option<String>,
10    after: Option<String>,
11    body: Vec<Body>,
12}
13
14impl Block {
15    /// Returns an empty code block.
16    pub fn new(before: &str) -> Self {
17        Block {
18            before: Some(before.to_string()),
19            after: None,
20            body: vec![],
21        }
22    }
23
24    /// Push a line to the code block.
25    pub fn line<T>(&mut self, line: T) -> &mut Self
26    where
27        T: ToString,
28    {
29        self.body.push(Body::String(line.to_string()));
30        self
31    }
32
33    /// Push a nested block to this block.
34    pub fn push_block(&mut self, block: Block) -> &mut Self {
35        self.body.push(Body::Block(block));
36        self
37    }
38
39    /// Add a snippet after the block.
40    pub fn after(&mut self, after: &str) -> &mut Self {
41        self.after = Some(after.to_string());
42        self
43    }
44
45    /// Formats the block using the given formatter.
46    pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
47        if let Some(ref before) = self.before {
48            write!(fmt, "{}", before)?;
49        }
50
51        // Inlined `Formatter::fmt`
52
53        if !fmt.is_start_of_line() {
54            write!(fmt, " ")?;
55        }
56
57        write!(fmt, "{{\n")?;
58
59        fmt.indent(|fmt| {
60            for b in &self.body {
61                b.fmt(fmt)?;
62            }
63
64            Ok(())
65        })?;
66
67        write!(fmt, "}}")?;
68
69        if let Some(ref after) = self.after {
70            write!(fmt, "{}", after)?;
71        }
72
73        write!(fmt, "\n")?;
74        Ok(())
75    }
76}