Skip to main content

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