justjson/
value.rs

1#[cfg(feature = "alloc")]
2use alloc::{string::String, vec::Vec};
3use core::convert::Infallible;
4use core::fmt::{self, Display};
5use core::ops::{Deref, DerefMut, Index, IndexMut};
6
7use crate::parser::{JsonKind, ParseConfig, ParseDelegate, Parser};
8use crate::{Error, JsonNumber, JsonString};
9
10/// A JSON value.
11///
12/// The `Backing` generic is the storage mechanism used by [`JsonNumber`] and
13/// [`JsonString`]. This is generally `&str` or `Cow<str>`.
14#[derive(Debug, Eq, PartialEq)]
15pub enum Value<'a> {
16    /// A JSON number.
17    Number(JsonNumber<'a>),
18    /// A JSON string.
19    String(JsonString<'a>),
20    /// A boolean value.
21    Boolean(bool),
22    /// A JSON object (key/value pairs).
23    Object(Object<'a>),
24    /// A JSON array (list of values).
25    Array(Vec<Value<'a>>),
26    /// A null value.
27    Null,
28}
29
30impl<'a> Value<'a> {
31    /// Parses a JSON value from `json`, returning a `Value<&str>` that borrows
32    /// data from `json`.
33    ///
34    /// Because the `str` type guarantees that `json` is valid UTF-8, no
35    /// additional unicode checks are performed on unescaped unicode sequences.
36    pub fn from_json(json: &'a str) -> Result<Self, Error> {
37        Self::from_json_with_config(json, ParseConfig::default())
38    }
39
40    /// Parses a JSON value from `json` using the settings from`config`,
41    /// returning a `Value<&str>` that borrows data from `json`.
42    ///
43    /// Because the `str` type guarantees that `json` is valid UTF-8, no
44    /// additional unicode checks are performed on unescaped unicode sequences.
45    pub fn from_json_with_config(json: &'a str, config: ParseConfig) -> Result<Self, Error> {
46        Parser::parse_json_with_config(json, config, ValueParser)
47    }
48
49    /// Parses a JSON value from `json`, returning a `Value<&str>` that borrows
50    /// data from `json`.
51    ///
52    /// This function verifies that `json` is valid UTF-8 while parsing the
53    /// JSON.
54    pub fn from_json_bytes(json: &'a [u8]) -> Result<Self, Error> {
55        Self::from_json_bytes_with_config(json, ParseConfig::default())
56    }
57
58    /// Parses a JSON value from `json` using the settings from`config`,
59    /// returning a `Value<&str>` that borrows data from `json`.
60    ///
61    /// This function verifies that `json` is valid UTF-8 while parsing the
62    /// JSON.
63    pub fn from_json_bytes_with_config(json: &'a [u8], config: ParseConfig) -> Result<Self, Error> {
64        Parser::parse_json_bytes_with_config(json, config, ValueParser)
65    }
66
67    /// Returns the [`Object`] inside of this value, if this is a
68    /// [`Value::Object`].
69    #[must_use]
70    #[inline]
71    pub const fn as_object(&self) -> Option<&Object<'a>> {
72        if let Self::Object(obj) = self {
73            Some(obj)
74        } else {
75            None
76        }
77    }
78
79    /// Returns a mutable reference to the [`Object`] inside of this value, if
80    /// this is a [`Value::Object`].
81    #[must_use]
82    #[inline]
83    pub fn as_object_mut(&mut self) -> Option<&mut Object<'a>> {
84        if let Self::Object(obj) = self {
85            Some(obj)
86        } else {
87            None
88        }
89    }
90
91    /// Returns the contained value associated with `key`, if this is a
92    /// [`Value::Object`]. Returns `None` if the value is not an object or if
93    /// the key is not found.
94    ///
95    /// # Performance
96    ///
97    /// [`Object`] uses a `Vec` of [`Entry`] types to store its entries. If the
98    /// operation being performed can be done with a single iteration over the
99    /// value's contents instead of multiple random accesses, the iteration
100    /// should be preferred. Additional options to make random access faster in
101    /// environments that can support it [are being considered][issue] for
102    /// future releases.
103    ///
104    /// [issue]: https://github.com/khonsulabs/justjson/issues/7
105    #[must_use]
106    #[inline]
107    pub fn get(&self, key: &str) -> Option<&Value<'a>> {
108        let object = self.as_object()?;
109        object.get(key)
110    }
111
112    /// Returns a mutable reference to the contained value associated with
113    /// `key`, if this is a [`Value::Object`]. Returns `None` if the value is
114    /// not an object or if the key is not found.
115    ///
116    /// # Performance
117    ///
118    /// [`Object`] uses a `Vec` of [`Entry`] types to store its entries. If the
119    /// operation being performed can be done with a single iteration over the
120    /// value's contents instead of multiple random accesses, the iteration
121    /// should be preferred. Additional options to make random access faster in
122    /// environments that can support it [are being considered][issue] for
123    /// future releases.
124    ///
125    /// [issue]: https://github.com/khonsulabs/justjson/issues/7
126    #[must_use]
127    #[inline]
128    pub fn get_mut(&mut self, key: &str) -> Option<&mut Value<'a>> {
129        let object = self.as_object_mut()?;
130        object.get_mut(key)
131    }
132
133    /// Returns the [`JsonString`] inside of this value, if this is a
134    /// [`Value::String`].
135    #[must_use]
136    #[inline]
137    pub const fn as_string(&self) -> Option<&JsonString<'a>> {
138        if let Self::String(obj) = self {
139            Some(obj)
140        } else {
141            None
142        }
143    }
144
145    /// Returns a reference to the contents of this value if it is a
146    /// [`Value::String`], and it does not have any escape sequences that need
147    /// to be decoded.
148    #[must_use]
149    #[inline]
150    pub fn as_str(&self) -> Option<&str> {
151        if let Self::String(json_string) = self {
152            json_string.as_str()
153        } else {
154            None
155        }
156    }
157
158    /// Returns the [`JsonNumber`] inside of this value, if this is a
159    /// [`Value::Number`].
160    #[must_use]
161    #[inline]
162    pub const fn as_number(&self) -> Option<&JsonNumber<'a>> {
163        if let Self::Number(obj) = self {
164            Some(obj)
165        } else {
166            None
167        }
168    }
169
170    /// Parses the contained value as an [`f32`], if it is a number.
171    ///
172    /// The JSON parser only validates that the number takes a correct form. If
173    /// a number cannot be parsed by the underlying routine due to having too
174    /// many digits, it this function can return None.
175    #[must_use]
176    pub fn as_f32(&self) -> Option<f32> {
177        self.as_number().and_then(JsonNumber::as_f32)
178    }
179
180    /// Parses the contained value as an [`f64`], if it is a number.
181    ///
182    /// The JSON parser only validates that the number takes a correct form. If
183    /// a number cannot be parsed by the underlying routine due to having too
184    /// many digits, it this function can return None.
185    #[must_use]
186    pub fn as_f64(&self) -> Option<f64> {
187        self.as_number().and_then(JsonNumber::as_f64)
188    }
189
190    /// Returns the `bool` inside of this value, if this is a
191    /// [`Value::Boolean`].
192    #[must_use]
193    #[inline]
194    pub const fn as_bool(&self) -> Option<bool> {
195        if let Self::Boolean(value) = self {
196            Some(*value)
197        } else {
198            None
199        }
200    }
201
202    /// Returns the slice of values inside of this value, if this is a
203    /// [`Value::Array`].
204    #[must_use]
205    #[inline]
206    pub fn as_array(&self) -> Option<&[Self]> {
207        if let Self::Array(value) = self {
208            Some(value)
209        } else {
210            None
211        }
212    }
213
214    /// Returns a mutable reference to the Vec of values inside of this value,
215    /// if this is a [`Value::Array`].
216    #[must_use]
217    #[inline]
218    pub fn as_array_mut(&mut self) -> Option<&mut Vec<Self>> {
219        if let Self::Array(value) = self {
220            Some(value)
221        } else {
222            None
223        }
224    }
225
226    /// Returns the contained value at `index`, if this is a [`Value::Array`].
227    /// Returns `None` if the value is not an array or if `index` is beyond the
228    /// bounds of the array.
229    #[must_use]
230    #[inline]
231    pub fn get_index(&self, index: usize) -> Option<&Value<'a>> {
232        let sequence = self.as_array()?;
233        sequence.get(index)
234    }
235
236    /// Returns a mutable reference to the contained value at `index`, if this
237    /// is a [`Value::Array`]. Returns `None` if the value is not an array or if
238    /// `index` is beyond the bounds of the array.
239    #[must_use]
240    #[inline]
241    pub fn get_index_mut(&mut self, index: usize) -> Option<&mut Value<'a>> {
242        let sequence = self.as_array_mut()?;
243        sequence.get_mut(index)
244    }
245
246    /// Returns true if this value is `null`/[`Value::Null`].
247    #[must_use]
248    #[inline]
249    pub const fn is_null(&self) -> bool {
250        matches!(self, Value::Null)
251    }
252
253    fn write_json<W: fmt::Write, const PRETTY: bool>(
254        &self,
255        indentation: &str,
256        line_ending: &str,
257        destination: W,
258    ) -> fmt::Result {
259        let mut state = WriteState::<W, PRETTY>::new(destination, indentation, line_ending);
260
261        self.write_json_value(&mut state)
262    }
263
264    fn write_json_value<W: fmt::Write, const PRETTY: bool>(
265        &self,
266        state: &mut WriteState<'_, W, PRETTY>,
267    ) -> fmt::Result {
268        match self {
269            Value::String(string) => state.write_json(string),
270            Value::Number(number) => state.write(number.source()),
271            Value::Boolean(bool) => state.write(if *bool { "true" } else { "false" }),
272            Value::Null => state.write("null"),
273            Value::Object(obj) => Self::write_json_object(obj, state),
274            Value::Array(array) => Self::write_json_array(array, state),
275        }
276    }
277
278    fn write_json_object<W: fmt::Write, const PRETTY: bool>(
279        obj: &Object<'_>,
280        state: &mut WriteState<'_, W, PRETTY>,
281    ) -> fmt::Result {
282        state.begin_object()?;
283
284        if !obj.0.is_empty() {
285            state.new_line()?;
286            for (index, entry) in obj.0.iter().enumerate() {
287                state.write_json(&entry.key)?;
288                state.write_object_key_end()?;
289                entry.value.write_json_value(state)?;
290                if index != obj.0.len() - 1 {
291                    state.write(",")?;
292                }
293                state.new_line()?;
294            }
295        }
296
297        state.end_object()
298    }
299
300    fn write_json_array<W: fmt::Write, const PRETTY: bool>(
301        array: &Vec<Self>,
302        state: &mut WriteState<'_, W, PRETTY>,
303    ) -> fmt::Result {
304        state.begin_array()?;
305
306        if !array.is_empty() {
307            state.new_line()?;
308            for (index, value) in array.iter().enumerate() {
309                value.write_json_value(state)?;
310                if index != array.len() - 1 {
311                    state.write(",")?;
312                }
313                state.new_line()?;
314            }
315        }
316
317        state.end_array()
318    }
319
320    /// Converts this value to its JSON representation, with extra whitespace to
321    /// make it easier for a human to read.
322    ///
323    /// This uses two spaces for indentation, and `\n` for end of lines. Use
324    /// [`to_json_pretty_custom()`](Self::to_json_pretty_custom) to customize
325    /// the formatting behavior.
326    ///
327    /// # Panics
328    ///
329    /// This function will panic if there is not enough memory to format the
330    /// JSON.
331    #[must_use]
332    pub fn to_json_pretty(&self) -> String {
333        let mut out = String::new();
334        self.pretty_write_json_to(&mut out).expect("out of memory");
335        out
336    }
337
338    /// Converts this value to its JSON representation, with extra whitespace to
339    /// make it easier for a human to read.
340    ///
341    /// # Panics
342    ///
343    /// This function will panic if there is not enough memory to format the
344    /// JSON.
345    #[must_use]
346    pub fn to_json_pretty_custom(&self, indentation: &str, line_ending: &str) -> String {
347        let mut out = String::new();
348        self.pretty_write_json_to_custom(indentation, line_ending, &mut out)
349            .expect("out of memory");
350        out
351    }
352
353    /// Converts this value to its JSON representation, with no extraneous
354    /// whitespace.
355    ///
356    /// # Panics
357    ///
358    /// This function will panic if there is not enough memory to format the
359    /// JSON.
360    #[must_use]
361    pub fn to_json(&self) -> String {
362        let mut out = String::new();
363        self.write_json_to(&mut out).expect("out of memory");
364        out
365    }
366
367    /// Writes this value's JSON representation to `destination`, with no extraneous
368    /// whitespace.
369    pub fn write_json_to<W: fmt::Write>(&self, destination: W) -> fmt::Result {
370        self.write_json::<W, false>("", "", destination)
371    }
372
373    /// Writes this value's JSON representation to `destination`, with extra
374    /// whitespace to make it easier for a human to read.
375    ///
376    /// This uses two spaces for indentation, and `\n` for end of lines. Use
377    /// [`to_json_pretty_custom()`](Self::to_json_pretty_custom) to customize
378    /// the formatting behavior.
379    pub fn pretty_write_json_to<W: fmt::Write>(&self, destination: W) -> fmt::Result {
380        self.pretty_write_json_to_custom("  ", "\n", destination)
381    }
382
383    /// Writes this value's JSON representation to `destination`, with extra
384    /// whitespace to make it easier for a human to read.
385    pub fn pretty_write_json_to_custom<W: fmt::Write>(
386        &self,
387        indentation: &str,
388        line_ending: &str,
389        destination: W,
390    ) -> fmt::Result {
391        self.write_json::<W, true>(indentation, line_ending, destination)
392    }
393}
394
395macro_rules! impl_as_number {
396    ($name:ident, $type:ident) => {
397        impl Value<'_> {
398            /// Parses the contained value as an
399            #[doc = concat!("[`", stringify!($type), "`]")]
400            /// if possible.
401            ///
402            /// If the source number is a floating point number or has a negative sign,
403            /// this will always return None.
404            #[must_use]
405            pub fn $name(&self) -> Option<$type> {
406                self.as_number().and_then(JsonNumber::$name)
407            }
408        }
409    };
410}
411
412impl_as_number!(as_u8, u8);
413impl_as_number!(as_u16, u16);
414impl_as_number!(as_u32, u32);
415impl_as_number!(as_u64, u64);
416impl_as_number!(as_u128, u128);
417impl_as_number!(as_usize, usize);
418impl_as_number!(as_i8, i8);
419impl_as_number!(as_i16, i16);
420impl_as_number!(as_i32, i32);
421impl_as_number!(as_i64, i64);
422impl_as_number!(as_i128, i128);
423impl_as_number!(as_isize, isize);
424
425#[test]
426fn value_ases() {
427    assert!(Value::from(true).as_bool().unwrap());
428    assert_eq!(
429        Value::String(JsonString::from_json("\"\"").unwrap())
430            .as_string()
431            .unwrap(),
432        ""
433    );
434    assert_eq!(
435        Value::String(JsonString::from_json("\"\"").unwrap())
436            .as_str()
437            .unwrap(),
438        ""
439    );
440    assert_eq!(
441        Value::Number(JsonNumber::from_json("1").unwrap())
442            .as_number()
443            .unwrap()
444            .as_u64()
445            .unwrap(),
446        1
447    );
448    assert_eq!(
449        Value::Object(Object::new()).as_object().unwrap(),
450        &Object::new()
451    );
452    assert_eq!(Value::Array(Vec::new()).as_array().unwrap(), &[]);
453
454    assert!(Value::Null.is_null());
455    assert!(!Value::from(true).is_null());
456    assert_eq!(Value::Null.as_bool(), None);
457    assert_eq!(Value::Null.as_number(), None);
458    assert_eq!(Value::Null.as_string(), None);
459    assert_eq!(Value::Null.as_str(), None);
460    assert_eq!(Value::Null.as_object(), None);
461    assert_eq!(Value::Null.as_array(), None);
462}
463
464impl<'a> Display for Value<'a> {
465    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
466        if f.alternate() {
467            self.pretty_write_json_to(f)
468        } else {
469            self.write_json_to(f)
470        }
471    }
472}
473
474pub(crate) struct ValueParser;
475
476impl<'a> ParseDelegate<'a> for ValueParser {
477    type Array = Vec<Value<'a>>;
478    type Error = Infallible;
479    type Key = JsonString<'a>;
480    type Object = Object<'a>;
481    type Value = Value<'a>;
482
483    #[inline]
484    fn null(&mut self) -> Result<Self::Value, Self::Error> {
485        Ok(Value::Null)
486    }
487
488    #[inline]
489    fn boolean(&mut self, value: bool) -> Result<Self::Value, Self::Error> {
490        Ok(Value::Boolean(value))
491    }
492
493    #[inline]
494    fn number(&mut self, value: JsonNumber<'a>) -> Result<Self::Value, Self::Error> {
495        Ok(Value::Number(value))
496    }
497
498    #[inline]
499    fn string(&mut self, value: JsonString<'a>) -> Result<Self::Value, Self::Error> {
500        Ok(Value::String(value))
501    }
502
503    #[inline]
504    fn begin_object(&mut self) -> Result<Self::Object, Self::Error> {
505        Ok(Object::default())
506    }
507
508    #[inline]
509    fn object_key(
510        &mut self,
511        _object: &mut Self::Object,
512        key: JsonString<'a>,
513    ) -> Result<Self::Key, Self::Error> {
514        Ok(key)
515    }
516
517    #[inline]
518    fn object_value(
519        &mut self,
520        object: &mut Self::Object,
521        key: Self::Key,
522        value: Self::Value,
523    ) -> Result<(), Self::Error> {
524        object.push(Entry { key, value });
525        Ok(())
526    }
527
528    #[inline]
529    fn object_is_empty(&self, object: &Self::Object) -> bool {
530        object.is_empty()
531    }
532
533    #[inline]
534    fn end_object(&mut self, object: Self::Object) -> Result<Self::Value, Self::Error> {
535        Ok(Value::Object(object))
536    }
537
538    #[inline]
539    fn begin_array(&mut self) -> Result<Self::Array, Self::Error> {
540        Ok(Vec::new())
541    }
542
543    #[inline]
544    fn array_value(
545        &mut self,
546        array: &mut Self::Array,
547        value: Self::Value,
548    ) -> Result<(), Self::Error> {
549        array.push(value);
550        Ok(())
551    }
552
553    #[inline]
554    fn array_is_empty(&self, array: &Self::Array) -> bool {
555        array.is_empty()
556    }
557
558    #[inline]
559    fn end_array(&mut self, array: Self::Array) -> Result<Self::Value, Self::Error> {
560        Ok(Value::Array(array))
561    }
562
563    #[inline]
564    fn kind_of(&self, value: &Self::Value) -> JsonKind {
565        match value {
566            Value::Number(_) => JsonKind::Number,
567            Value::String(_) => JsonKind::String,
568            Value::Boolean(_) => JsonKind::Boolean,
569            Value::Object(_) => JsonKind::Object,
570            Value::Array(_) => JsonKind::Array,
571            Value::Null => JsonKind::Null,
572        }
573    }
574}
575
576struct WriteState<'a, W, const PRETTY: bool> {
577    writer: W,
578    level: usize,
579    indent_per_level: &'a str,
580    line_ending: &'a str,
581    is_at_line_start: bool,
582}
583
584impl<'a, W, const PRETTY: bool> WriteState<'a, W, PRETTY>
585where
586    W: fmt::Write,
587{
588    fn new(writer: W, indentation: &'a str, line_ending: &'a str) -> Self {
589        Self {
590            writer,
591            level: 0,
592            is_at_line_start: true,
593            indent_per_level: indentation,
594            line_ending,
595        }
596    }
597
598    fn write(&mut self, str: &str) -> fmt::Result {
599        if PRETTY && self.is_at_line_start {
600            self.is_at_line_start = false;
601
602            for _ in 0..self.level {
603                self.writer.write_str(self.indent_per_level)?;
604            }
605        }
606
607        self.writer.write_str(str)?;
608        Ok(())
609    }
610
611    fn write_json(&mut self, str: &JsonString<'_>) -> fmt::Result {
612        if PRETTY && self.is_at_line_start {
613            self.is_at_line_start = false;
614
615            for _ in 0..self.level {
616                self.writer.write_str(self.indent_per_level)?;
617            }
618        }
619
620        write!(self.writer, "\"{}\"", str.as_json())
621    }
622
623    fn new_line(&mut self) -> fmt::Result {
624        if PRETTY {
625            self.write(self.line_ending)?;
626            self.is_at_line_start = true;
627        }
628        Ok(())
629    }
630
631    fn begin_object(&mut self) -> fmt::Result {
632        self.write("{")?;
633        self.level += 1;
634        Ok(())
635    }
636
637    fn write_object_key_end(&mut self) -> fmt::Result {
638        if PRETTY {
639            self.write(": ")?;
640        } else {
641            self.write(":")?;
642        }
643        Ok(())
644    }
645
646    fn end_object(&mut self) -> fmt::Result {
647        self.level -= 1;
648        self.write("}")?;
649        Ok(())
650    }
651
652    fn begin_array(&mut self) -> fmt::Result {
653        self.write("[")?;
654        self.level += 1;
655        Ok(())
656    }
657
658    fn end_array(&mut self) -> fmt::Result {
659        self.level -= 1;
660        self.write("]")?;
661        Ok(())
662    }
663}
664
665impl<'a> Index<usize> for Value<'a> {
666    type Output = Value<'a>;
667
668    /// Returns the contained value at `index`, if this is a [`Value::Array`].
669    ///
670    /// # Panics
671    ///
672    /// This function panics if the value is not a [`Value::Array`] or if the
673    /// index is out of bounds of the array.
674    #[inline]
675    fn index(&self, index: usize) -> &Self::Output {
676        self.get_index(index).expect("index not found")
677    }
678}
679
680impl<'a> IndexMut<usize> for Value<'a> {
681    /// Returns a mutable reference to the contained value at `index`, if this
682    /// is a [`Value::Array`].
683    ///
684    /// # Panics
685    ///
686    /// This function panics if the value is not a [`Value::Array`] or if the
687    /// index is out of bounds of the array.
688    #[inline]
689    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
690        self.get_index_mut(index).expect("index not found")
691    }
692}
693
694impl<'b, 'a> Index<&'b str> for Value<'a> {
695    type Output = Value<'a>;
696
697    /// Returns the contained value associated with `key`, if this is a
698    /// [`Value::Object`].
699    ///
700    /// # Panics
701    ///
702    /// This function panics if this value is not a [`Value::Object`] or if the
703    /// `key` is not found.
704    ///
705    /// # Performance
706    ///
707    /// [`Object`] uses a `Vec` of [`Entry`] types to store its entries. If the
708    /// operation being performed can be done with a single iteration over the
709    /// value's contents instead of multiple random accesses, the iteration
710    /// should be preferred. Additional options to make random access faster in
711    /// environments that can support it [are being considered][issue] for
712    /// future releases.
713    ///
714    /// [issue]: https://github.com/khonsulabs/justjson/issues/7
715    #[inline]
716    fn index(&self, index: &'b str) -> &Self::Output {
717        self.get(index).expect("key not found")
718    }
719}
720
721impl<'b, 'a> IndexMut<&'b str> for Value<'a> {
722    /// Returns a mutable reference to the contained value associated with
723    /// `key`, if this is a [`Value::Object`].
724    ///
725    /// # Panics
726    ///
727    /// This function panics if this value is not a [`Value::Object`] or if the
728    /// `key` is not found.
729    ///
730    /// # Performance
731    ///
732    /// [`Object`] uses a `Vec` of [`Entry`] types to store its entries. If the
733    /// operation being performed can be done with a single iteration over the
734    /// value's contents instead of multiple random accesses, the iteration
735    /// should be preferred. Additional options to make random access faster in
736    /// environments that can support it [are being considered][issue] for
737    /// future releases.
738    ///
739    /// [issue]: https://github.com/khonsulabs/justjson/issues/7
740    #[inline]
741    fn index_mut(&mut self, index: &'b str) -> &mut Self::Output {
742        self.get_mut(index).expect("key not found")
743    }
744}
745
746impl<'a> From<bool> for Value<'a> {
747    #[inline]
748    fn from(value: bool) -> Self {
749        Self::Boolean(value)
750    }
751}
752
753impl<'a> From<Object<'a>> for Value<'a> {
754    #[inline]
755    fn from(value: Object<'a>) -> Self {
756        Self::Object(value)
757    }
758}
759
760impl<'a> From<Vec<Value<'a>>> for Value<'a> {
761    #[inline]
762    fn from(value: Vec<Value<'a>>) -> Self {
763        Self::Array(value)
764    }
765}
766
767impl<'a> From<&'a str> for Value<'a> {
768    #[inline]
769    fn from(value: &'a str) -> Self {
770        Self::from(JsonString::from(value))
771    }
772}
773
774impl<'a> From<String> for Value<'a> {
775    #[inline]
776    fn from(value: String) -> Self {
777        Self::from(JsonString::from(value))
778    }
779}
780
781impl<'a> From<JsonString<'a>> for Value<'a> {
782    #[inline]
783    fn from(value: JsonString<'a>) -> Self {
784        Self::String(value)
785    }
786}
787
788/// A JSON Object (list of key-value pairs).
789///
790/// # Performance
791///
792/// [`Object`] uses a `Vec` of [`Entry`] types to store its entries. If the
793/// operation being performed can be done with a single iteration over the
794/// value's contents instead of multiple random accesses, the iteration should
795/// be preferred. Additional options to make random access faster in
796/// environments that can support it [are being considered][issue] for future
797/// releases.
798///
799/// # Modifying an Object
800///
801/// Because [`Object`] internally is just a `Vec<Entry>`, it implements
802/// `Deref`/`DerefMut` to its internal storage. This means that all of `Vec`'s
803/// methods are available to change the contents of an object.
804///
805/// ```rust
806/// use justjson::{Entry, Object, Value};
807///
808/// let mut obj = Object::new();
809/// obj.push(Entry::new("hello", "world"));
810///
811/// assert_eq!(Value::Object(obj).to_json(), r#"{"hello":"world"}"#)
812/// ```
813///
814/// [issue]: https://github.com/khonsulabs/justjson/issues/7
815#[derive(Debug, Eq, PartialEq)]
816pub struct Object<'a>(Vec<Entry<'a>>);
817
818impl<'a> Default for Object<'a> {
819    #[inline]
820    fn default() -> Self {
821        Self::new()
822    }
823}
824
825impl<'a> Object<'a> {
826    /// Returns an empty object.
827    #[must_use]
828    #[inline]
829    pub const fn new() -> Self {
830        Self(Vec::new())
831    }
832
833    /// Returns an empty object that can store up to `capacity` elements without
834    /// reallocating.
835    #[must_use]
836    #[inline]
837    pub fn with_capacity(capacity: usize) -> Self {
838        Self(Vec::with_capacity(capacity))
839    }
840
841    /// Returns the value associated with `key`, if found.
842    #[must_use]
843    #[inline]
844    pub fn get(&self, key: &str) -> Option<&Value<'a>> {
845        self.iter()
846            .find_map(|entry| (entry.key == key).then_some(&entry.value))
847    }
848
849    /// Returns a mutable reference to the value associated with `key`, if
850    /// found.
851    #[must_use]
852    #[inline]
853    pub fn get_mut(&mut self, key: &str) -> Option<&mut Value<'a>> {
854        self.get_entry_mut(key).map(|entry| &mut entry.value)
855    }
856
857    /// Returns a mutable reference to the entry associated with `key`, if
858    /// found.
859    #[must_use]
860    #[inline]
861    pub fn get_entry_mut(&mut self, key: &str) -> Option<&mut Entry<'a>> {
862        self.iter_mut().find(|entry| entry.key == key)
863    }
864}
865
866impl<'a> Deref for Object<'a> {
867    type Target = Vec<Entry<'a>>;
868
869    #[inline]
870    fn deref(&self) -> &Self::Target {
871        &self.0
872    }
873}
874
875impl<'a> DerefMut for Object<'a> {
876    #[inline]
877    fn deref_mut(&mut self) -> &mut Self::Target {
878        &mut self.0
879    }
880}
881
882impl<'a> FromIterator<(JsonString<'a>, Value<'a>)> for Object<'a> {
883    fn from_iter<T: IntoIterator<Item = (JsonString<'a>, Value<'a>)>>(iter: T) -> Self {
884        iter.into_iter()
885            .map(|(key, value)| Entry { key, value })
886            .collect()
887    }
888}
889
890impl<'a> FromIterator<Entry<'a>> for Object<'a> {
891    fn from_iter<T: IntoIterator<Item = Entry<'a>>>(iter: T) -> Self {
892        Self(iter.into_iter().collect())
893    }
894}
895
896/// An key-value pair in an [`Object`].
897#[derive(Debug, Eq, PartialEq)]
898pub struct Entry<'a> {
899    /// The key of this entry.
900    pub key: JsonString<'a>,
901    /// The value associated with the key.
902    pub value: Value<'a>,
903}
904
905impl<'a> Entry<'a> {
906    /// Returns a new entry for the given key and value.
907    #[inline]
908    pub fn new(key: impl Into<JsonString<'a>>, value: impl Into<Value<'a>>) -> Self {
909        Self {
910            key: key.into(),
911            value: value.into(),
912        }
913    }
914}
915
916#[test]
917fn primitive_values() {
918    assert_eq!(Value::from_json("true").unwrap(), Value::from(true));
919    assert_eq!(Value::from_json("false").unwrap(), Value::from(false));
920    assert_eq!(Value::from_json("null").unwrap(), Value::Null);
921}
922
923#[test]
924fn objects() {
925    assert_eq!(
926        Value::from_json("{}").unwrap(),
927        Value::Object(Object::default())
928    );
929    assert_eq!(
930        Value::from_json(r#"{"hello":"world"}"#).unwrap(),
931        Value::Object(Object::from_iter([(
932            JsonString::from_json(r#""hello""#).unwrap(),
933            Value::String(JsonString::from_json(r#""world""#).unwrap())
934        )]))
935    );
936    assert_eq!(
937        Value::from_json(r#" { "hello" : "world" , "another" : "value" }"#).unwrap(),
938        Value::Object(Object::from_iter([
939            Entry::new(
940                JsonString::from_json(r#""hello""#).unwrap(),
941                Value::String(JsonString::from_json(r#""world""#).unwrap())
942            ),
943            Entry::new(
944                JsonString::from_json(r#""another""#).unwrap(),
945                Value::String(JsonString::from_json(r#""value""#).unwrap())
946            )
947        ]))
948    );
949}
950
951#[test]
952fn cow() {
953    let mut value =
954        Value::from_json_bytes(br#"{"a":1,"b":true,"c":"hello","d":[],"e":{}}"#).unwrap();
955    value["b"] = Value::from(false);
956    let root = value.as_object_mut().unwrap();
957    root[0].key = JsonString::from("newa");
958    root[0].value = JsonString::from("a").into();
959    let Value::Array(d_array) = &mut root[3].value else {
960        unreachable!()
961    };
962    d_array.push(Value::Null);
963
964    // Replace the newly inserted null (uses IndexMut on the array).
965    value["d"][0] = Value::from(false);
966
967    let generated = value.to_json();
968    assert_eq!(
969        generated,
970        r#"{"newa":"a","b":false,"c":"hello","d":[false],"e":{}}"#
971    );
972}
973
974#[test]
975fn index() {
976    let mut value = Value::from_json_bytes(br#"{"b":true,"a":[false]}"#).unwrap();
977    assert_eq!(value["b"], Value::from(true));
978    assert_eq!(value.get_index_mut(0), None);
979    assert_eq!(value["a"][0], Value::from(false));
980    assert_eq!(value["a"].get_mut("a"), None);
981}
982
983#[test]
984fn froms() {
985    assert_eq!(Value::from(true), Value::Boolean(true));
986    assert_eq!(Value::from(Object::new()), Value::Object(Object::new()));
987    assert_eq!(Value::from(Vec::new()), Value::Array(Vec::new()));
988    assert_eq!(
989        Value::from(String::from("a")),
990        Value::String(JsonString::from("a"))
991    );
992    assert_eq!(Value::from("a"), Value::String(JsonString::from("a")));
993    assert_eq!(
994        Value::from(JsonString::from("a")),
995        Value::String(JsonString::from("a"))
996    );
997}
998
999#[test]
1000fn as_es() {
1001    macro_rules! test_as {
1002        ($as:ident) => {
1003            assert_eq!(
1004                Value::Number(JsonNumber::from_json("1").unwrap()).$as(),
1005                Some(1)
1006            );
1007        };
1008    }
1009
1010    test_as!(as_i8);
1011    test_as!(as_i16);
1012    test_as!(as_i32);
1013    test_as!(as_i64);
1014    test_as!(as_i128);
1015    test_as!(as_isize);
1016    test_as!(as_u8);
1017    test_as!(as_u16);
1018    test_as!(as_u32);
1019    test_as!(as_u64);
1020    test_as!(as_u128);
1021    test_as!(as_usize);
1022
1023    assert!(
1024        Value::Number(JsonNumber::from_json("0").unwrap())
1025            .as_f32()
1026            .unwrap()
1027            .abs()
1028            < f32::EPSILON
1029    );
1030    assert!(
1031        Value::Number(JsonNumber::from_json("0").unwrap())
1032            .as_f64()
1033            .unwrap()
1034            .abs()
1035            < f64::EPSILON
1036    );
1037}