smoljson/
value.rs

1use super::read::Result;
2use super::read::*;
3use super::write::{self, WriteJson, Writer};
4use alloc::borrow::Cow;
5use alloc::collections::BTreeMap;
6use alloc::string::String;
7use alloc::vec::Vec;
8
9#[derive(Debug, Clone, PartialEq)]
10pub enum Value<'a> {
11    Null,
12    Bool(bool),
13    Num(Num),
14    Str(Cow<'a, str>),
15    Array(Vec<Value<'a>>),
16    Object(BTreeMap<Cow<'a, str>, Value<'a>>),
17}
18impl<'a> Value<'a> {
19    pub fn is_null(&self) -> bool {
20        matches!(self, Self::Null)
21    }
22    pub fn is_bool(&self) -> bool {
23        matches!(self, Self::Bool(_))
24    }
25    pub fn is_number(&self) -> bool {
26        matches!(self, Self::Num(_))
27    }
28    pub fn is_str(&self) -> bool {
29        matches!(self, Self::Str(_))
30    }
31    pub fn is_array(&self) -> bool {
32        matches!(self, Self::Array(_))
33    }
34    pub fn is_object(&self) -> bool {
35        matches!(self, Self::Object(_))
36    }
37    pub fn as_bool(&self) -> Option<bool> {
38        opt_extract!(self, Self::Bool(b) => Some(*b))
39    }
40    pub fn as_f64(&self) -> Option<f64> {
41        opt_extract!(self, Self::Num(n) => n.as_f64())
42    }
43    pub fn as_i64(&self) -> Option<i64> {
44        opt_extract!(self, Self::Num(n) => n.as_i64())
45    }
46    pub fn as_u64(&self) -> Option<u64> {
47        opt_extract!(self, Self::Num(n) => n.as_u64())
48    }
49    pub fn as_str(&self) -> Option<&str> {
50        opt_extract!(self, Self::Str(s) => Some(&*s))
51    }
52    pub fn as_array(&self) -> Option<&[Value<'a>]> {
53        opt_extract!(self, Self::Array(a) => Some(&a[..]))
54    }
55    pub fn as_object(&self) -> Option<&BTreeMap<Cow<'a, str>, Value<'a>>> {
56        opt_extract!(self, Self::Object(o) => Some(o))
57    }
58
59    pub fn into_str(self) -> Option<Cow<'a, str>> {
60        opt_extract!(self, Self::Str(s) => Some(s))
61    }
62    pub fn into_array(self) -> Option<Vec<Value<'a>>> {
63        opt_extract!(self, Self::Array(a) => Some(a))
64    }
65    pub fn into_object(self) -> Option<BTreeMap<Cow<'a, str>, Value<'a>>> {
66        opt_extract!(self, Self::Object(a) => Some(a))
67    }
68
69    pub fn as_mut_array(&mut self) -> Option<&mut Vec<Value<'a>>> {
70        opt_extract!(self, Self::Array(a) => Some(a))
71    }
72    pub fn as_mut_object(&mut self) -> Option<&mut BTreeMap<Cow<'a, str>, Value<'a>>> {
73        opt_extract!(self, Self::Object(a) => Some(a))
74    }
75
76    pub fn get(&self, key: &str) -> Option<&Value<'a>> {
77        self.as_object().and_then(|s| s.get(key))
78    }
79    pub fn at(&self, i: usize) -> Option<&Value<'a>> {
80        self.as_array().and_then(|s| s.get(i))
81    }
82    pub fn get_mut(&mut self, key: &str) -> Option<&mut Value<'a>> {
83        self.as_mut_object().and_then(|s| s.get_mut(key))
84    }
85    pub fn at_mut(&mut self, i: usize) -> Option<&mut Value<'a>> {
86        self.as_mut_array().and_then(|s| s.get_mut(i))
87    }
88    pub fn take(&mut self) -> Value {
89        core::mem::replace(self, Self::Null)
90    }
91}
92
93static NULL: Value<'static> = Value::Null;
94
95impl<'a> core::ops::Index<usize> for Value<'a> {
96    type Output = Value<'a>;
97    fn index(&self, i: usize) -> &Value<'a> {
98        self.at(i).unwrap_or(&NULL)
99    }
100}
101impl<'a> core::ops::IndexMut<usize> for Value<'a> {
102    fn index_mut(&mut self, i: usize) -> &mut Value<'a> {
103        self.at_mut(i).unwrap()
104    }
105}
106impl<'a> core::ops::Index<&str> for Value<'a> {
107    type Output = Value<'a>;
108    fn index(&self, a: &str) -> &Value<'a> {
109        self.get(a).unwrap_or(&NULL)
110    }
111}
112impl<'a> core::ops::IndexMut<&str> for Value<'a> {
113    fn index_mut(&mut self, s: &str) -> &mut Value<'a> {
114        if self.is_null() {
115            *self = Value::Object(BTreeMap::new());
116        }
117        if let Self::Object(o) = self {
118            o.entry(Cow::Owned(s.into())).or_insert(Value::Null)
119        } else {
120            bad_index(s)
121        }
122    }
123}
124
125#[cold]
126#[inline(never)]
127fn bad_index(s: &str) -> ! {
128    panic!("Attempt to insert key {:?} into non-object json value", s)
129}
130
131impl Default for Value<'_> {
132    fn default() -> Self {
133        Self::Null
134    }
135}
136impl From<bool> for Value<'_> {
137    fn from(b: bool) -> Self {
138        Self::Bool(b)
139    }
140}
141impl From<String> for Value<'_> {
142    fn from(s: String) -> Self {
143        Self::Str(s.into())
144    }
145}
146impl<'a> From<&'a str> for Value<'a> {
147    fn from(s: &'a str) -> Self {
148        Self::Str(Cow::Borrowed(s))
149    }
150}
151impl<'a> From<Cow<'a, str>> for Value<'a> {
152    fn from(s: Cow<'a, str>) -> Self {
153        Self::Str(s)
154    }
155}
156
157impl<'a> From<Num> for Value<'a> {
158    fn from(n: Num) -> Self {
159        Self::Num(n)
160    }
161}
162
163impl<'a> core::iter::FromIterator<Value<'a>> for Value<'a> {
164    fn from_iter<T: IntoIterator<Item = Value<'a>>>(iter: T) -> Self {
165        Value::Array(iter.into_iter().collect())
166    }
167}
168
169impl<'a, S: Into<Cow<'a, str>>> core::iter::FromIterator<(S, Value<'a>)> for Value<'a> {
170    fn from_iter<T: IntoIterator<Item = (S, Value<'a>)>>(iter: T) -> Self {
171        Value::Object(iter.into_iter().map(|(k, v)| (k.into(), v)).collect())
172    }
173}
174
175impl<'a> Value<'a> {
176    pub fn from_str(s: &'a str) -> Result<Self> {
177        Self::from_str_with(s, Dialect::DEFAULT)
178    }
179
180    pub fn from_str_with(input: &'a str, d: Dialect) -> Result<Self> {
181        let mut de = Reader::with_dialect(input, d);
182        let r = tri!(Self::from_reader(&mut de));
183        tri!(de.finish());
184        Ok(r)
185    }
186
187    pub fn into_static(self) -> Value<'static> {
188        match self {
189            Value::Null => Value::Null,
190            Value::Bool(b) => Value::Bool(b),
191            Value::Num(n) => Value::Num(n),
192            Value::Str(Cow::Owned(s)) => Value::Str(Cow::Owned(s)),
193            Value::Str(Cow::Borrowed(s)) => Value::Str(Cow::Owned(s.into())),
194            Value::Array(a) => Value::Array(a.into_iter().map(|v| v.into_static()).collect()),
195            Value::Object(o) => Value::Object(
196                o.into_iter()
197                    .map(|(s, v)| {
198                        let s: Cow<'static, str> = match s {
199                            Cow::Borrowed(s) => Cow::Owned(s.into()),
200                            Cow::Owned(s) => Cow::Owned(s),
201                        };
202                        (s, v.into_static())
203                    })
204                    .collect(),
205            ),
206        }
207    }
208    pub fn from_reader(de: &mut Reader<'a>) -> Result<Self> {
209        match tri!(de.next()) {
210            Token::Null => Ok(Self::Null),
211            Token::Bool(b) => Ok(Self::Bool(b)),
212            Token::NumF(b) => Ok(Self::from(b)),
213            Token::NumI(b) => Ok(Self::from(b)),
214            Token::NumU(b) => Ok(Self::from(b)),
215            Token::StrBorrow(b) => Ok(Self::Str(Cow::Borrowed(b))),
216            Token::StrOwn(b) => Ok(Self::Str(Cow::Owned(b.into()))),
217            Token::ArrayBegin => Self::do_read_array(de),
218            Token::ObjectBegin => Self::do_read_obj(de),
219            _ => Err(de.err()),
220        }
221    }
222    fn do_read_array(de: &mut Reader<'a>) -> Result<Self> {
223        let mut v = alloc::vec![];
224        if tri!(de.skipnpeek()) == Some(b']') {
225            assert!(matches!(de.next_token(), Ok(Some(Token::ArrayEnd))));
226            return Ok(Self::Array(v));
227        }
228        loop {
229            v.push(tri!(Value::from_reader(de)));
230            if !tri!(de.comma_or_array_end()) {
231                break;
232            }
233        }
234        Ok(Self::Array(v))
235    }
236    fn do_read_obj(de: &mut Reader<'a>) -> Result<Self> {
237        let mut obj = BTreeMap::new();
238        if tri!(de.skipnpeek()) == Some(b'}') {
239            assert!(matches!(de.next_token(), Ok(Some(Token::ObjectEnd))));
240            return Ok(Self::Object(obj));
241        }
242        loop {
243            let k = tri!(de.key());
244            tri!(de.colon());
245            let val = tri!(Value::from_reader(de));
246            obj.insert(k, val);
247            if !tri!(de.comma_or_obj_end()) {
248                break;
249            }
250        }
251        Ok(Self::Object(obj))
252    }
253}
254
255impl WriteJson for Num {
256    fn write_json(&self, w: &mut Writer) {
257        match self.0 {
258            N::F(n) => n.write_json(w),
259            N::I(n) => n.write_json(w),
260            N::U(n) => n.write_json(w),
261        }
262    }
263}
264impl WriteJson for Value<'_> {
265    fn write_json(&self, w: &mut Writer) {
266        match self {
267            Self::Null => write::Null.write_json(w),
268            Self::Bool(b) => b.write_json(w),
269            Self::Num(n) => n.write_json(w),
270            Self::Str(s) => (&*s).write_json(w),
271            Self::Array(s) => {
272                let mut a = w.array();
273                for v in s {
274                    a.put(v);
275                }
276            }
277            Self::Object(s) => {
278                let mut o = w.object();
279                for (k, v) in s {
280                    o.put(&*k, v);
281                }
282            }
283        }
284    }
285}
286impl Value<'_> {
287    pub fn to_string(&self, pretty: bool) -> String {
288        let mut w = Writer::new(pretty);
289        self.write_json(&mut w);
290        w.finish()
291    }
292}
293impl core::str::FromStr for Value<'static> {
294    type Err = Error;
295    fn from_str(s: &str) -> Result<Self> {
296        // Not really ideal to do 2 passes...
297        Value::from_str(s).map(|v| v.into_static())
298    }
299}
300
301impl core::fmt::Display for Value<'_> {
302    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
303        f.write_str(&self.to_string(false))
304    }
305}
306
307#[derive(Debug, Copy, Clone)]
308enum N {
309    F(f64),
310    // only negative
311    I(i64),
312    U(u64),
313}
314
315const MAX_FLOAT_I: f64 = 9007199254740990.0;
316
317// If this returns true for some float, then we'll consider converting it to an
318// equivalent int internally.
319fn is_sanely_integral(f: f64) -> bool {
320    f.is_finite() && f >= -MAX_FLOAT_I && f <= MAX_FLOAT_I && (f as i64 as f64 == f)
321}
322
323#[derive(Debug, Copy, Clone)]
324#[repr(transparent)]
325pub struct Num(N);
326
327impl Num {
328    pub fn from_u64(v: u64) -> Self {
329        Self(N::U(v))
330    }
331    pub fn from_i64(v: i64) -> Self {
332        if v < 0 {
333            Self(N::I(v))
334        } else {
335            Self(N::U(v as u64))
336        }
337    }
338    pub fn from_f64(v: f64) -> Self {
339        debug_assert!(v.is_finite());
340        if is_sanely_integral(v) {
341            let result = if v < 0.0 {
342                Self(N::I(v as i64))
343            } else {
344                Self(N::U(v as u64))
345            };
346            debug_assert_eq!(result.as_f64(), Some(v));
347            result
348        } else {
349            Self(N::F(v))
350        }
351    }
352    pub fn as_f64(self) -> Option<f64> {
353        match self.0 {
354            N::F(f) => Some(f),
355            N::I(i) if (i as f64 as i64) == i => Some(i as f64),
356            N::U(i) if (i as f64 as u64) == i => Some(i as f64),
357            _ => None,
358        }
359    }
360    pub fn as_u64(self) -> Option<u64> {
361        match self.0 {
362            N::F(f) if f >= 0.0 && is_sanely_integral(f) => Some(f as u64),
363            N::I(i) if i >= 0 => Some(i as u64),
364            N::U(u) => Some(u),
365            _ => None,
366        }
367    }
368    pub fn as_i64(self) -> Option<i64> {
369        match self.0 {
370            N::F(f) if is_sanely_integral(f) => Some(f as i64),
371            N::I(i) => Some(i),
372            N::U(u) if u < (i64::MAX as u64) => Some(u as i64),
373            _ => None,
374        }
375    }
376    pub fn as_int(self) -> i128 {
377        match self.0 {
378            N::F(f) => f as i128,
379            N::I(i) => i as i128,
380            N::U(u) => u as i128,
381        }
382    }
383    fn desc_id(self) -> u8 {
384        match self.0 {
385            N::F(_) => 0,
386            N::I(_) => 1,
387            N::U(_) => 2,
388        }
389    }
390    pub fn get_float(self) -> Option<f64> {
391        if let N::F(f) = self.0 {
392            Some(f)
393        } else {
394            None
395        }
396    }
397    pub fn get_int(self) -> Option<i128> {
398        match self.0 {
399            N::F(_) => None,
400            N::I(i) => Some(i as i128),
401            N::U(u) => Some(u as i128),
402        }
403    }
404}
405impl core::fmt::Display for Num {
406    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
407        match self.0 {
408            N::F(n) => n.fmt(f),
409            N::I(n) => n.fmt(f),
410            N::U(n) => n.fmt(f),
411        }
412    }
413}
414
415impl PartialEq for Num {
416    fn eq(&self, o: &Self) -> bool {
417        use N::*;
418        match (self.0, o.0) {
419            (F(a), F(b)) => a == b,
420            (I(a), I(b)) => a == b,
421            (U(a), U(b)) => a == b,
422            (I(i), U(_)) | (U(_), I(i)) => {
423                debug_assert!(i < 0, "{}", i);
424                false
425            }
426            (F(f), I(i)) | (I(i), F(f)) => {
427                debug_assert!(i < 0, "{}", i);
428                if f < 0.0 && f >= -MAX_FLOAT_I && f as i64 as f64 == f {
429                    (i as f64) == f || (f as i64) == i
430                } else {
431                    false
432                }
433            }
434            (F(f), U(i)) | (U(i), F(f)) => {
435                if f >= 0.0 && f <= MAX_FLOAT_I && f as u64 as f64 == f {
436                    (i as f64) == f || (f as u64) == i
437                } else {
438                    false
439                }
440            }
441        }
442    }
443}
444
445macro_rules! impl_into_num {
446    (@via($bty:ident, $cast:ident) $($t:ident),*) => {$(
447        impl From<$t> for Num {
448            fn from(t: $t) -> Self { Num::$cast(t as $bty) }
449        }
450        impl From<$t> for Value<'_> {
451            fn from(t: $t) -> Self { Value::Num(Num::$cast(t as $bty)) }
452        }
453    )*};
454}
455
456// impl_into_num!(i8, u8, i16, u16, i32, u32, i64, u64, isize, usize);
457impl_into_num!(@via(i64, from_i64) i8, i16, i32, i64, isize);
458impl_into_num!(@via(u64, from_u64) u8, u16, u32, u64, usize);
459impl_into_num!(@via(f64, from_f64) f32, f64);