immutable_json/
array.rs

1use crate::api::Number::{Decimal, Integer};
2use crate::api::{Number, Value};
3use crate::error::JsonIndexError;
4use crate::object::Object;
5use imbl::Vector;
6use imbl::shared_ptr::DefaultSharedPtr;
7use imbl::vector::Iter;
8use std::cmp::PartialEq;
9
10#[derive(Clone, Debug)]
11pub struct Array {
12    vec: Vector<Value>,
13}
14
15impl Default for Array {
16    fn default() -> Self {
17        Self::new()
18    }
19}
20
21impl FromIterator<Value> for Array {
22    fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
23        let mut result = Array::new();
24
25        for i in iter {
26            result = result.add(i);
27        }
28
29        result
30    }
31}
32
33impl<'a> IntoIterator for &'a Array {
34    type Item = Value;
35    type IntoIter = ArrayIter<'a>;
36
37    fn into_iter(self) -> ArrayIter<'a> {
38        self.iter()
39    }
40}
41
42impl PartialEq for Array {
43    fn eq(&self, other: &Self) -> bool {
44        self.vec == other.vec
45    }
46}
47
48impl Array {
49    /// Adds a JSON value to an array.
50    /// ```rust
51    /// # use immutable_json::array::Array;
52    /// # use immutable_json::api::Value;
53    /// # fn main() {
54    /// assert_eq!(Some(true), Array::new().add(Value::Bool(true)).get_bool(0).ok().flatten());
55    /// # }
56    /// ```
57    pub fn add(&self, value: Value) -> Self {
58        let mut new_vec = self.vec.clone();
59
60        new_vec.push_back(value);
61        Array { vec: new_vec }
62    }
63
64    /// Adds an array to an array.
65    /// ```rust
66    /// # use immutable_json::array::Array;
67    /// # fn main() {
68    /// assert_eq!(
69    ///     Some(0),
70    ///     Array::new()
71    ///         .add_array(Array::new().add_integer(0))
72    ///         .get_array(0).ok().flatten().and_then(|a| a.get_integer(0).ok().flatten()));
73    /// # }
74    /// ```
75    pub fn add_array(&self, value: Array) -> Self {
76        self.add(Value::Array(value))
77    }
78
79    /// Adds a bool to an array.
80    /// ```rust
81    /// # use immutable_json::array::Array;
82    /// # fn main() {
83    /// assert_eq!(Some(true), Array::new().add_bool(true).get_bool(0).ok().flatten());
84    /// # }
85    /// ```
86    pub fn add_bool(&self, value: bool) -> Self {
87        self.add(Value::Bool(value))
88    }
89
90    /// Adds a decimal to an array.
91    /// ```rust
92    /// # use immutable_json::array::Array;
93    /// # fn main() {
94    /// assert_eq!(Some(2.0), Array::new().add_decimal(2.0).get_decimal(0).ok().flatten());
95    /// # }
96    /// ```
97    pub fn add_decimal(&self, value: f64) -> Self {
98        self.add(Value::Number(Decimal(value)))
99    }
100
101    /// Adds an integer to an array.
102    /// ```rust
103    /// # use immutable_json::array::Array;
104    /// # fn main() {
105    /// assert_eq!(Some(0), Array::new().add_integer(0).get_integer(0).ok().flatten());
106    /// # }
107    /// ```
108    pub fn add_integer(&self, value: i128) -> Self {
109        self.add(Value::Number(Integer(value)))
110    }
111
112    /// Adds a number to an array.
113    /// ```rust
114    /// # use immutable_json::array::Array;
115    /// # use immutable_json::api::Number::Integer;
116    /// # fn main() {
117    /// assert_eq!(
118    ///   Some(Integer(0)),
119    ///   Array::new().add_number(Integer(0)).get_number(0).ok().flatten());
120    /// # }
121    /// ```
122    pub fn add_number(&self, value: Number) -> Self {
123        self.add(Value::Number(value))
124    }
125
126    /// Adds an object to an array.
127    /// ```rust
128    /// # use immutable_json::array::Array;
129    /// # use immutable_json::object::Object;
130    /// # fn main() {
131    /// assert_eq!(
132    ///     Some(0),
133    ///     Array::new()
134    ///         .add_object(Object::new().add_integer("test", 0))
135    ///         .get_object(0).ok().flatten().and_then(|o| o.get_integer("test")));
136    /// # }
137    /// ```
138    pub fn add_object(&self, value: Object) -> Self {
139        self.add(Value::Object(value))
140    }
141
142    /// Adds a string to an array.
143    /// ```rust
144    /// # use immutable_json::array::Array;
145    /// # fn main() {
146    /// assert_eq!(
147    ///     Some("test".to_string()),
148    ///     Array::new().add_string("test").get_string(0).ok().flatten());
149    /// # }
150    /// ```
151    pub fn add_string(&self, value: &str) -> Self {
152        self.add(Value::String(value.to_string()))
153    }
154
155    /// Gets a JSON value from an array at a given index, which is positive and less than the length
156    /// of the array.
157    pub fn get(&self, index: usize) -> Result<Value, JsonIndexError> {
158        self.vec.get(index).cloned().ok_or_else(|| JsonIndexError {
159            index,
160            len: self.len(),
161        })
162    }
163
164    /// Gets an array from an array at a given index, which is positive and less than the length
165    /// of the array.
166    /// ```rust
167    /// # use immutable_json::array::Array;
168    /// # use immutable_json::api::Number::Integer;
169    /// # use immutable_json::error::JsonIndexError;
170    /// # fn main() {
171    /// let array = Array::new().add_number(Integer(0));
172    ///
173    /// assert_eq!(Some(Integer(0)), array.get_number(0).ok().flatten());
174    /// assert_eq!(None, array.get_string(0).ok().flatten());
175    /// assert_eq!(Some(JsonIndexError { index: 1, len: 1, }), array.get_number(1).err());
176    /// # }
177    /// ```
178    pub fn get_array(&self, index: usize) -> Result<Option<Array>, JsonIndexError> {
179        self.get(index).map(|v| v.as_array())
180    }
181
182    /// Gets a bool from an array at a given index, which is positive and less than the length
183    /// of the array.
184    /// ```rust
185    /// # use immutable_json::array::Array;
186    /// # use immutable_json::error::JsonIndexError;
187    /// # fn main() {
188    /// let array = Array::new().add_bool(true);
189    ///
190    /// assert_eq!(Some(true), array.get_bool(0).ok().flatten());
191    /// assert_eq!(None, array.get_string(0).ok().flatten());
192    /// assert_eq!(Some(JsonIndexError { index: 1, len: 1, }), array.get_bool(1).err());
193    /// # }
194    /// ```
195    pub fn get_bool(&self, index: usize) -> Result<Option<bool>, JsonIndexError> {
196        self.get(index).map(|v| v.as_bool())
197    }
198
199    /// Gets a decimal from an array at a given index, which is positive and less than the length
200    /// of the array.
201    /// ```rust
202    /// # use immutable_json::array::Array;
203    /// # use immutable_json::error::JsonIndexError;
204    /// # fn main() {
205    /// let array = Array::new().add_decimal(2.0);
206    ///
207    /// assert_eq!(Some(2.0), array.get_decimal(0).ok().flatten());
208    /// assert_eq!(None, array.get_string(0).ok().flatten());
209    /// assert_eq!(Some(JsonIndexError { index: 1, len: 1, }), array.get_decimal(1).err());
210    /// # }
211    /// ```
212    pub fn get_decimal(&self, index: usize) -> Result<Option<f64>, JsonIndexError> {
213        self.get(index).map(|v| v.as_decimal())
214    }
215
216    /// Gets an integer from an array at a given index, which is positive and less than the length
217    /// of the array.
218    /// ```rust
219    /// # use immutable_json::array::Array;
220    /// # use immutable_json::error::JsonIndexError;
221    /// # fn main() {
222    /// let array = Array::new().add_integer(0);
223    ///
224    /// assert_eq!(Some(0), array.get_integer(0).ok().flatten());
225    /// assert_eq!(None, array.get_string(0).ok().flatten());
226    /// assert_eq!(Some(JsonIndexError { index: 1, len: 1, }), array.get_integer(1).err());
227    /// # }
228    /// ```
229    pub fn get_integer(&self, index: usize) -> Result<Option<i128>, JsonIndexError> {
230        self.get(index).map(|v| v.as_integer())
231    }
232
233    /// Gets a number from an array at a given index, which is positive and less than the length
234    /// of the array.
235    /// ```rust
236    /// # use immutable_json::array::Array;
237    /// # use immutable_json::api::Number::Integer;
238    /// # use immutable_json::error::JsonIndexError;
239    /// # fn main() {
240    /// let array = Array::new().add_number(Integer(0));
241    ///
242    /// assert_eq!(Some(Integer(0)), array.get_number(0).ok().flatten());
243    /// assert_eq!(None, array.get_string(0).ok().flatten());
244    /// assert_eq!(Some(JsonIndexError { index: 1, len: 1, }), array.get_number(1).err());
245    /// # }
246    /// ```
247    pub fn get_number(&self, index: usize) -> Result<Option<Number>, JsonIndexError> {
248        self.get(index).map(|v| v.as_number())
249    }
250
251    /// Gets an object from an array at a given index, which is positive and less than the length
252    /// of the array.
253    /// ```rust
254    /// # use immutable_json::array::Array;
255    /// # use immutable_json::object::Object;
256    /// # use immutable_json::error::JsonIndexError;
257    /// # fn main() {
258    /// let array = Array::new().add_object(Object::new().add_integer("test", 0));
259    ///
260    /// assert_eq!(Some(0),
261    ///     array.get_object(0).ok().flatten().and_then(|o| o.get_integer("test")));
262    /// assert_eq!(None, array.get_string(0).ok().flatten());
263    /// assert_eq!(Some(JsonIndexError { index: 1, len: 1, }), array.get_object(1).err());
264    /// # }
265    /// ```
266    pub fn get_object(&self, index: usize) -> Result<Option<Object>, JsonIndexError> {
267        self.get(index).map(|v| v.as_object())
268    }
269
270    /// Gets a string from an array at a given index, which is positive and less than the length
271    /// of the array.
272    /// ```rust
273    /// # use immutable_json::array::Array;
274    /// # use immutable_json::error::JsonIndexError;
275    /// # fn main() {
276    /// let array = Array::new().add_string("test");
277    ///
278    /// assert_eq!(Some("test".to_string()), array.get_string(0).ok().flatten());
279    /// assert_eq!(None, array.get_integer(0).ok().flatten());
280    /// assert_eq!(Some(JsonIndexError { index: 1, len: 1, }), array.get_string(1).err());
281    /// # }
282    /// ```
283    pub fn get_string(&self, index: usize) -> Result<Option<String>, JsonIndexError> {
284        self.get(index).map(|v| v.as_string())
285    }
286
287    /// Indicates if the array is empty or not.
288    /// ```rust
289    /// # use immutable_json::array::Array;
290    /// # fn main() {
291    /// assert_eq!(true, Array::new().is_empty());
292    /// assert_eq!(false, Array::new().add_integer(0).is_empty());
293    /// # }
294    /// ```
295    pub fn is_empty(&self) -> bool {
296        self.vec.is_empty()
297    }
298
299    /// Returns an iterator over the values of the array.
300    /// ```rust
301    /// # use immutable_json::array::Array;
302    /// # fn main() {
303    /// let array = Array::new().add_string("test").add_integer(1);
304    ///
305    /// assert_eq!(array, Array::from_iter(array.iter()));
306    /// # }
307    /// ```
308    pub fn iter(&'_ self) -> ArrayIter<'_> {
309        ArrayIter {
310            iter: self.vec.iter(),
311        }
312    }
313
314    /// Returns the length of an array.
315    /// ```rust
316    /// # use immutable_json::array::Array;
317    /// # fn main() {
318    /// assert_eq!(0, Array::new().len());
319    /// assert_eq!(1, Array::new().add_integer(0).len());
320    /// # }
321    /// ```
322    pub fn len(&self) -> usize {
323        self.vec.len()
324    }
325
326    pub fn new() -> Self {
327        Array { vec: Vector::new() }
328    }
329
330    /// Removes a JSON value from an array at a given index, which is positive and less than the
331    /// length of the array.
332    /// ```rust
333    /// # use immutable_json::array::Array;
334    /// # use immutable_json::error::JsonIndexError;
335    /// # fn main() {
336    /// assert_eq!(Some(0), Array::new().add_integer(0).remove(0).ok().map(|a| a.len()));
337    /// assert_eq!(Some(JsonIndexError { index: 1, len: 0, }), Array::new().remove(1).err());
338    /// # }
339    /// ```
340    pub fn remove(&self, index: usize) -> Result<Self, JsonIndexError> {
341        if index >= self.len() {
342            Err(JsonIndexError {
343                index,
344                len: self.len(),
345            })
346        } else {
347            let mut new_vec = self.vec.clone();
348
349            new_vec.remove(index);
350            Ok(Array { vec: new_vec })
351        }
352    }
353
354    /// Sets a JSON value in an array at a given index, which is positive and less than the length
355    /// of the array.
356    pub fn set(&self, index: usize, value: Value) -> Result<Self, JsonIndexError> {
357        if index >= self.len() {
358            Err(JsonIndexError {
359                index,
360                len: self.len(),
361            })
362        } else {
363            let mut new_vec = self.vec.clone();
364
365            new_vec.set(index, value);
366            Ok(Array { vec: new_vec })
367        }
368    }
369
370    /// Sets an array in an array at a given index, which is positive and less than the length
371    /// of the array.
372    /// ```rust
373    /// # use immutable_json::array::Array;
374    /// # use immutable_json::error::JsonIndexError;
375    /// # fn main() {
376    /// let array = Array::new().add_bool(true);
377    ///
378    /// assert_eq!(
379    ///     Some(0),
380    ///     array
381    ///       .set_array(0, Array::new().add_integer(0))
382    ///       .ok()
383    ///       .and_then(|a|
384    ///           a.get_array(0).ok().flatten().and_then(|a| a.get_integer(0).ok().flatten())));
385    /// assert_eq!(Some(JsonIndexError { index: 1, len: 1, }), array.set_bool(1, false).err());
386    /// # }
387    /// ```
388    pub fn set_array(&self, index: usize, value: Array) -> Result<Self, JsonIndexError> {
389        self.set(index, Value::Array(value))
390    }
391
392    /// Sets a bool in an array at a given index, which is positive and less than the length
393    /// of the array.
394    /// ```rust
395    /// # use immutable_json::array::Array;
396    /// # use immutable_json::error::JsonIndexError;
397    /// # fn main() {
398    /// let array = Array::new().add_bool(true);
399    ///
400    /// assert_eq!(
401    ///     Some(false),
402    ///     array
403    ///       .set_bool(0, false)
404    ///       .ok()
405    ///       .and_then(|a| a.get_bool(0).ok().flatten()));
406    /// assert_eq!(Some(JsonIndexError { index: 1, len: 1, }), array.set_bool(1, false).err());
407    /// # }
408    /// ```
409    pub fn set_bool(&self, index: usize, value: bool) -> Result<Self, JsonIndexError> {
410        self.set(index, Value::Bool(value))
411    }
412
413    /// Sets a decimal in an array at a given index, which is positive and less than the length
414    /// of the array.
415    /// ```rust
416    /// # use immutable_json::array::Array;
417    /// # use immutable_json::error::JsonIndexError;
418    /// # fn main() {
419    /// let array = Array::new().add_bool(true);
420    ///
421    /// assert_eq!(
422    ///     Some(3.0),
423    ///     array
424    ///       .set_decimal(0, 3.0)
425    ///       .ok()
426    ///       .and_then(|a| a.get_decimal(0).ok().flatten()));
427    /// assert_eq!(Some(JsonIndexError { index: 1, len: 1, }), array.set_decimal(1, 1.0).err());
428    /// # }
429    /// ```
430    pub fn set_decimal(&self, index: usize, value: f64) -> Result<Self, JsonIndexError> {
431        self.set(index, Value::Number(Decimal(value)))
432    }
433
434    /// Sets an integer in an array at a given index, which is positive and less than the length
435    /// of the array.
436    /// ```rust
437    /// # use immutable_json::array::Array;
438    /// # use immutable_json::error::JsonIndexError;
439    /// # fn main() {
440    /// let array = Array::new().add_bool(true);
441    ///
442    /// assert_eq!(
443    ///     Some(3),
444    ///     array
445    ///       .set_integer(0, 3)
446    ///       .ok()
447    ///       .and_then(|a| a.get_integer(0).ok().flatten()));
448    /// assert_eq!(Some(JsonIndexError { index: 1, len: 1, }), array.set_integer(1, 1).err());
449    /// # }
450    /// ```
451    pub fn set_integer(&self, index: usize, value: i128) -> Result<Self, JsonIndexError> {
452        self.set(index, Value::Number(Integer(value)))
453    }
454
455    /// Sets a number in an array at a given index, which is positive and less than the length
456    /// of the array.
457    /// ```rust
458    /// # use immutable_json::array::Array;
459    /// # use immutable_json::api::Number::Decimal;
460    /// # use immutable_json::error::JsonIndexError;
461    /// # fn main() {
462    /// let array = Array::new().add_bool(true);
463    ///
464    /// assert_eq!(
465    ///     Some(Decimal(3.0)),
466    ///     array
467    ///       .set_number(0, Decimal(3.0))
468    ///       .ok()
469    ///       .and_then(|a| a.get_number(0).ok().flatten()));
470    /// assert_eq!(
471    ///     Some(JsonIndexError { index: 1, len: 1, }),
472    ///     array.set_number(1, Decimal(1.0)).err());
473    /// # }
474    /// ```
475    pub fn set_number(&self, index: usize, value: Number) -> Result<Self, JsonIndexError> {
476        self.set(index, Value::Number(value))
477    }
478
479    /// Sets an object in an array at a given index, which is positive and less than the length
480    /// of the array.
481    /// ```rust
482    /// # use immutable_json::array::Array;
483    /// # use immutable_json::object::Object;
484    /// # use immutable_json::error::JsonIndexError;
485    /// # fn main() {
486    /// let array = Array::new().add_bool(true);
487    ///
488    /// assert_eq!(
489    ///     Some("test".to_string()),
490    ///     array
491    ///       .set_object(0, Object::new().add_string("test", "test"))
492    ///       .ok()
493    ///       .and_then(|a| a.get_object(0).ok().flatten().and_then(|o| o.get_string("test"))));
494    /// assert_eq!(
495    ///     Some(JsonIndexError { index: 1, len: 1, }),
496    ///     array.set_object(1, Object::new()).err());
497    /// # }
498    /// ```
499    pub fn set_object(&self, index: usize, value: Object) -> Result<Self, JsonIndexError> {
500        self.set(index, Value::Object(value))
501    }
502
503    /// Sets a string in an array at a given index, which is positive and less than the length
504    /// of the array.
505    /// ```rust
506    /// # use immutable_json::array::Array;
507    /// # use immutable_json::error::JsonIndexError;
508    /// # fn main() {
509    /// let array = Array::new().add_bool(true);
510    ///
511    /// assert_eq!(
512    ///     Some("test".to_string()),
513    ///     array
514    ///       .set_string(0, "test")
515    ///       .ok()
516    ///       .and_then(|a| a.get_string(0).ok().flatten()));
517    /// assert_eq!(Some(JsonIndexError { index: 1, len: 1, }), array.set_string(1, "test").err());
518    /// # }
519    /// ```
520    pub fn set_string(&self, index: usize, value: &str) -> Result<Self, JsonIndexError> {
521        self.set(index, Value::String(value.to_string()))
522    }
523}
524
525#[derive(Clone)]
526pub struct ArrayIter<'a> {
527    iter: Iter<'a, Value, DefaultSharedPtr>,
528}
529
530impl<'a> Iterator for ArrayIter<'a> {
531    type Item = Value;
532
533    fn next(&mut self) -> Option<Self::Item> {
534        self.iter.next().cloned()
535    }
536}