immutable_json/object.rs
1use crate::api::{Number, Value};
2use crate::array::Array;
3use imbl::HashMap;
4use imbl::hashmap::Iter;
5use imbl::shared_ptr::DefaultSharedPtr;
6use crate::api::Number::{Decimal, Integer};
7
8#[derive(Clone, Debug)]
9pub struct Object {
10 map: HashMap<String, Value>,
11}
12
13impl Default for Object {
14 fn default() -> Self {
15 Self::new()
16 }
17}
18
19impl FromIterator<(String, Value)> for Object {
20 fn from_iter<T: IntoIterator<Item = (String, Value)>>(iter: T) -> Self {
21 let mut result = Object::new();
22
23 for i in iter {
24 result = result.add(&i.0, i.1);
25 }
26
27 result
28 }
29}
30
31impl<'a> IntoIterator for &'a Object {
32 type Item = (String, Value);
33 type IntoIter = ObjectIter<'a>;
34
35 fn into_iter(self) -> ObjectIter<'a> {
36 self.iter()
37 }
38}
39
40impl PartialEq for Object {
41 fn eq(&self, other: &Self) -> bool {
42 self.map == other.map
43 }
44}
45
46impl Object {
47 /// Adds a field to an object.
48 /// ```rust
49 /// # use immutable_json::api::Value::String;
50 /// # use immutable_json::object::Object;
51 /// # fn main() {
52 /// assert_eq!(Some("test".to_string()),
53 /// Object::new().add("test", String("test".to_string())).get_string("test"));
54 /// # }
55 /// ```
56 pub fn add(&self, key: &str, value: Value) -> Self {
57 let mut new_map = self.map.clone();
58
59 new_map.insert(key.to_string(), value);
60 Object { map: new_map }
61 }
62
63 /// Adds a field to an object as an array.
64 /// ```rust
65 /// # use immutable_json::array::Array;
66 /// # use immutable_json::object::Object;
67 /// # fn main() {
68 /// assert_eq!(Some(1),
69 /// Object::new()
70 /// .add_array("test", Array::new().add_integer(1))
71 /// .get_array("test").and_then(|a| a.get_integer(0).ok()?));
72 /// # }
73 /// ```
74 pub fn add_array(&self, key: &str, value: Array) -> Self {
75 self.add(key, Value::Array(value))
76 }
77
78 /// Adds a field to an object as a bool.
79 /// ```rust
80 /// # use immutable_json::object::Object;
81 /// # fn main() {
82 /// assert_eq!(Some(true), Object::new().add_bool("test", true).get_bool("test"));
83 /// # }
84 /// ```
85 pub fn add_bool(&self, key: &str, value: bool) -> Self {
86 self.add(key, Value::Bool(value))
87 }
88
89 /// Adds a field to an object as a decimal.
90 /// ```rust
91 /// # use immutable_json::object::Object;
92 /// # fn main() {
93 /// assert_eq!(Some(3.0), Object::new().add_decimal("test", 3.0).get_decimal("test"));
94 /// # }
95 /// ```
96 pub fn add_decimal(&self, key: &str, value: f64) -> Self {
97 self.add(key, Value::Number(Decimal(value)))
98 }
99
100 /// Adds a field to an object as an integer.
101 /// ```rust
102 /// # use immutable_json::object::Object;
103 /// # fn main() {
104 /// assert_eq!(Some(3), Object::new().add_integer("test", 3).get_integer("test"));
105 /// # }
106 /// ```
107 pub fn add_integer(&self, key: &str, value: i128) -> Self {
108 self.add(key, Value::Number(Integer(value)))
109 }
110
111 /// Adds a field to an object as a number.
112 /// ```rust
113 /// # use immutable_json::object::Object;
114 /// # use immutable_json::api::Number::Integer;
115 /// # fn main() {
116 /// assert_eq!(Some(3),
117 /// Object::new()
118 /// .add_number("test", Integer(3))
119 /// .get_number("test").and_then(|n| n.as_integer()));
120 /// # }
121 /// ```
122 pub fn add_number(&self, key: &str, value: Number) -> Self {
123 self.add(key, Value::Number(value))
124 }
125
126 /// Adds a field to an object as an object.
127 /// ```rust
128 /// # use immutable_json::object::Object;
129 /// # use immutable_json::api::Number::Integer;
130 /// # fn main() {
131 /// assert_eq!(Some(1),
132 /// Object::new()
133 /// .add_object("test", Object::new().add_integer("test", 1))
134 /// .get_object("test").and_then(|o| o.get_integer("test")));
135 /// # }
136 /// ```
137 pub fn add_object(&self, key: &str, value: Object) -> Self {
138 self.add(key, Value::Object(value))
139 }
140
141 /// Adds a field to an object as an integer.
142 /// ```rust
143 /// # use immutable_json::object::Object;
144 /// # fn main() {
145 /// assert_eq!(Some("test".to_string()),
146 /// Object::new().add_string("test", "test").get_string("test"));
147 /// # }
148 /// ```
149 pub fn add_string(&self, key: &str, value: &str) -> Self {
150 self.add(key, Value::String(value.to_string()))
151 }
152
153 /// Returns a value from the object if it exists at the given key.
154 /// ```rust
155 /// # use immutable_json::object::Object;
156 /// # fn main() {
157 /// let object = Object::new().add_string("test1", "test");
158 ///
159 /// assert_eq!(Some("test".to_string()), object.get_string("test1"));
160 /// assert_eq!(None, object.get_string("test2"));
161 /// # }
162 /// ```
163 pub fn get(&self, key: &str) -> Option<&Value> {
164 self.map.get(&key.to_string())
165 }
166
167 /// Returns a value from the object if it exists at the given key and if it is an array.
168 /// ```rust
169 /// # use immutable_json::array::Array;
170 /// # use immutable_json::object::Object;
171 /// # fn main() {
172 /// let object = Object::new()
173 /// .add_array("test1", Array::new().add_integer(3))
174 /// .add_integer("test2", 3);
175 ///
176 /// assert_eq!(Some(3), object.get_array("test1").and_then(|a| a.get_integer(0).ok()?));
177 /// assert_eq!(None, object.get_array("test2"));
178 /// # }
179 /// ```
180 pub fn get_array(&self, key: &str) -> Option<Array> {
181 self.get(key).and_then(|v| v.as_array())
182 }
183
184 /// Returns a value from the object if it exists at the given key and if it is a bool.
185 /// ```rust
186 /// # use immutable_json::object::Object;
187 /// # fn main() {
188 /// let object = Object::new()
189 /// .add_bool("test1", true)
190 /// .add_integer("test2", 3);
191 ///
192 /// assert_eq!(Some(true), object.get_bool("test1"));
193 /// assert_eq!(None, object.get_string("test2"));
194 /// # }
195 /// ```
196 pub fn get_bool(&self, key: &str) -> Option<bool> {
197 self.get(key).and_then(|v| v.as_bool())
198 }
199
200 /// Returns a value from the object if it exists at the given key and if it is a decimal.
201 /// ```rust
202 /// # use immutable_json::object::Object;
203 /// # fn main() {
204 /// let object = Object::new()
205 /// .add_decimal("test1", 3.0)
206 /// .add_integer("test2", 3);
207 ///
208 /// assert_eq!(Some(3.0), object.get_decimal("test1"));
209 /// assert_eq!(None, object.get_string("test2"));
210 /// # }
211 /// ```
212 pub fn get_decimal(&self, key: &str) -> Option<f64> {
213 self.get(key).and_then(|v| v.as_decimal())
214 }
215
216 /// Returns a value from the object if it exists at the given key and if it is an integer.
217 /// ```rust
218 /// # use immutable_json::object::Object;
219 /// # fn main() {
220 /// let object = Object::new()
221 /// .add_decimal("test1", 3.0)
222 /// .add_integer("test2", 3);
223 ///
224 /// assert_eq!(Some(3.0), object.get_decimal("test1"));
225 /// assert_eq!(None, object.get_string("test2"));
226 /// # }
227 /// ```
228 pub fn get_integer(&self, key: &str) -> Option<i128> {
229 self.get(key).and_then(|v| v.as_integer())
230 }
231
232 /// Returns a value from the object if it exists at the given key and if it is a number.
233 /// ```rust
234 /// # use immutable_json::api::Number;
235 /// # use immutable_json::object::Object;
236 /// # fn main() {
237 /// let object = Object::new()
238 /// .add_number("test1", Number::Decimal(3.0))
239 /// .add_integer("test2", 3);
240 ///
241 /// assert_eq!(Some(3.0), object.get_number("test1").and_then(|n| n.as_decimal()));
242 /// assert_eq!(None, object.get_string("test2"));
243 /// # }
244 /// ```
245 pub fn get_number(&self, key: &str) -> Option<Number> {
246 self.get(key).and_then(|v| v.as_number())
247 }
248
249 /// Returns a value from the object if it exists at the given key and if it is an object.
250 /// ```rust
251 /// # use immutable_json::object::Object;
252 /// # fn main() {
253 /// let object = Object::new()
254 /// .add_object("test1", Object::new().add_integer("test", 3))
255 /// .add_integer("test2", 3);
256 ///
257 /// assert_eq!(Some(3), object.get_object("test1").and_then(|a| a.get_integer("test")));
258 /// assert_eq!(None, object.get_array("test2"));
259 /// # }
260 /// ```
261 pub fn get_object(&self, key: &str) -> Option<Object> {
262 self.get(key).and_then(|v| v.as_object())
263 }
264
265 /// Returns a value from the object if it exists at the given key and if it is a string.
266 /// ```rust
267 /// # use immutable_json::object::Object;
268 /// # fn main() {
269 /// let object = Object::new()
270 /// .add_string("test1", "test")
271 /// .add_integer("test2", 3);
272 ///
273 /// assert_eq!(Some("test".to_string()), object.get_string("test1"));
274 /// assert_eq!(None, object.get_string("test2"));
275 /// # }
276 /// ```
277 pub fn get_string(&self, key: &str) -> Option<String> {
278 self.get(key).and_then(|v| v.as_string())
279 }
280
281 /// Returns `true` if the object has a field with the given key.
282 /// ```rust
283 /// # use immutable_json::object::Object;
284 /// # fn main() {
285 /// let object = Object::new().add_string("test1", "test");
286 ///
287 /// assert_eq!(true, object.has_key("test1"));
288 /// assert_eq!(false, object.has_key("test2"));
289 /// # }
290 /// ```
291 pub fn has_key(&self, key: &str) -> bool {
292 self.map.contains_key(&key.to_string())
293 }
294
295 /// Returns an iterator over the key/value tuples of the object.
296 /// ```rust
297 /// # use immutable_json::object::Object;
298 /// # fn main() {
299 /// let object = Object::new().add_string("test1", "test1").add_integer("test2", 1);
300 ///
301 /// assert_eq!(object, Object::from_iter(object.iter()));
302 /// # }
303 /// ```
304 pub fn iter(&'_ self) -> ObjectIter<'_> {
305 ObjectIter {
306 iter: self.map.iter(),
307 }
308 }
309
310 pub fn new() -> Self {
311 Object {
312 map: HashMap::new(),
313 }
314 }
315
316 /// Removes the field with the given key from the object.
317 /// ```rust
318 /// # use immutable_json::object::Object;
319 /// # fn main() {
320 /// let object = Object::new().add_string("test", "test");
321 ///
322 /// assert_eq!(true, object.has_key("test"));
323 /// assert_eq!(false, object.remove("test").has_key("test"));
324 /// # }
325 /// ```
326 pub fn remove(&self, key: &str) -> Self {
327 let mut new_map = self.map.clone();
328
329 new_map.remove(&key.to_string());
330 Object { map: new_map }
331 }
332}
333
334#[derive(Clone)]
335pub struct ObjectIter<'a> {
336 iter: Iter<'a, String, Value, DefaultSharedPtr>,
337}
338
339impl<'a> Iterator for ObjectIter<'a> {
340 type Item = (String, Value);
341
342 fn next(&mut self) -> Option<Self::Item> {
343 self.iter.next().map(|i| (i.0.clone(), i.1.clone()))
344 }
345}