1use super::{Attribute, Block, BlockLabel, Body, Structure};
4use crate::de::NewtypeStructDeserializer;
5use crate::expr::Expression;
6use crate::{Error, Identifier, Result};
7use serde::de::{self, IntoDeserializer};
8use serde::forward_to_deserialize_any;
9
10impl IntoDeserializer<'_, Error> for Body {
11 type Deserializer = NewtypeStructDeserializer<Vec<Structure>>;
12
13 fn into_deserializer(self) -> Self::Deserializer {
14 NewtypeStructDeserializer::new(self.into_inner())
15 }
16}
17
18impl IntoDeserializer<'_, Error> for Structure {
19 type Deserializer = Self;
20
21 fn into_deserializer(self) -> Self::Deserializer {
22 self
23 }
24}
25
26impl<'de> de::Deserializer<'de> for Structure {
27 type Error = Error;
28
29 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
30 where
31 V: de::Visitor<'de>,
32 {
33 match self {
34 Structure::Attribute(attribute) => visitor.visit_map(AttributeAccess::new(attribute)),
35 Structure::Block(block) => visitor.visit_map(BlockAccess::new(block)),
36 }
37 }
38
39 impl_deserialize_enum!();
40
41 forward_to_deserialize_any! {
42 bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str
43 string bytes byte_buf option unit unit_struct newtype_struct seq
44 tuple tuple_struct map struct identifier ignored_any
45 }
46}
47
48pub struct AttributeAccess {
49 key: Option<Identifier>,
50 expr: Option<Expression>,
51}
52
53impl AttributeAccess {
54 fn new(attr: Attribute) -> Self {
55 AttributeAccess {
56 key: Some(attr.key),
57 expr: Some(attr.expr),
58 }
59 }
60}
61
62impl<'de> de::MapAccess<'de> for AttributeAccess {
63 type Error = Error;
64
65 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
66 where
67 K: de::DeserializeSeed<'de>,
68 {
69 if self.key.is_some() {
70 seed.deserialize("key".into_deserializer()).map(Some)
71 } else if self.expr.is_some() {
72 seed.deserialize("expr".into_deserializer()).map(Some)
73 } else {
74 Ok(None)
75 }
76 }
77
78 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
79 where
80 V: de::DeserializeSeed<'de>,
81 {
82 if let Some(key) = self.key.take() {
83 seed.deserialize(key.into_deserializer())
84 } else if let Some(expr) = self.expr.take() {
85 seed.deserialize(expr.into_deserializer())
86 } else {
87 Err(de::Error::custom("invalid HCL attribute"))
88 }
89 }
90}
91
92pub struct BlockAccess {
93 identifier: Option<Identifier>,
94 labels: Option<Vec<BlockLabel>>,
95 body: Option<Body>,
96}
97
98impl BlockAccess {
99 fn new(block: Block) -> Self {
100 BlockAccess {
101 identifier: Some(block.identifier),
102 labels: Some(block.labels),
103 body: Some(block.body),
104 }
105 }
106}
107
108impl<'de> de::MapAccess<'de> for BlockAccess {
109 type Error = Error;
110
111 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
112 where
113 K: de::DeserializeSeed<'de>,
114 {
115 if self.identifier.is_some() {
116 seed.deserialize("identifier".into_deserializer()).map(Some)
117 } else if self.labels.is_some() {
118 seed.deserialize("labels".into_deserializer()).map(Some)
119 } else if self.body.is_some() {
120 seed.deserialize("body".into_deserializer()).map(Some)
121 } else {
122 Ok(None)
123 }
124 }
125
126 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
127 where
128 V: de::DeserializeSeed<'de>,
129 {
130 if let Some(identifier) = self.identifier.take() {
131 seed.deserialize(identifier.into_deserializer())
132 } else if let Some(labels) = self.labels.take() {
133 seed.deserialize(labels.into_deserializer())
134 } else if let Some(body) = self.body.take() {
135 seed.deserialize(body.into_deserializer())
136 } else {
137 Err(de::Error::custom("invalid HCL block"))
138 }
139 }
140}
141
142impl IntoDeserializer<'_, Error> for BlockLabel {
143 type Deserializer = Self;
144
145 fn into_deserializer(self) -> Self::Deserializer {
146 self
147 }
148}
149
150impl<'de> de::Deserializer<'de> for BlockLabel {
151 type Error = Error;
152
153 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
154 where
155 V: de::Visitor<'de>,
156 {
157 match self {
158 BlockLabel::String(string) => visitor.visit_string(string),
159 BlockLabel::Identifier(ident) => visitor.visit_string(ident.into_inner()),
160 }
161 }
162
163 impl_deserialize_enum!();
164
165 forward_to_deserialize_any! {
166 bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str
167 string bytes byte_buf option unit unit_struct newtype_struct seq
168 tuple tuple_struct map struct identifier ignored_any
169 }
170}
171
172impl_variant_name! {
173 BlockLabel => { String, Identifier },
174 Structure => { Attribute, Block }
175}
176
177impl_into_map_access_deserializer! {
178 Attribute => AttributeAccess,
179 Block => BlockAccess
180}