jaq_json/
lib.rs

1//! JSON superset with binary data and non-string object keys.
2//!
3//! This crate provides a few macros for formatting / writing;
4//! this is done in order to function with both
5//! [`core::fmt::Write`] and [`std::io::Write`].
6#![no_std]
7#![forbid(unsafe_code)]
8#![warn(missing_docs)]
9
10extern crate alloc;
11// even if this crate is `no_std`, it currently relies on `std`, because
12// `to_json` has to go through the JSON writer to preserve invalid UTF-8
13extern crate std;
14
15mod funs;
16mod num;
17#[macro_use]
18pub mod write;
19pub mod read;
20
21use alloc::{borrow::ToOwned, boxed::Box, string::String, vec::Vec};
22use bstr::{BStr, ByteSlice};
23use bytes::{BufMut, Bytes, BytesMut};
24use core::cmp::Ordering;
25use core::fmt;
26use core::hash::{Hash, Hasher};
27use jaq_core::box_iter::box_once;
28use jaq_core::{load, ops, path, val, Exn};
29use num_bigint::BigInt;
30use num_traits::{cast::ToPrimitive, Signed};
31
32pub use funs::{bytes_valrs, funs};
33pub use num::Num;
34
35#[cfg(not(feature = "sync"))]
36pub use alloc::rc::Rc;
37#[cfg(feature = "sync")]
38pub use alloc::sync::Arc as Rc;
39
40#[cfg(feature = "serde")]
41mod serde;
42
43/// JSON superset with binary data and non-string object keys.
44///
45/// This is the default value type for jaq.
46#[derive(Clone, Debug, Default)]
47pub enum Val {
48    #[default]
49    /// Null
50    Null,
51    /// Boolean
52    Bool(bool),
53    /// Number
54    Num(Num),
55    /// String
56    Str(Bytes, Tag),
57    /// Array
58    Arr(Rc<Vec<Val>>),
59    /// Object
60    Obj(Rc<Map<Val, Val>>),
61}
62
63#[cfg(feature = "sync")]
64#[test]
65fn val_send_sync() {
66    fn send_sync<T: Send + Sync>(_: T) {}
67    send_sync(Val::default())
68}
69
70/// Interpretation of a string.
71///
72/// This influences the outcome of a few operations (e.g. slicing)
73/// as well as how a string is printed.
74#[derive(Copy, Clone, Debug, PartialEq, Eq)]
75pub enum Tag {
76    /// Sequence of bytes, to be escaped
77    Bytes,
78    /// Sequence of UTF-8 code points
79    ///
80    /// Note that this does not require the actual bytes to be all valid UTF-8;
81    /// this just means that the bytes are interpreted as UTF-8.
82    /// An effort is made to preserve invalid UTF-8 as is, else
83    /// replace invalid UTF-8 by the Unicode replacement character.
84    Utf8,
85}
86
87/// Types and sets of types.
88#[derive(Clone, Debug, PartialEq, Eq)]
89enum Type {
90    /// `[] | .["a"]` or `limit("a"; 0)` or `range(0; "a")`
91    Int,
92    /*
93    /// `"1" | sin` or `pow(2; "3")` or `fma(2; 3; "4")`
94    Float,
95    */
96    /// `-"a"`, `"a" | round`
97    Num,
98    /// `{(0): 1}` or `0 | fromjson` or `0 | explode` or `"a b c" | split(0)`
99    Str,
100    /// `0 | sort` or `0 | implode` or `[] | .[0:] = 0`
101    Arr,
102    /// `0 | .[]` or `0 | .[0]` or `0 | keys` (array or object)
103    Iter,
104    /// `{}[0:1]` (string or array)
105    Range,
106}
107
108impl Type {
109    fn as_str(&self) -> &'static str {
110        match self {
111            Self::Int => "integer",
112            //Self::Float => "floating-point number",
113            Self::Num => "number",
114            Self::Str => "string",
115            Self::Arr => "array",
116            Self::Iter => "iterable (array or object)",
117            Self::Range => "rangeable (array or string)",
118        }
119    }
120}
121
122/// Order-preserving map
123pub type Map<K = Val, V = K> = indexmap::IndexMap<K, V, foldhash::fast::RandomState>;
124
125/// Error that can occur during filter execution.
126pub type Error = jaq_core::Error<Val>;
127/// A value or an eRror.
128pub type ValR = jaq_core::ValR<Val>;
129/// A value or an eXception.
130pub type ValX = jaq_core::ValX<Val>;
131
132// This is part of the Rust standard library since 1.76:
133// <https://doc.rust-lang.org/std/rc/struct.Rc.html#method.unwrap_or_clone>.
134// However, to keep MSRV low, we reimplement it here.
135fn rc_unwrap_or_clone<T: Clone>(a: Rc<T>) -> T {
136    Rc::try_unwrap(a).unwrap_or_else(|a| (*a).clone())
137}
138
139impl jaq_core::ValT for Val {
140    fn from_num(n: &str) -> ValR {
141        Ok(Self::Num(Num::from_str(n)))
142    }
143
144    fn from_map<I: IntoIterator<Item = (Self, Self)>>(iter: I) -> ValR {
145        Ok(Self::obj(iter.into_iter().collect()))
146    }
147
148    fn key_values(self) -> Box<dyn Iterator<Item = Result<(Val, Val), Error>>> {
149        let arr_idx = |(i, x)| Ok((Self::from(i as isize), x));
150        match self {
151            Self::Arr(a) => Box::new(rc_unwrap_or_clone(a).into_iter().enumerate().map(arr_idx)),
152            Self::Obj(o) => Box::new(rc_unwrap_or_clone(o).into_iter().map(Ok)),
153            _ => box_once(Err(Error::typ(self, Type::Iter.as_str()))),
154        }
155    }
156
157    fn values(self) -> Box<dyn Iterator<Item = ValR>> {
158        match self {
159            Self::Arr(a) => Box::new(rc_unwrap_or_clone(a).into_iter().map(Ok)),
160            Self::Obj(o) => Box::new(rc_unwrap_or_clone(o).into_iter().map(|(_k, v)| Ok(v))),
161            _ => box_once(Err(Error::typ(self, Type::Iter.as_str()))),
162        }
163    }
164
165    fn index(self, index: &Self) -> ValR {
166        match (self, index) {
167            (Val::Null, _) => Ok(Val::Null),
168            (Val::Str(a, Tag::Bytes), Val::Num(i @ (Num::Int(_) | Num::BigInt(_)))) => Ok(i
169                .as_pos_usize()
170                .and_then(|i| abs_index(i, a.len()))
171                .map_or(Val::Null, |i| Val::from(a[i] as usize))),
172            (Val::Arr(a), Val::Num(i @ (Num::Int(_) | Num::BigInt(_)))) => Ok(i
173                .as_pos_usize()
174                .and_then(|i| abs_index(i, a.len()))
175                .map_or(Val::Null, |i| a[i].clone())),
176            (v @ (Val::Str(..) | Val::Arr(_)), Val::Obj(o)) => {
177                v.range(o.get(&Val::utf8_str("start"))..o.get(&Val::utf8_str("end")))
178            }
179            (Val::Obj(o), i) => Ok(o.get(i).cloned().unwrap_or(Val::Null)),
180            (s @ (Val::Str(_, Tag::Bytes) | Val::Arr(_)), _) => Err(Error::index(s, index.clone())),
181            (s, _) => Err(Error::typ(s, Type::Iter.as_str())),
182        }
183    }
184
185    fn range(self, range: val::Range<&Self>) -> ValR {
186        match self {
187            Val::Str(s, t) => Self::range_int(range)
188                .map(|range_char| skip_take_str(t, range_char, &s))
189                .map(|(skip, take)| Val::Str(s.slice(skip..skip + take), t)),
190            Val::Arr(a) => Self::range_int(range)
191                .map(|range| skip_take(range, a.len()))
192                .map(|(skip, take)| a.iter().skip(skip).take(take).cloned().collect()),
193            _ => Err(Error::typ(self, Type::Range.as_str())),
194        }
195    }
196
197    fn map_values<I: Iterator<Item = ValX>>(self, opt: path::Opt, f: impl Fn(Self) -> I) -> ValX {
198        match self {
199            Self::Arr(a) => {
200                let iter = rc_unwrap_or_clone(a).into_iter().flat_map(f);
201                Ok(iter.collect::<Result<_, _>>()?)
202            }
203            Self::Obj(o) => {
204                let iter = rc_unwrap_or_clone(o).into_iter();
205                let iter = iter.filter_map(|(k, v)| f(v).next().map(|v| Ok((k, v?))));
206                Ok(Self::obj(iter.collect::<Result<_, Exn<_>>>()?))
207            }
208            v => opt.fail(v, |v| Exn::from(Error::typ(v, Type::Iter.as_str()))),
209        }
210    }
211
212    fn map_index<I: Iterator<Item = ValX>>(
213        mut self,
214        index: &Self,
215        opt: path::Opt,
216        f: impl Fn(Self) -> I,
217    ) -> ValX {
218        if let (Val::Str(..) | Val::Arr(_), Val::Obj(o)) = (&self, index) {
219            let range = o.get(&Val::utf8_str("start"))..o.get(&Val::utf8_str("end"));
220            return self.map_range(range, opt, f);
221        };
222        match self {
223            Val::Obj(ref mut o) => {
224                use indexmap::map::Entry::{Occupied, Vacant};
225                match Rc::make_mut(o).entry(index.clone()) {
226                    Occupied(mut e) => {
227                        let v = core::mem::take(e.get_mut());
228                        match f(v).next().transpose()? {
229                            Some(y) => e.insert(y),
230                            // this runs in constant time, at the price of
231                            // changing the order of the elements
232                            None => e.swap_remove(),
233                        };
234                    }
235                    Vacant(e) => {
236                        if let Some(y) = f(Val::Null).next().transpose()? {
237                            e.insert(y);
238                        }
239                    }
240                }
241                Ok(self)
242            }
243            Val::Arr(ref mut a) => {
244                let oob = || Error::str(format_args!("index {index} out of bounds"));
245                let abs_or = |i| abs_index(i, a.len()).ok_or_else(oob);
246                let i = match index.as_pos_usize().and_then(abs_or) {
247                    Ok(i) => i,
248                    Err(e) => return opt.fail(self, |_| Exn::from(e)),
249                };
250
251                let a = Rc::make_mut(a);
252                let x = core::mem::take(&mut a[i]);
253                if let Some(y) = f(x).next().transpose()? {
254                    a[i] = y;
255                } else {
256                    a.remove(i);
257                }
258                Ok(self)
259            }
260            _ => opt.fail(self, |v| Exn::from(Error::typ(v, Type::Iter.as_str()))),
261        }
262    }
263
264    fn map_range<I: Iterator<Item = ValX>>(
265        mut self,
266        range: val::Range<&Self>,
267        opt: path::Opt,
268        f: impl Fn(Self) -> I,
269    ) -> ValX {
270        match self {
271            Val::Arr(ref mut a) => {
272                let (skip, take) = match Self::range_int(range) {
273                    Ok(range) => skip_take(range, a.len()),
274                    Err(e) => return opt.fail(self, |_| Exn::from(e)),
275                };
276                let arr = a.iter().skip(skip).take(take).cloned().collect();
277                let y = f(arr).map(|y| y?.into_arr().map_err(Exn::from)).next();
278                let y = y.transpose()?.unwrap_or_default();
279                Rc::make_mut(a).splice(skip..skip + take, (*y).clone());
280                Ok(self)
281            }
282            Val::Str(b, t) => {
283                let (skip, take) = match Self::range_int(range) {
284                    Ok(range) => skip_take_str(t, range, &b),
285                    Err(e) => return opt.fail(Val::Str(b, t), |_| Exn::from(e)),
286                };
287                let str = Val::Str(b.slice(skip..skip + take), t);
288                let y = f(str).map(|y| y?.into_str(t).map_err(Exn::from)).next();
289                let y = y.transpose()?.unwrap_or_default();
290                let mut b = BytesMut::from(b);
291                bytes_splice(&mut b, skip, take, &y);
292                Ok(Val::Str(b.freeze(), t))
293            }
294            _ => opt.fail(self, |v| Exn::from(Error::typ(v, Type::Arr.as_str()))),
295        }
296    }
297
298    /// True if the value is neither null nor false.
299    fn as_bool(&self) -> bool {
300        !matches!(self, Self::Null | Self::Bool(false))
301    }
302
303    fn into_string(self) -> Self {
304        if let Self::Str(b, _tag) = self {
305            Self::utf8_str(b)
306        } else {
307            Self::utf8_str(self.to_json())
308        }
309    }
310}
311
312impl jaq_std::ValT for Val {
313    fn into_seq<S: FromIterator<Self>>(self) -> Result<S, Self> {
314        match self {
315            Self::Arr(a) => match Rc::try_unwrap(a) {
316                Ok(a) => Ok(a.into_iter().collect()),
317                Err(a) => Ok(a.iter().cloned().collect()),
318            },
319            _ => Err(self),
320        }
321    }
322
323    fn is_int(&self) -> bool {
324        self.as_num().is_some_and(Num::is_int)
325    }
326
327    fn as_isize(&self) -> Option<isize> {
328        self.as_num().and_then(Num::as_isize)
329    }
330
331    fn as_f64(&self) -> Option<f64> {
332        self.as_num().map(Num::as_f64)
333    }
334
335    fn is_utf8_str(&self) -> bool {
336        matches!(self, Self::Str(_, Tag::Utf8))
337    }
338
339    fn as_bytes(&self) -> Option<&[u8]> {
340        if let Self::Str(b, _) = self {
341            Some(b)
342        } else {
343            None
344        }
345    }
346
347    fn as_sub_str(&self, sub: &[u8]) -> Self {
348        match self {
349            Self::Str(b, tag) => Self::Str(b.slice_ref(sub), *tag),
350            _ => panic!(),
351        }
352    }
353
354    fn from_utf8_bytes(b: impl AsRef<[u8]> + Send + 'static) -> Self {
355        Self::Str(Bytes::from_owner(b), Tag::Utf8)
356    }
357}
358
359/// Definitions of the standard library.
360pub fn defs() -> impl Iterator<Item = load::parse::Def<&'static str>> {
361    load::parse(include_str!("defs.jq"), |p| p.defs())
362        .unwrap()
363        .into_iter()
364}
365
366fn skip_take(range: val::Range<num::PosUsize>, len: usize) -> (usize, usize) {
367    let from = abs_bound(range.start, len, 0);
368    let upto = abs_bound(range.end, len, len);
369    (from, upto.saturating_sub(from))
370}
371
372fn skip_take_str(tag: Tag, range: val::Range<num::PosUsize>, b: &[u8]) -> (usize, usize) {
373    let byte_index = |num::PosUsize(pos, c)| {
374        let mut chars = b.char_indices().map(|(start, ..)| start);
375        if pos {
376            chars.nth(c).unwrap_or(b.len())
377        } else {
378            chars.nth_back(c - 1).unwrap_or(0)
379        }
380    };
381    match tag {
382        Tag::Bytes => skip_take(range, b.len()),
383        Tag::Utf8 => {
384            let from_byte = range.start.map_or(0, byte_index);
385            let upto_byte = range.end.map_or(b.len(), byte_index);
386            (from_byte, upto_byte.saturating_sub(from_byte))
387        }
388    }
389}
390
391fn bytes_splice(b: &mut BytesMut, skip: usize, take: usize, replace: &[u8]) {
392    let final_len = b.len() - take + replace.len();
393    let post_take = skip + take..b.len();
394
395    if replace.len() > take {
396        b.resize(final_len, 0);
397    }
398    b.copy_within(post_take, skip + replace.len());
399    b[skip..skip + replace.len()].copy_from_slice(replace);
400    if replace.len() < take {
401        b.truncate(final_len);
402    }
403}
404
405/// If a range bound is given, absolutise and clip it between 0 and `len`,
406/// else return `default`.
407fn abs_bound(i: Option<num::PosUsize>, len: usize, default: usize) -> usize {
408    i.map_or(default, |i| core::cmp::min(i.wrap(len).unwrap_or(0), len))
409}
410
411/// Absolutise an index and return result if it is inside [0, len).
412fn abs_index(i: num::PosUsize, len: usize) -> Option<usize> {
413    i.wrap(len).filter(|i| *i < len)
414}
415
416impl Val {
417    /// Construct an object value.
418    pub fn obj(m: Map) -> Self {
419        Self::Obj(m.into())
420    }
421
422    /// Construct a string that is interpreted as UTF-8.
423    pub fn utf8_str(s: impl Into<Bytes>) -> Self {
424        Self::Str(s.into(), Tag::Utf8)
425    }
426
427    /// Construct a string that is interpreted as bytes.
428    pub fn byte_str(s: impl Into<Bytes>) -> Self {
429        Self::Str(s.into(), Tag::Bytes)
430    }
431
432    fn as_num(&self) -> Option<&Num> {
433        match self {
434            Self::Num(n) => Some(n),
435            _ => None,
436        }
437    }
438
439    /// If the value is an integer in [-usize::MAX, +usize::MAX], return it, else fail.
440    fn as_pos_usize(&self) -> Result<num::PosUsize, Error> {
441        let fail = || Error::typ(self.clone(), Type::Int.as_str());
442        self.as_num().and_then(Num::as_pos_usize).ok_or_else(fail)
443    }
444
445    fn into_str(self, t: Tag) -> Result<Bytes, Error> {
446        match self {
447            Self::Str(b, t_) if t == t_ => Ok(b),
448            _ => Err(Error::typ(self, Type::Str.as_str())),
449        }
450    }
451
452    /// If the value is an array, return it, else fail.
453    fn into_arr(self) -> Result<Rc<Vec<Self>>, Error> {
454        match self {
455            Self::Arr(a) => Ok(a),
456            _ => Err(Error::typ(self, Type::Arr.as_str())),
457        }
458    }
459
460    fn as_arr(&self) -> Result<&Rc<Vec<Self>>, Error> {
461        match self {
462            Self::Arr(a) => Ok(a),
463            _ => Err(Error::typ(self.clone(), Type::Arr.as_str())),
464        }
465    }
466
467    fn range_int(range: val::Range<&Self>) -> Result<val::Range<num::PosUsize>, Error> {
468        let f = |i: Option<&Self>| {
469            i.as_ref()
470                .filter(|i| !matches!(i, Val::Null))
471                .map(|i| i.as_pos_usize())
472                .transpose()
473        };
474        Ok(f(range.start)?..f(range.end)?)
475    }
476
477    fn to_json(&self) -> Vec<u8> {
478        let mut buf = Vec::new();
479        write::write(&mut buf, &write::Pp::default(), 0, self).unwrap();
480        buf
481    }
482}
483
484impl From<bool> for Val {
485    fn from(b: bool) -> Self {
486        Self::Bool(b)
487    }
488}
489
490impl From<isize> for Val {
491    fn from(i: isize) -> Self {
492        Self::Num(Num::Int(i))
493    }
494}
495
496impl From<usize> for Val {
497    fn from(i: usize) -> Self {
498        Self::Num(Num::from_integral(i))
499    }
500}
501
502impl From<f64> for Val {
503    fn from(f: f64) -> Self {
504        Self::Num(Num::Float(f))
505    }
506}
507
508impl From<String> for Val {
509    fn from(s: String) -> Self {
510        Self::Str(Bytes::from_owner(s), Tag::Utf8)
511    }
512}
513
514impl From<val::Range<Val>> for Val {
515    fn from(r: val::Range<Val>) -> Self {
516        let kv = |(k, v): (&str, Option<_>)| v.map(|v| (k.to_owned().into(), v));
517        let kvs = [("start", r.start), ("end", r.end)];
518        Val::obj(kvs.into_iter().flat_map(kv).collect())
519    }
520}
521
522impl FromIterator<Self> for Val {
523    fn from_iter<T: IntoIterator<Item = Self>>(iter: T) -> Self {
524        Self::Arr(Rc::new(iter.into_iter().collect()))
525    }
526}
527
528fn bigint_to_int_saturated(i: &BigInt) -> isize {
529    let (min, max) = (isize::MIN, isize::MAX);
530    i.to_isize()
531        .unwrap_or_else(|| if i.is_negative() { min } else { max })
532}
533
534impl core::ops::Add for Val {
535    type Output = ValR;
536    fn add(self, rhs: Self) -> Self::Output {
537        use Val::*;
538        match (self, rhs) {
539            // `null` is a neutral element for addition
540            (Null, x) | (x, Null) => Ok(x),
541            (Num(x), Num(y)) => Ok(Num(x + y)),
542            (Str(l, tag), Str(r, tag_)) if tag == tag_ => {
543                let mut buf = BytesMut::from(l);
544                buf.put(r);
545                Ok(Str(buf.into(), tag))
546            }
547            (Arr(mut l), Arr(r)) => {
548                //std::dbg!(Rc::strong_count(&l));
549                Rc::make_mut(&mut l).extend(r.iter().cloned());
550                Ok(Arr(l))
551            }
552            (Obj(mut l), Obj(r)) => {
553                Rc::make_mut(&mut l).extend(r.iter().map(|(k, v)| (k.clone(), v.clone())));
554                Ok(Obj(l))
555            }
556            (l, r) => Err(Error::math(l, ops::Math::Add, r)),
557        }
558    }
559}
560
561impl core::ops::Sub for Val {
562    type Output = ValR;
563    fn sub(self, rhs: Self) -> Self::Output {
564        match (self, rhs) {
565            (Self::Num(x), Self::Num(y)) => Ok(Self::Num(x - y)),
566            (Self::Arr(mut l), Self::Arr(r)) => {
567                let r = r.iter().collect::<alloc::collections::BTreeSet<_>>();
568                Rc::make_mut(&mut l).retain(|x| !r.contains(x));
569                Ok(Self::Arr(l))
570            }
571            (l, r) => Err(Error::math(l, ops::Math::Sub, r)),
572        }
573    }
574}
575
576fn obj_merge(l: &mut Rc<Map>, r: Rc<Map>) {
577    let l = Rc::make_mut(l);
578    let r = rc_unwrap_or_clone(r).into_iter();
579    r.for_each(|(k, v)| match (l.get_mut(&k), v) {
580        (Some(Val::Obj(l)), Val::Obj(r)) => obj_merge(l, r),
581        (Some(l), r) => *l = r,
582        (None, r) => {
583            l.insert(k, r);
584        }
585    });
586}
587
588impl core::ops::Mul for Val {
589    type Output = ValR;
590    fn mul(self, rhs: Self) -> Self::Output {
591        use crate::Num::{BigInt, Int};
592        use Val::*;
593        match (self, rhs) {
594            (Num(x), Num(y)) => Ok(Num(x * y)),
595            (s @ Str(..), Num(BigInt(i))) | (Num(BigInt(i)), s @ Str(..)) => {
596                s * Num(Int(bigint_to_int_saturated(&i)))
597            }
598            (Str(s, tag), Num(Int(i))) | (Num(Int(i)), Str(s, tag)) if i > 0 => {
599                Ok(Self::Str(s.repeat(i as usize).into(), tag))
600            }
601            // string multiplication with negatives or 0 results in null
602            // <https://jqlang.github.io/jq/manual/#Builtinoperatorsandfunctions>
603            (Str(..), Num(Int(_))) | (Num(Int(_)), Str(..)) => Ok(Null),
604            (Obj(mut l), Obj(r)) => {
605                obj_merge(&mut l, r);
606                Ok(Obj(l))
607            }
608            (l, r) => Err(Error::math(l, ops::Math::Mul, r)),
609        }
610    }
611}
612
613/// Split a string by a given separator string.
614fn split<'a>(s: &'a [u8], sep: &'a [u8]) -> Box<dyn Iterator<Item = &'a [u8]> + 'a> {
615    if s.is_empty() {
616        Box::new(core::iter::empty())
617    } else if sep.is_empty() {
618        // Rust's `split` function with an empty separator ("")
619        // yields an empty string as first and last result
620        // to prevent this, we are using `chars` instead
621        Box::new(s.char_indices().map(|(start, end, _)| &s[start..end]))
622    } else {
623        Box::new(s.split_str(sep))
624    }
625}
626
627impl core::ops::Div for Val {
628    type Output = ValR;
629    fn div(self, rhs: Self) -> Self::Output {
630        match (self, rhs) {
631            (Self::Num(x), Self::Num(y)) => Ok(Self::Num(x / y)),
632            (Self::Str(x, tag), Self::Str(y, tag_)) if tag == tag_ => Ok(split(&x, &y)
633                .map(|s| Val::Str(x.slice_ref(s), tag))
634                .collect()),
635            (l, r) => Err(Error::math(l, ops::Math::Div, r)),
636        }
637    }
638}
639
640impl core::ops::Rem for Val {
641    type Output = ValR;
642    fn rem(self, rhs: Self) -> Self::Output {
643        match (self, rhs) {
644            (Self::Num(x), Self::Num(y)) if !(x.is_int() && y.is_int() && y == Num::Int(0)) => {
645                Ok(Self::Num(x % y))
646            }
647            (l, r) => Err(Error::math(l, ops::Math::Rem, r)),
648        }
649    }
650}
651
652impl core::ops::Neg for Val {
653    type Output = ValR;
654    fn neg(self) -> Self::Output {
655        match self {
656            Self::Num(n) => Ok(Self::Num(-n)),
657            x => Err(Error::typ(x, Type::Num.as_str())),
658        }
659    }
660}
661
662impl PartialOrd for Val {
663    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
664        Some(self.cmp(other))
665    }
666}
667
668impl Ord for Val {
669    fn cmp(&self, other: &Self) -> Ordering {
670        use Ordering::{Equal, Greater, Less};
671        match (self, other) {
672            (Self::Null, Self::Null) => Equal,
673            (Self::Bool(x), Self::Bool(y)) => x.cmp(y),
674            (Self::Num(x), Self::Num(y)) => x.cmp(y),
675            (Self::Str(x, _), Self::Str(y, _)) => x.cmp(y),
676            (Self::Arr(x), Self::Arr(y)) => x.cmp(y),
677            (Self::Obj(x), Self::Obj(y)) => match (x.len(), y.len()) {
678                (0, 0) => Equal,
679                (0, _) => Less,
680                (_, 0) => Greater,
681                _ => {
682                    let mut l: Vec<_> = x.iter().collect();
683                    let mut r: Vec<_> = y.iter().collect();
684                    l.sort_by_key(|(k, _v)| *k);
685                    r.sort_by_key(|(k, _v)| *k);
686                    // TODO: make this nicer
687                    let kl = l.iter().map(|(k, _v)| k);
688                    let kr = r.iter().map(|(k, _v)| k);
689                    let vl = l.iter().map(|(_k, v)| v);
690                    let vr = r.iter().map(|(_k, v)| v);
691                    kl.cmp(kr).then_with(|| vl.cmp(vr))
692                }
693            },
694
695            // nulls are smaller than anything else
696            (Self::Null, _) => Less,
697            (_, Self::Null) => Greater,
698            // bools are smaller than anything else, except for nulls
699            (Self::Bool(_), _) => Less,
700            (_, Self::Bool(_)) => Greater,
701            // numbers are smaller than anything else, except for nulls and bools
702            (Self::Num(_), _) => Less,
703            (_, Self::Num(_)) => Greater,
704            // etc.
705            (Self::Str(..), _) => Less,
706            (_, Self::Str(..)) => Greater,
707            (Self::Arr(_), _) => Less,
708            (_, Self::Arr(_)) => Greater,
709        }
710    }
711}
712
713impl PartialEq for Val {
714    fn eq(&self, other: &Self) -> bool {
715        match (self, other) {
716            (Self::Null, Self::Null) => true,
717            (Self::Bool(x), Self::Bool(y)) => x == y,
718            (Self::Num(x), Self::Num(y)) => x == y,
719            (Self::Str(x, _tag), Self::Str(y, _)) => x == y,
720            (Self::Arr(x), Self::Arr(y)) => x == y,
721            (Self::Obj(x), Self::Obj(y)) => x == y,
722            _ => false,
723        }
724    }
725}
726
727impl Eq for Val {}
728
729impl Hash for Val {
730    fn hash<H: Hasher>(&self, state: &mut H) {
731        fn hash_with(u: u8, x: impl Hash, state: &mut impl Hasher) {
732            state.write_u8(u);
733            x.hash(state)
734        }
735        match self {
736            Self::Num(n) => n.hash(state),
737            // Num::hash() starts its hash with a 0 or 1, so we start with 2 here
738            Self::Null => state.write_u8(2),
739            Self::Bool(b) => state.write_u8(if *b { 3 } else { 4 }),
740            Self::Str(b, _) => hash_with(5, b, state),
741            Self::Arr(a) => hash_with(6, a, state),
742            Self::Obj(o) => {
743                state.write_u8(7);
744                // this is similar to what happens in `Val::cmp`
745                let mut kvs: Vec<_> = o.iter().collect();
746                kvs.sort_by_key(|(k, _v)| *k);
747                kvs.iter().for_each(|(k, v)| (k, v).hash(state));
748            }
749        }
750    }
751}
752
753/// Display bytes as valid UTF-8 string.
754///
755/// This maps invalid UTF-8 to the Unicode replacement character.
756pub fn bstr(s: &(impl core::convert::AsRef<[u8]> + ?Sized)) -> impl fmt::Display + '_ {
757    BStr::new(s)
758}
759
760impl fmt::Display for Val {
761    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
762        write::format(f, &write::Pp::default(), 0, self)
763    }
764}