1use crate::{read, Error, Num, Tag, Val, ValR, ValX};
2use alloc::{boxed::Box, vec::Vec};
3use bstr::ByteSlice;
4use bytes::{BufMut, Bytes, BytesMut};
5use core::fmt;
6use jaq_core::box_iter::{then, BoxIter};
7use jaq_core::{DataT, Exn, Native, RunPtr};
8use jaq_std::{bome, run, unary, v, Filter, ValT as _};
9
10impl Val {
11 fn length(&self) -> ValR {
16 match self {
17 Val::Null => Ok(Val::from(0usize)),
18 Val::Num(n) => Ok(Val::Num(n.length())),
19 Val::Str(s, Tag::Utf8) => Ok(Val::from(s.chars().count() as isize)),
20 Val::Str(b, Tag::Bytes) => Ok(Val::from(b.len() as isize)),
21 Val::Arr(a) => Ok(Val::from(a.len() as isize)),
22 Val::Obj(o) => Ok(Val::from(o.len() as isize)),
23 Val::Bool(_) => Err(Error::str(format_args!("{self} has no length"))),
24 }
25 }
26
27 fn indices<'a>(&'a self, y: &'a Val) -> Result<Box<dyn Iterator<Item = usize> + 'a>, Error> {
29 match (self, y) {
30 (Val::Str(_, tag @ (Tag::Bytes | Tag::Utf8)), Val::Str(y, tag_))
31 if tag == tag_ && y.is_empty() =>
32 {
33 Ok(Box::new(core::iter::empty()))
34 }
35 (Val::Arr(_), Val::Arr(y)) if y.is_empty() => Ok(Box::new(core::iter::empty())),
36 (Val::Str(x, Tag::Utf8), Val::Str(y, Tag::Utf8)) => {
37 let index = |(i, _, _)| x.get(i..i + y.len());
38 let iw = x.char_indices().map_while(index).enumerate();
39 Ok(Box::new(iw.filter_map(|(i, w)| (w == *y).then_some(i))))
40 }
41 (Val::Str(x, tag @ Tag::Bytes), Val::Str(y, tag_)) if tag == tag_ => {
42 let iw = x.windows(y.len()).enumerate();
43 Ok(Box::new(iw.filter_map(|(i, w)| (w == *y).then_some(i))))
44 }
45 (Val::Arr(x), Val::Arr(y)) => {
46 let iw = x.windows(y.len()).enumerate();
47 Ok(Box::new(iw.filter_map(|(i, w)| (w == **y).then_some(i))))
48 }
49 (Val::Arr(x), y) => {
50 let ix = x.iter().enumerate();
51 Ok(Box::new(ix.filter_map(move |(i, x)| (x == y).then_some(i))))
52 }
53 (x, y) => Err(Error::index(x.clone(), y.clone())),
54 }
55 }
56
57 fn has(&self, key: &Self) -> Result<bool, Error> {
61 match (self, key) {
62 (Self::Str(a, Tag::Bytes), Self::Num(Num::Int(i))) if *i >= 0 => {
63 Ok((*i as usize) < a.len())
64 }
65 (Self::Arr(a), Self::Num(Num::Int(i))) if *i >= 0 => Ok((*i as usize) < a.len()),
66 (a @ (Self::Str(_, Tag::Bytes) | Self::Arr(_)), Self::Num(Num::BigInt(i))) => {
67 a.has(&Self::from(crate::bigint_to_int_saturated(i)))
68 }
69 (Self::Obj(o), k) => Ok(o.contains_key(k)),
70 _ => Err(Error::index(self.clone(), key.clone())),
71 }
72 }
73
74 fn contains(&self, other: &Self) -> bool {
81 match (self, other) {
82 (Self::Str(l, tag), Self::Str(r, tag_)) if tag == tag_ => l.contains_str(r),
83 (Self::Arr(l), Self::Arr(r)) => r.iter().all(|r| l.iter().any(|l| l.contains(r))),
84 (Self::Obj(l), Self::Obj(r)) => r
85 .iter()
86 .all(|(k, r)| l.get(k).is_some_and(|l| l.contains(r))),
87 _ => self == other,
88 }
89 }
90
91 fn to_bytes(&self) -> Result<Bytes, Self> {
92 match self {
93 Val::Num(n) => n
94 .as_isize()
95 .and_then(|i| u8::try_from(i).ok())
96 .map(|u| Bytes::from(Vec::from([u])))
97 .ok_or_else(|| self.clone()),
98 Val::Str(b, _) => Ok(b.clone()),
99 Val::Arr(a) => {
100 let mut buf = BytesMut::new();
101 for x in a.iter() {
102 buf.put(Val::to_bytes(x)?);
103 }
104 Ok(buf.into())
105 }
106 _ => Err(self.clone()),
107 }
108 }
109
110 fn as_bytes_owned(&self) -> Option<Bytes> {
111 if let Self::Str(b, _) = self {
112 Some(b.clone())
113 } else {
114 None
115 }
116 }
117
118 fn as_utf8_bytes_owned(&self) -> Option<Bytes> {
119 self.is_utf8_str().then(|| self.as_bytes_owned()).flatten()
120 }
121
122 pub fn try_as_bytes_owned(&self) -> Result<Bytes, Error> {
124 self.as_bytes_owned()
125 .ok_or_else(|| Error::typ(self.clone(), "string"))
126 }
127
128 pub fn try_as_utf8_bytes_owned(&self) -> Result<Bytes, Error> {
130 self.as_utf8_bytes_owned()
131 .ok_or_else(|| Error::typ(self.clone(), "string"))
132 }
133}
134
135fn bmme<'a>(iter: BoxIter<'a, ValR>) -> BoxIter<'a, ValX> {
137 Box::new(iter.map(|r| r.map_err(Exn::from)))
138}
139
140fn parse_fail(i: &impl fmt::Display, fmt: &str, e: impl fmt::Display) -> Error {
141 Error::str(format_args!("cannot parse {i} as {fmt}: {e}"))
142}
143
144self_cell::self_cell!(
145 struct BytesValRs {
146 owner: Bytes,
147
148 #[not_covariant]
149 dependent: ValRs,
150 }
151);
152
153impl Iterator for BytesValRs {
154 type Item = ValR;
155 fn next(&mut self) -> Option<Self::Item> {
156 self.with_dependent_mut(|_owner, iter| iter.next())
157 }
158}
159
160type ValRs<'a> = BoxIter<'a, ValR>;
161
162pub fn bytes_valrs(b: Bytes, f: impl FnOnce(&[u8]) -> ValRs) -> ValRs<'static> {
164 Box::new(BytesValRs::new(b, |b| f(b)))
165}
166
167pub fn funs<D: for<'a> DataT<V<'a> = Val>>() -> impl Iterator<Item = Filter<Native<D>>> {
169 base().into_vec().into_iter().map(run)
170}
171
172fn base<D: for<'a> DataT<V<'a> = Val>>() -> Box<[Filter<RunPtr<D>>]> {
173 Box::new([
174 ("fromjson", v(0), |cv| {
175 bmme(then(cv.1.try_as_utf8_bytes_owned(), |s| {
176 let fail = move |r: Result<_, _>| r.map_err(|e| parse_fail(&cv.1, "JSON", e));
177 bytes_valrs(s, |s| Box::new(read::parse_many(s).map(fail)))
178 }))
179 }),
180 ("tojson", v(0), |cv| bome(Ok(Val::utf8_str(cv.1.to_json())))),
181 ("tobytes", v(0), |cv| {
182 let pass = |b| Val::Str(b, Tag::Bytes);
183 let fail = |v| Error::str(format_args!("cannot convert {v} to bytes"));
184 bome(cv.1.to_bytes().map(pass).map_err(fail))
185 }),
186 ("length", v(0), |cv| bome(cv.1.length())),
187 ("contains", v(1), |cv| {
188 unary(cv, |x, y| Ok(Val::from(x.contains(&y))))
189 }),
190 ("has", v(1), |cv| unary(cv, |v, k| v.has(&k).map(Val::from))),
191 ("indices", v(1), |cv| {
192 let to_int = |i: usize| Val::from(i as isize);
193 unary(cv, move |x, v| {
194 x.indices(&v).map(|idxs| idxs.map(to_int).collect())
195 })
196 }),
197 ("bsearch", v(1), |cv| {
198 let to_idx = |r: Result<_, _>| r.map_or_else(|i| -1 - i as isize, |i| i as isize);
199 unary(cv, move |a, x| {
200 a.as_arr().map(|a| Val::from(to_idx(a.binary_search(&x))))
201 })
202 }),
203 ])
204}