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 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 I(i64),
312 U(u64),
313}
314
315const MAX_FLOAT_I: f64 = 9007199254740990.0;
316
317fn 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
456impl_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);