hcl/structure/
de.rs

1//! Deserialize impls for HCL structure types.
2
3use 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}