aws_smithy_types/
document.rs1use crate::Number;
7use std::borrow::Cow;
8use std::collections::HashMap;
9
10#[cfg(any(
11    all(aws_sdk_unstable, feature = "serde-deserialize"),
12    all(aws_sdk_unstable, feature = "serde-serialize")
13))]
14use serde;
15
16#[derive(Clone, Debug, PartialEq)]
25#[cfg_attr(
26    all(aws_sdk_unstable, feature = "serde-serialize"),
27    derive(serde::Serialize)
28)]
29#[cfg_attr(
30    all(aws_sdk_unstable, feature = "serde-deserialize"),
31    derive(serde::Deserialize)
32)]
33#[cfg_attr(
34    any(
35        all(aws_sdk_unstable, feature = "serde-deserialize"),
36        all(aws_sdk_unstable, feature = "serde-serialize")
37    ),
38    serde(untagged)
39)]
40pub enum Document {
41    Object(HashMap<String, Document>),
43    Array(Vec<Document>),
45    Number(Number),
47    String(String),
49    Bool(bool),
51    Null,
53}
54
55impl Document {
56    pub fn as_object(&self) -> Option<&HashMap<String, Document>> {
58        if let Self::Object(object) = self {
59            Some(object)
60        } else {
61            None
62        }
63    }
64
65    pub fn as_object_mut(&mut self) -> Option<&mut HashMap<String, Document>> {
67        if let Self::Object(object) = self {
68            Some(object)
69        } else {
70            None
71        }
72    }
73
74    pub fn as_array(&self) -> Option<&Vec<Document>> {
76        if let Self::Array(array) = self {
77            Some(array)
78        } else {
79            None
80        }
81    }
82
83    pub fn as_array_mut(&mut self) -> Option<&mut Vec<Document>> {
85        if let Self::Array(array) = self {
86            Some(array)
87        } else {
88            None
89        }
90    }
91
92    pub fn as_number(&self) -> Option<&Number> {
94        if let Self::Number(number) = self {
95            Some(number)
96        } else {
97            None
98        }
99    }
100
101    pub fn as_string(&self) -> Option<&str> {
103        if let Self::String(string) = self {
104            Some(string)
105        } else {
106            None
107        }
108    }
109
110    pub fn as_bool(&self) -> Option<bool> {
112        if let Self::Bool(boolean) = self {
113            Some(*boolean)
114        } else {
115            None
116        }
117    }
118
119    pub fn as_null(&self) -> Option<()> {
121        if let Self::Null = self {
122            Some(())
123        } else {
124            None
125        }
126    }
127
128    pub fn is_object(&self) -> bool {
130        matches!(self, Self::Object(_))
131    }
132
133    pub fn is_array(&self) -> bool {
135        matches!(self, Self::Array(_))
136    }
137
138    pub fn is_number(&self) -> bool {
140        matches!(self, Self::Number(_))
141    }
142
143    pub fn is_string(&self) -> bool {
145        matches!(self, Self::String(_))
146    }
147
148    pub fn is_bool(&self) -> bool {
150        matches!(self, Self::Bool(_))
151    }
152
153    pub fn is_null(&self) -> bool {
155        matches!(self, Self::Null)
156    }
157}
158
159impl Default for Document {
161    fn default() -> Self {
162        Self::Null
163    }
164}
165
166impl From<bool> for Document {
167    fn from(value: bool) -> Self {
168        Document::Bool(value)
169    }
170}
171
172impl<'a> From<&'a str> for Document {
173    fn from(value: &'a str) -> Self {
174        Document::String(value.to_string())
175    }
176}
177
178impl<'a> From<Cow<'a, str>> for Document {
179    fn from(value: Cow<'a, str>) -> Self {
180        Document::String(value.into_owned())
181    }
182}
183
184impl From<String> for Document {
185    fn from(value: String) -> Self {
186        Document::String(value)
187    }
188}
189
190impl From<Vec<Document>> for Document {
191    fn from(values: Vec<Document>) -> Self {
192        Document::Array(values)
193    }
194}
195
196impl From<HashMap<String, Document>> for Document {
197    fn from(values: HashMap<String, Document>) -> Self {
198        Document::Object(values)
199    }
200}
201
202impl From<u64> for Document {
203    fn from(value: u64) -> Self {
204        Document::Number(Number::PosInt(value))
205    }
206}
207
208impl From<i64> for Document {
209    fn from(value: i64) -> Self {
210        Document::Number(Number::NegInt(value))
211    }
212}
213
214impl From<i32> for Document {
215    fn from(value: i32) -> Self {
216        Document::Number(Number::NegInt(value as i64))
217    }
218}
219
220impl From<f64> for Document {
221    fn from(value: f64) -> Self {
222        Document::Number(Number::Float(value))
223    }
224}
225
226impl From<Number> for Document {
227    fn from(value: Number) -> Self {
228        Document::Number(value)
229    }
230}
231
232#[cfg(test)]
235mod test {
236    #[test]
238    #[cfg(all(
239        aws_sdk_unstable,
240        feature = "serde-serialize",
241        feature = "serde-deserialize"
242    ))]
243    fn serialize_json() {
244        use crate::Document;
245        use crate::Number;
246        use std::collections::HashMap;
247        let mut map: HashMap<String, Document> = HashMap::new();
248        map.insert("hello".into(), "world".to_string().into());
250        map.insert("pos_int".into(), Document::Number(Number::PosInt(1).into()));
252        map.insert(
253            "neg_int".into(),
254            Document::Number(Number::NegInt(-1).into()),
255        );
256        map.insert(
257            "float".into(),
258            Document::Number(Number::Float(0.1 + 0.2).into()),
259        );
260        map.insert("true".into(), true.into());
262        map.insert("false".into(), false.into());
263        map.insert(
265            "array".into(),
266            vec![
267                map.clone().into(),
268                "hello-world".to_string().into(),
269                true.into(),
270                false.into(),
271            ]
272            .into(),
273        );
274        map.insert("map".into(), map.clone().into());
276        map.insert("null".into(), Document::Null);
278        let obj = Document::Object(map);
279        let target_file = include_str!("../test_data/serialize_document.json");
281        let json: Result<serde_json::Value, _> = serde_json::from_str(target_file);
282        assert_eq!(serde_json::to_value(&obj).unwrap(), json.unwrap());
284        let doc: Result<Document, _> = serde_json::from_str(target_file);
285        assert_eq!(obj, doc.unwrap());
286    }
287}