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}