hcl/structure/mod.rs
1//! Types to represent the HCL structural sub-language.
2//!
3//! The main types in this module are:
4//!
5//! - [`Attribute`]: represent an HCL attribute
6//! - [`Block`]: represent an HCL block
7//! - [`BlockBuilder`]: provides functionality for building `Block`s
8//! - [`Body`]: represent the body of an HCL configuration or block
9//! - [`BodyBuilder`]: provides functionality for building `Body`s
10//!
11//! ## Examples
12//!
13//! Building HCL structures:
14//!
15//! ```
16//! use hcl::{Body, Block, BlockLabel};
17//!
18//! let body = Body::builder()
19//! .add_block(
20//! Block::builder("resource")
21//! .add_label("aws_s3_bucket")
22//! .add_label("mybucket")
23//! .add_attribute(("name", "mybucket"))
24//! .add_block(
25//! Block::builder("logging")
26//! .add_attribute(("target_bucket", "mylogsbucket"))
27//! .build()
28//! )
29//! .build()
30//! )
31//! .build();
32//!
33//! let mut iter = body.attributes();
34//!
35//! assert_eq!(iter.next(), None);
36//!
37//! let mut iter = body.blocks();
38//!
39//! let block = iter.next().unwrap();
40//!
41//! assert_eq!(block.identifier(), "resource");
42//! assert_eq!(
43//! block.labels().first(),
44//! Some(&BlockLabel::from("aws_s3_bucket")),
45//! );
46//! ```
47
48mod attribute;
49mod block;
50mod body;
51pub(crate) mod de;
52mod edit;
53pub mod iter;
54mod json_spec;
55mod ser;
56#[cfg(test)]
57mod tests;
58
59pub(crate) use self::json_spec::IntoJsonSpec;
60pub use self::{
61 attribute::Attribute,
62 block::{Block, BlockBuilder, BlockLabel},
63 body::{Body, BodyBuilder},
64};
65use crate::Value;
66use serde::Deserialize;
67
68/// Represents an HCL structure.
69///
70/// There are two possible structures that can occur in an HCL [`Body`]: [`Attribute`]s and [`Block`]s.
71#[derive(Deserialize, Debug, PartialEq, Eq, Clone)]
72pub enum Structure {
73 /// Represents an HCL attribute.
74 Attribute(Attribute),
75 /// Represents an HCL block.
76 Block(Block),
77}
78
79impl Structure {
80 /// Returns `true` if the structure represents an [`Attribute`].
81 pub fn is_attribute(&self) -> bool {
82 self.as_attribute().is_some()
83 }
84
85 /// Returns `true` if the structure represents a [`Block`].
86 pub fn is_block(&self) -> bool {
87 self.as_block().is_some()
88 }
89
90 /// Takes ownership of the `Structure` and, if it is an `Attribute`, returns its value,
91 /// otherwise `None`.
92 pub fn into_attribute(self) -> Option<Attribute> {
93 match self {
94 Structure::Attribute(attr) => Some(attr),
95 Structure::Block(_) => None,
96 }
97 }
98
99 /// If the `Structure` is an `Attribute`, returns a reference to it, otherwise `None`.
100 pub fn as_attribute(&self) -> Option<&Attribute> {
101 match self {
102 Structure::Attribute(attr) => Some(attr),
103 Structure::Block(_) => None,
104 }
105 }
106
107 /// If the `Structure` is an `Attribute`, returns a mutable reference to it, otherwise `None`.
108 pub fn as_attribute_mut(&mut self) -> Option<&mut Attribute> {
109 match self {
110 Structure::Attribute(attr) => Some(attr),
111 Structure::Block(_) => None,
112 }
113 }
114
115 /// Takes ownership of the `Structure` and, if it is a `Block`, returns its value,
116 /// otherwise `None`.
117 pub fn into_block(self) -> Option<Block> {
118 match self {
119 Structure::Block(block) => Some(block),
120 Structure::Attribute(_) => None,
121 }
122 }
123
124 /// If the `Structure` is a `Block`, returns a reference to it, otherwise `None`.
125 pub fn as_block(&self) -> Option<&Block> {
126 match self {
127 Structure::Block(block) => Some(block),
128 Structure::Attribute(_) => None,
129 }
130 }
131
132 /// If the `Structure` is a `Block`, returns a mutable reference to it, otherwise `None`.
133 pub fn as_block_mut(&mut self) -> Option<&mut Block> {
134 match self {
135 Structure::Block(block) => Some(block),
136 Structure::Attribute(_) => None,
137 }
138 }
139}
140
141impl From<Structure> for Value {
142 fn from(s: Structure) -> Value {
143 match s {
144 Structure::Attribute(attr) => attr.into(),
145 Structure::Block(block) => block.into(),
146 }
147 }
148}
149
150impl From<Attribute> for Structure {
151 fn from(attr: Attribute) -> Structure {
152 Structure::Attribute(attr)
153 }
154}
155
156impl From<Block> for Structure {
157 fn from(block: Block) -> Structure {
158 Structure::Block(block)
159 }
160}