hcl/structure/body.rs
1//! Types to represent and build HCL body structures.
2
3use super::iter::{
4 Attributes, AttributesMut, Blocks, BlocksMut, IntoAttributes, IntoBlocks, Iter, IterMut,
5};
6use super::ser::BodySerializer;
7use super::{Attribute, Block, Structure};
8use crate::ser::with_internal_serialization;
9use crate::{Error, Result};
10use serde::{Deserialize, Serialize};
11use std::str::FromStr;
12
13/// Represents an HCL config file body.
14///
15/// A `Body` consists of zero or more [`Attribute`] and [`Block`] HCL structures.
16#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Default, Clone)]
17#[serde(rename = "$hcl::Body")]
18pub struct Body(pub Vec<Structure>);
19
20impl Body {
21 #[doc(hidden)]
22 pub fn from_serializable<T>(value: &T) -> Result<Body>
23 where
24 T: ?Sized + Serialize,
25 {
26 with_internal_serialization(|| value.serialize(BodySerializer))
27 }
28
29 /// Consumes `self` and returns the wrapped `Vec<Structure>`.
30 pub fn into_inner(self) -> Vec<Structure> {
31 self.0
32 }
33
34 /// Creates a new [`BodyBuilder`] to start building a new `Body`.
35 pub fn builder() -> BodyBuilder {
36 BodyBuilder::default()
37 }
38
39 /// An iterator visiting all structures within the `Body`. The iterator element type is `&'a
40 /// Structure`.
41 ///
42 /// # Examples
43 ///
44 /// ```
45 /// use hcl::{Attribute, Body};
46 ///
47 /// let body = Body::from([
48 /// Attribute::new("a", 1),
49 /// Attribute::new("b", 2),
50 /// Attribute::new("c", 3),
51 /// ]);
52 ///
53 /// for structure in body.iter() {
54 /// println!("{structure:?}");
55 /// }
56 /// ```
57 pub fn iter(&self) -> Iter<'_> {
58 Iter::new(self)
59 }
60
61 /// An iterator visiting all structures within the `Body`. The iterator element type is `&'a
62 /// mut Structure`.
63 ///
64 /// # Examples
65 ///
66 /// ```
67 /// use hcl::{Attribute, Block, Body, Identifier, Structure};
68 ///
69 /// let mut body = Body::from([
70 /// Structure::Attribute(Attribute::new("a", 1)),
71 /// Structure::Block(Block::new("b")),
72 /// Structure::Attribute(Attribute::new("c", 3)),
73 /// ]);
74 ///
75 /// // Update all attribute keys and block identifiers
76 /// for structure in body.iter_mut() {
77 /// match structure {
78 /// Structure::Attribute(attr) => {
79 /// attr.key = Identifier::new(format!("attr_{}", attr.key)).unwrap();
80 /// }
81 /// Structure::Block(block) => {
82 /// block.identifier = Identifier::new(format!("block_{}", block.identifier)).unwrap();
83 /// }
84 /// }
85 /// }
86 ///
87 /// assert_eq!(body.into_inner(), [
88 /// Structure::Attribute(Attribute::new("attr_a", 1)),
89 /// Structure::Block(Block::new("block_b")),
90 /// Structure::Attribute(Attribute::new("attr_c", 3)),
91 /// ]);
92 /// ```
93 pub fn iter_mut(&mut self) -> IterMut<'_> {
94 IterMut::new(self)
95 }
96
97 /// An iterator visiting all attributes within the `Body`. The iterator element type is `&'a
98 /// Attribute`.
99 ///
100 /// # Examples
101 ///
102 /// ```
103 /// use hcl::{Attribute, Block, Body, Structure};
104 ///
105 /// let body = Body::from([
106 /// Structure::Attribute(Attribute::new("a", 1)),
107 /// Structure::Block(Block::new("b")),
108 /// Structure::Attribute(Attribute::new("c", 3)),
109 /// ]);
110 ///
111 /// let vec: Vec<&Attribute> = body.attributes().collect();
112 /// assert_eq!(vec, [&Attribute::new("a", 1), &Attribute::new("c", 3)]);
113 /// ```
114 pub fn attributes(&self) -> Attributes<'_> {
115 Attributes::new(self)
116 }
117
118 /// An iterator visiting all attributes within the `Body`. The iterator element type is `&'a
119 /// mut Attribute`.
120 ///
121 /// # Examples
122 ///
123 /// ```
124 /// use hcl::{Attribute, Block, Body, Identifier, Structure};
125 ///
126 /// let mut body = Body::from([
127 /// Structure::Attribute(Attribute::new("a", 1)),
128 /// Structure::Block(Block::new("b")),
129 /// Structure::Attribute(Attribute::new("c", 3)),
130 /// ]);
131 ///
132 /// // Update all attribute keys
133 /// for attr in body.attributes_mut() {
134 /// attr.key = Identifier::new(format!("attr_{}", attr.key)).unwrap();
135 /// }
136 ///
137 /// assert_eq!(body.into_inner(), [
138 /// Structure::Attribute(Attribute::new("attr_a", 1)),
139 /// Structure::Block(Block::new("b")),
140 /// Structure::Attribute(Attribute::new("attr_c", 3)),
141 /// ]);
142 /// ```
143 pub fn attributes_mut(&mut self) -> AttributesMut<'_> {
144 AttributesMut::new(self)
145 }
146
147 /// Creates a consuming iterator visiting all attributes within the `Body`. The object cannot
148 /// be used after calling this. The iterator element type is `Attribute`.
149 ///
150 /// # Examples
151 ///
152 /// ```
153 /// use hcl::{Attribute, Block, Body, Structure};
154 ///
155 /// let body = Body::from([
156 /// Structure::Attribute(Attribute::new("a", 1)),
157 /// Structure::Block(Block::new("b")),
158 /// Structure::Attribute(Attribute::new("c", 3)),
159 /// ]);
160 ///
161 /// let vec: Vec<Attribute> = body.into_attributes().collect();
162 /// assert_eq!(vec, [Attribute::new("a", 1), Attribute::new("c", 3)]);
163 /// ```
164 pub fn into_attributes(self) -> IntoAttributes {
165 IntoAttributes::new(self)
166 }
167
168 /// An iterator visiting all blocks within the `Body`. The iterator element type is `&'a
169 /// Block`.
170 ///
171 /// # Examples
172 ///
173 /// ```
174 /// use hcl::{Attribute, Block, Body, Structure};
175 ///
176 /// let body = Body::from([
177 /// Structure::Attribute(Attribute::new("a", 1)),
178 /// Structure::Block(Block::new("b")),
179 /// Structure::Attribute(Attribute::new("c", 3)),
180 /// ]);
181 ///
182 /// let vec: Vec<&Block> = body.blocks().collect();
183 /// assert_eq!(vec, [&Block::new("b")]);
184 /// ```
185 pub fn blocks(&self) -> Blocks<'_> {
186 Blocks::new(self)
187 }
188
189 /// An iterator visiting all blocks within the `Body`. The iterator element type is `&'a mut
190 /// Block`.
191 ///
192 /// # Examples
193 ///
194 /// ```
195 /// use hcl::{Attribute, Block, Body, Identifier, Structure};
196 ///
197 /// let mut body = Body::from([
198 /// Structure::Attribute(Attribute::new("a", 1)),
199 /// Structure::Block(Block::new("b")),
200 /// Structure::Attribute(Attribute::new("c", 3)),
201 /// ]);
202 ///
203 /// // Update all block identifiers
204 /// for block in body.blocks_mut() {
205 /// block.identifier = Identifier::new(format!("block_{}", block.identifier)).unwrap();
206 /// }
207 ///
208 /// assert_eq!(body.into_inner(), [
209 /// Structure::Attribute(Attribute::new("a", 1)),
210 /// Structure::Block(Block::new("block_b")),
211 /// Structure::Attribute(Attribute::new("c", 3)),
212 /// ]);
213 /// ```
214 pub fn blocks_mut(&mut self) -> BlocksMut<'_> {
215 BlocksMut::new(self)
216 }
217
218 /// Creates a consuming iterator visiting all blocks within the `Body`. The object cannot
219 /// be used after calling this. The iterator element type is `Block`.
220 ///
221 /// # Examples
222 ///
223 /// ```
224 /// use hcl::{Attribute, Block, Body, Structure};
225 ///
226 /// let body = Body::from([
227 /// Structure::Attribute(Attribute::new("a", 1)),
228 /// Structure::Block(Block::new("b")),
229 /// Structure::Attribute(Attribute::new("c", 3)),
230 /// ]);
231 ///
232 /// let vec: Vec<Block> = body.into_blocks().collect();
233 /// assert_eq!(vec, [Block::new("b")]);
234 /// ```
235 pub fn into_blocks(self) -> IntoBlocks {
236 IntoBlocks::new(self)
237 }
238}
239
240impl FromStr for Body {
241 type Err = Error;
242
243 #[inline]
244 fn from_str(s: &str) -> Result<Self, Self::Err> {
245 let body: hcl_edit::structure::Body = s.parse()?;
246 Ok(body.into())
247 }
248}
249
250impl<T> From<T> for Body
251where
252 T: Into<Structure>,
253{
254 fn from(value: T) -> Body {
255 Body(vec![value.into()])
256 }
257}
258
259impl<T> From<Vec<T>> for Body
260where
261 T: Into<Structure>,
262{
263 fn from(vec: Vec<T>) -> Self {
264 Body::from_iter(vec)
265 }
266}
267
268impl<T> From<&[T]> for Body
269where
270 T: Clone + Into<Structure>,
271{
272 fn from(slice: &[T]) -> Self {
273 Body::from_iter(slice.to_vec())
274 }
275}
276
277impl<T> From<&mut [T]> for Body
278where
279 T: Clone + Into<Structure>,
280{
281 fn from(slice: &mut [T]) -> Self {
282 Body::from_iter(slice.to_vec())
283 }
284}
285
286impl<T, const N: usize> From<[T; N]> for Body
287where
288 T: Into<Structure>,
289{
290 fn from(arr: [T; N]) -> Self {
291 Body::from_iter(arr)
292 }
293}
294
295/// `BodyBuilder` builds a HCL [`Body`].
296///
297/// The builder allows to build the `Body` by adding attributes and other nested blocks via chained
298/// method calls. A call to [`.build()`](BodyBuilder::build) produces the final `Body`.
299///
300/// ## Example
301///
302/// ```
303/// use hcl::{Body, Block};
304///
305/// let body = Body::builder()
306/// .add_block(
307/// Block::builder("resource")
308/// .add_label("aws_s3_bucket")
309/// .add_label("mybucket")
310/// .add_attribute(("name", "mybucket"))
311/// .build()
312/// )
313/// .build();
314/// ```
315#[derive(Debug, Default)]
316pub struct BodyBuilder(Vec<Structure>);
317
318impl BodyBuilder {
319 /// Adds an `Attribute` to the body.
320 ///
321 /// Consumes `self` and returns a new `BodyBuilder`.
322 pub fn add_attribute<A>(self, attr: A) -> BodyBuilder
323 where
324 A: Into<Attribute>,
325 {
326 self.add_structure(attr.into())
327 }
328
329 /// Adds `Attribute`s to the body from an iterator.
330 ///
331 /// Consumes `self` and returns a new `BodyBuilder`.
332 pub fn add_attributes<I>(self, iter: I) -> BodyBuilder
333 where
334 I: IntoIterator,
335 I::Item: Into<Attribute>,
336 {
337 self.add_structures(iter.into_iter().map(Into::into))
338 }
339
340 /// Adds a `Block` to the body.
341 ///
342 /// Consumes `self` and returns a new `BodyBuilder`.
343 pub fn add_block<B>(self, block: B) -> BodyBuilder
344 where
345 B: Into<Block>,
346 {
347 self.add_structure(block.into())
348 }
349
350 /// Adds `Block`s to the body from an iterator.
351 ///
352 /// Consumes `self` and returns a new `BodyBuilder`.
353 pub fn add_blocks<I>(self, iter: I) -> BodyBuilder
354 where
355 I: IntoIterator,
356 I::Item: Into<Block>,
357 {
358 self.add_structures(iter.into_iter().map(Into::into))
359 }
360
361 /// Adds a `Structure` to the body.
362 ///
363 /// Consumes `self` and returns a new `BodyBuilder`.
364 pub fn add_structure<S>(mut self, structure: S) -> BodyBuilder
365 where
366 S: Into<Structure>,
367 {
368 self.0.push(structure.into());
369 self
370 }
371
372 /// Adds `Structure`s to the body from an iterator.
373 ///
374 /// Consumes `self` and returns a new `BodyBuilder`.
375 pub fn add_structures<I>(mut self, iter: I) -> BodyBuilder
376 where
377 I: IntoIterator,
378 I::Item: Into<Structure>,
379 {
380 self.0.extend(iter.into_iter().map(Into::into));
381 self
382 }
383
384 /// Consumes `self` and builds the [`Body`] from the structures added via the builder methods.
385 pub fn build(self) -> Body {
386 Body::from_iter(self.0)
387 }
388}