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}