rust_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    /// Content before the block.
10    before: Option<String>,
11    /// Content after the block.
12    after: Option<String>,
13    /// The contents inside the block.
14    body: Vec<Body>,
15}
16
17impl Block {
18    /// Returns an empty code block.
19    /// 
20    /// # Arguments
21    /// 
22    /// * `before` - The contents to add before the block. This can be an empty "" if you don't want anything before the block.
23    /// 
24    /// # Examples
25    /// 
26    /// ```
27    /// use rust_codegen::Block;
28    /// 
29    /// let mut block = Block::new("");
30    /// ```
31    pub fn new(before: &str) -> Self {
32        Block {
33            before: Some(before.to_string()),
34            after: None,
35            body: vec![],
36        }
37    }
38
39    /// Push a line to the code block.
40    /// 
41    /// # Arguments 
42    /// 
43    /// * `line` - The line to add to the code block.
44    /// 
45    /// # Examples
46    /// 
47    /// ```
48    /// use rust_codegen::Block;
49    /// 
50    /// let mut block = Block::new("");
51    /// block.line("println!(\"Hello, world!\");");
52    /// ```
53    pub fn line<T>(&mut self, line: T) -> &mut Self
54    where
55        T: ToString,
56    {
57        self.body.push(Body::String(line.to_string()));
58        self
59    }
60
61    /// Push a nested block to this block.
62    /// 
63    /// # Arguments
64    /// 
65    /// * `block` - The block to push to this block.
66    /// 
67    /// # Examples
68    /// 
69    /// ```
70    /// use rust_codegen::Block;
71    /// 
72    /// let mut block_1 = Block::new("");
73    /// block_1.line("println!(\"Hello, world!\");");
74    /// 
75    /// let mut block_2 = Block::new("");
76    /// block_2.line("println!(\"from Rust!!\");");
77    /// 
78    /// block_1.push_block(block_2);
79    /// ```
80    pub fn push_block(&mut self, block: Block) -> &mut Self {
81        self.body.push(Body::Block(block));
82        self
83    }
84
85    /// Add a snippet after the block.
86    /// 
87    /// # Arguments 
88    /// 
89    /// * `after` - The snippet to add after the code block.
90    /// 
91    /// # Examples
92    /// 
93    /// ```
94    /// use rust_codegen::Block;
95    /// 
96    /// let mut block = Block::new("This is before");
97    /// block.after("This is after");
98    /// ```
99    pub fn after(&mut self, after: &str) -> &mut Self {
100        self.after = Some(after.to_string());
101        self
102    }
103
104    /// Formats the block using the given formatter.
105    /// 
106    /// # Arguments
107    /// 
108    /// * `fmt` - The formatter to use.
109    /// 
110    /// # Examples
111    /// 
112    /// ```
113    /// use rust_codegen::{Block, Formatter};
114    /// 
115    /// let mut dest = String::new();
116    /// let mut fmt = Formatter::new(&mut dest);
117    /// 
118    /// let mut block = Block::new("This is before");
119    /// block.fmt(&mut fmt);
120    /// ```
121    pub fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
122        if let Some(ref before) = self.before {
123            write!(fmt, "{}", before)?;
124        }
125
126        // Inlined `Formatter::fmt`
127
128        if !fmt.is_start_of_line() {
129            write!(fmt, " ")?;
130        }
131
132        write!(fmt, "{{\n")?;
133
134        fmt.indent(|fmt| {
135            for b in &self.body {
136                b.fmt(fmt)?;
137            }
138
139            Ok(())
140        })?;
141
142        write!(fmt, "}}")?;
143
144        if let Some(ref after) = self.after {
145            write!(fmt, "{}", after)?;
146        }
147
148        write!(fmt, "\n")?;
149        Ok(())
150    }
151}