1use serde_json::Number;
16
17use crate::{
18 ast::*,
19 json::{ArrayRef, Cow, Json, JsonRef, ObjectRef},
20};
21
22pub type Result<T> = std::result::Result<T, Error>;
23
24#[non_exhaustive]
26#[derive(Debug, thiserror::Error, PartialEq, Eq)]
27pub enum Error {
28 #[error("JSON object does not contain key \"{0}\"")]
30 NoKey(Box<str>),
31 #[error("jsonpath array accessor can only be applied to an array")]
32 ArrayAccess,
33 #[error("jsonpath wildcard array accessor can only be applied to an array")]
34 WildcardArrayAccess,
35 #[error("jsonpath member accessor can only be applied to an object")]
36 MemberAccess,
37 #[error("jsonpath wildcard member accessor can only be applied to an object")]
38 WildcardMemberAccess,
39 #[error("jsonpath array subscript is out of bounds")]
40 ArrayIndexOutOfBounds,
41
42 #[error("jsonpath array subscript is out of integer range")]
43 ArrayIndexOutOfRange,
44 #[error("jsonpath array subscript is not a single numeric value")]
45 ArrayIndexNotNumeric,
46 #[error("could not find jsonpath variable \"{0}\"")]
47 NoVariable(Box<str>),
48 #[error("\"vars\" argument is not an object")]
49 VarsNotObject,
50 #[error("operand of unary jsonpath operator {0} is not a numeric value")]
51 UnaryOperandNotNumeric(UnaryOp),
52 #[error("left operand of jsonpath operator {0} is not a single numeric value")]
53 LeftOperandNotNumeric(BinaryOp),
54 #[error("right operand of jsonpath operator {0} is not a single numeric value")]
55 RightOperandNotNumeric(BinaryOp),
56 #[error("jsonpath item method .{0}() can only be applied to a numeric value")]
57 MethodNotNumeric(&'static str),
58 #[error("jsonpath item method .size() can only be applied to an array")]
59 SizeNotArray,
60 #[error("jsonpath item method .double() can only be applied to a string or numeric value")]
61 DoubleTypeError,
62 #[error("numeric argument of jsonpath item method .double() is out of range for type double precision")]
63 DoubleOutOfRange,
64 #[error("string argument of jsonpath item method .double() is not a valid representation of a double precision number")]
65 InvalidDouble,
66 #[error("jsonpath item method .keyvalue() can only be applied to an object")]
67 KeyValueNotObject,
68 #[error("division by zero")]
69 DivisionByZero,
70 #[error("single boolean result is expected")]
71 ExpectSingleBoolean,
72}
73
74impl Error {
75 pub const fn can_silent(&self) -> bool {
77 !matches!(self, Self::NoVariable(_))
81 }
82
83 pub const fn is_structural(&self) -> bool {
85 matches!(
86 self,
87 Self::NoKey(_)
88 | Self::ArrayAccess
89 | Self::WildcardArrayAccess
90 | Self::MemberAccess
91 | Self::WildcardMemberAccess
92 | Self::ArrayIndexOutOfBounds
93 )
94 }
95}
96
97#[derive(Debug, Clone, Copy, PartialEq, Eq)]
99enum Truth {
100 True,
101 False,
102 Unknown,
103}
104
105impl From<bool> for Truth {
106 fn from(b: bool) -> Self {
107 if b {
108 Truth::True
109 } else {
110 Truth::False
111 }
112 }
113}
114
115impl Truth {
116 fn is_true(self) -> bool {
118 matches!(self, Truth::True)
119 }
120
121 #[allow(unused)]
123 fn is_false(self) -> bool {
124 matches!(self, Truth::False)
125 }
126
127 fn is_unknown(self) -> bool {
129 matches!(self, Truth::Unknown)
130 }
131
132 fn and(self, other: Self) -> Self {
134 match (self, other) {
135 (Truth::True, Truth::True) => Truth::True,
136 (Truth::False, _) | (_, Truth::False) => Truth::False,
137 _ => Truth::Unknown,
138 }
139 }
140
141 fn or(self, other: Self) -> Self {
143 match (self, other) {
144 (Truth::True, _) | (_, Truth::True) => Truth::True,
145 (Truth::False, Truth::False) => Truth::False,
146 _ => Truth::Unknown,
147 }
148 }
149
150 fn not(self) -> Self {
152 match self {
153 Truth::True => Truth::False,
154 Truth::False => Truth::True,
155 Truth::Unknown => Truth::Unknown,
156 }
157 }
158
159 fn merge(self, other: Self) -> Self {
161 match (self, other) {
162 (Truth::Unknown, _) | (_, Truth::Unknown) => Truth::Unknown,
163 (Truth::True, _) | (_, Truth::True) => Truth::True,
164 (Truth::False, Truth::False) => Truth::False,
165 }
166 }
167
168 fn to_json<T: Json>(self) -> T {
170 match self {
171 Truth::True => T::bool(true),
172 Truth::False => T::bool(false),
173 Truth::Unknown => T::null(),
174 }
175 }
176}
177
178impl JsonPath {
179 pub fn query<'a, T: JsonRef<'a>>(&self, value: T) -> Result<Vec<Cow<'a, T::Owned>>> {
181 Evaluator {
182 root: value,
183 current: value,
184 vars: T::null(),
185 array: T::null(),
186 mode: self.mode,
187 first: false,
188 }
189 .eval_expr_or_predicate(&self.expr)
190 }
191
192 pub fn query_with_vars<'a, T: JsonRef<'a>>(
194 &self,
195 value: T,
196 vars: T,
197 ) -> Result<Vec<Cow<'a, T::Owned>>> {
198 if !vars.is_object() {
199 return Err(Error::VarsNotObject);
200 }
201 Evaluator {
202 root: value,
203 current: value,
204 vars,
205 array: T::null(),
206 mode: self.mode,
207 first: false,
208 }
209 .eval_expr_or_predicate(&self.expr)
210 }
211
212 pub fn query_first<'a, T: JsonRef<'a>>(&self, value: T) -> Result<Option<Cow<'a, T::Owned>>> {
214 Evaluator {
215 root: value,
216 current: value,
217 vars: T::null(),
218 array: T::null(),
219 mode: self.mode,
220 first: true,
221 }
222 .eval_expr_or_predicate(&self.expr)
223 .map(|set| set.into_iter().next())
224 }
225
226 pub fn query_first_with_vars<'a, T: JsonRef<'a>>(
228 &self,
229 value: T,
230 vars: T,
231 ) -> Result<Option<Cow<'a, T::Owned>>> {
232 if !vars.is_object() {
233 return Err(Error::VarsNotObject);
234 }
235 Evaluator {
236 root: value,
237 current: value,
238 vars,
239 array: T::null(),
240 mode: self.mode,
241 first: true,
242 }
243 .eval_expr_or_predicate(&self.expr)
244 .map(|set| set.into_iter().next())
245 }
246
247 pub fn exists<'a, T: JsonRef<'a>>(&self, value: T) -> Result<bool> {
249 self.query_first(value).map(|v| v.is_some())
250 }
251
252 pub fn exists_with_vars<'a, T: JsonRef<'a>>(&self, value: T, vars: T) -> Result<bool> {
255 self.query_first_with_vars(value, vars).map(|v| v.is_some())
256 }
257}
258
259#[derive(Debug, Clone, Copy)]
261struct Evaluator<'a, T: Json + 'a> {
262 current: T::Borrowed<'a>,
264 root: T::Borrowed<'a>,
266 array: T::Borrowed<'a>,
268 vars: T::Borrowed<'a>,
270 mode: Mode,
273 first: bool,
275}
276
277macro_rules! lax {
279 ($self:expr, $expr:expr, $err:expr) => {
281 match $expr {
282 Some(x) => x,
283 None if $self.is_lax() => return Ok(vec![]),
284 None => return Err($err),
285 }
286 };
287 ($self:expr, $expr:expr, $err:expr; continue) => {
289 match $expr {
290 Some(x) => x,
291 None if $self.is_lax() => continue,
292 None => return Err($err),
293 }
294 };
295 ($self:expr, $expr:expr, $err:expr; break) => {
297 match $expr {
298 Some(x) => x,
299 None if $self.is_lax() => break,
300 None => return Err($err),
301 }
302 };
303 ($self:expr, $expr:expr) => {
305 match $expr {
306 Ok(x) => x,
307 Err(e @ Error::NoVariable(_)) => return Err(e),
308 Err(_) => return Ok(Truth::Unknown),
309 }
310 };
311}
312
313impl<'a, T: Json> Evaluator<'a, T> {
314 fn is_lax(&self) -> bool {
316 matches!(self.mode, Mode::Lax)
317 }
318
319 fn is_first(&self) -> bool {
321 self.first && self.is_lax()
322 }
323
324 fn with_current<'b>(&self, current: T::Borrowed<'b>) -> Evaluator<'b, T>
326 where
327 'a: 'b,
328 {
329 Evaluator {
330 current,
331 root: T::borrow(self.root),
332 vars: T::borrow(self.vars),
333 array: T::borrow(self.array),
334 mode: self.mode,
335 first: self.first,
336 }
337 }
338
339 fn all(&self) -> Self {
340 Evaluator {
341 first: false,
342 ..*self
343 }
344 }
345
346 fn first(&self) -> Self {
347 Evaluator {
348 first: true,
349 ..*self
350 }
351 }
352
353 fn get_variable(&self, name: &str) -> Result<T::Borrowed<'a>> {
355 self.vars
356 .as_object()
357 .ok_or_else(|| Error::NoVariable(name.into()))?
359 .get(name)
360 .ok_or_else(|| Error::NoVariable(name.into()))
361 }
362
363 fn eval_expr_or_predicate(&self, expr: &ExprOrPredicate) -> Result<Vec<Cow<'a, T>>> {
365 match expr {
366 ExprOrPredicate::Expr(expr) => self.eval_expr(expr),
367 ExprOrPredicate::Pred(pred) => self
368 .eval_predicate(pred)
369 .map(|t| vec![Cow::Owned(t.to_json())]),
370 }
371 }
372
373 fn eval_predicate(&self, pred: &Predicate) -> Result<Truth> {
375 match pred {
376 Predicate::Compare(op, left, right) => {
377 let left = lax!(self, self.all().eval_expr(left));
378 let right = lax!(self, self.all().eval_expr(right));
379
380 let mut result = Truth::False;
381 'product: for r in right.iter() {
384 for l in left.iter() {
385 let res = eval_compare::<T>(*op, l.as_ref(), r.as_ref());
386 result = result.merge(res);
387 if res.is_unknown() || res.is_true() && self.is_lax() {
390 break 'product;
392 }
393 }
395 }
396 Ok(result)
397 }
398 Predicate::Exists(expr) => {
399 let set = lax!(self, self.first().eval_expr(expr));
400 Ok(Truth::from(!set.is_empty()))
403 }
404 Predicate::And(left, right) => {
405 let left = self.eval_predicate(left)?;
406 let right = self.eval_predicate(right)?;
407 Ok(left.and(right))
408 }
409 Predicate::Or(left, right) => {
410 let left = self.eval_predicate(left)?;
411 let right = self.eval_predicate(right)?;
412 Ok(left.or(right))
413 }
414 Predicate::Not(inner) => {
415 let inner = self.eval_predicate(inner)?;
416 Ok(inner.not())
417 }
418 Predicate::IsUnknown(inner) => {
419 let inner = self.eval_predicate(inner)?;
420 Ok(Truth::from(inner.is_unknown()))
421 }
422 Predicate::StartsWith(expr, prefix) => {
423 let set = lax!(self, self.all().eval_expr(expr));
424 let prefix = self.eval_value(prefix)?;
425 let prefix = prefix.as_ref().as_str().unwrap();
426 let mut result = Truth::False;
427 for v in set {
428 let res = match v.as_ref().as_str() {
429 Some(s) => s.starts_with(prefix).into(),
430 None => Truth::Unknown,
431 };
432 result = result.merge(res);
433 if result.is_unknown() || result.is_true() && self.is_lax() {
434 break;
435 }
436 }
437 Ok(result)
438 }
439 Predicate::LikeRegex(expr, regex) => {
440 let set = lax!(self, self.all().eval_expr(expr));
441 let mut result = Truth::False;
442 for v in set {
443 let res = match v.as_ref().as_str() {
444 Some(s) => regex.is_match(s).into(),
445 None => Truth::Unknown,
446 };
447 result = result.merge(res);
448 if result.is_unknown() || result.is_true() && self.is_lax() {
449 break;
450 }
451 }
452 Ok(result)
453 }
454 }
455 }
456
457 fn eval_expr(&self, expr: &Expr) -> Result<Vec<Cow<'a, T>>> {
459 match expr {
460 Expr::PathPrimary(primary) => self.eval_path_primary(primary),
461 Expr::Accessor(base, op) => {
462 let set = self.all().eval_expr(base)?;
463 let mut new_set = vec![];
464 for v in &set {
465 match v {
466 Cow::Owned(v) => {
467 let sset = self.with_current(v.as_ref()).eval_accessor_op(op)?;
468 new_set.extend(
469 sset.into_iter().map(|cow| Cow::Owned(cow.into_owned())),
473 )
474 }
475 Cow::Borrowed(v) => {
476 new_set.extend(self.with_current(*v).eval_accessor_op(op)?);
477 }
478 }
479 if self.is_first() && !new_set.is_empty() {
480 break;
481 }
482 }
483 Ok(new_set)
484 }
485 Expr::UnaryOp(op, expr) => {
486 let set = self.eval_expr(expr)?;
487 let mut new_set = Vec::with_capacity(set.len());
488 for v in set {
489 let v = v.as_ref();
490 if v.is_array() && self.is_lax() {
491 for v in v.as_array().unwrap().list() {
493 new_set.push(Cow::Owned(eval_unary_op(*op, v)?));
494 }
495 } else {
496 new_set.push(Cow::Owned(eval_unary_op(*op, v)?));
497 }
498 }
499 Ok(new_set)
500 }
501 Expr::BinaryOp(op, left, right) => {
502 let left = self.eval_expr(left)?;
503 let right = self.eval_expr(right)?;
504 if left.len() != 1 {
505 return Err(Error::LeftOperandNotNumeric(*op));
506 }
507 if right.len() != 1 {
508 return Err(Error::RightOperandNotNumeric(*op));
509 }
510 let left = if self.is_lax() {
512 if let Some(array) = left[0].as_ref().as_array() {
513 if array.len() != 1 {
514 return Err(Error::LeftOperandNotNumeric(*op));
515 }
516 array.get(0).unwrap()
517 } else {
518 left[0].as_ref()
519 }
520 } else {
521 left[0].as_ref()
522 };
523 let right = if self.is_lax() {
525 if let Some(array) = right[0].as_ref().as_array() {
526 if array.len() != 1 {
527 return Err(Error::RightOperandNotNumeric(*op));
528 }
529 array.get(0).unwrap()
530 } else {
531 right[0].as_ref()
532 }
533 } else {
534 right[0].as_ref()
535 };
536 Ok(vec![Cow::Owned(eval_binary_op(*op, left, right)?)])
537 }
538 }
539 }
540
541 fn eval_path_primary(&self, primary: &PathPrimary) -> Result<Vec<Cow<'a, T>>> {
543 match primary {
544 PathPrimary::Root => Ok(vec![Cow::Borrowed(self.root)]),
545 PathPrimary::Current => Ok(vec![Cow::Borrowed(self.current)]),
546 PathPrimary::Value(v) => Ok(vec![self.eval_value(v)?]),
547 PathPrimary::Last => {
548 let array = self
549 .array
550 .as_array()
551 .expect("LAST is allowed only in array subscripts");
552 Ok(vec![Cow::Owned(T::from_i64(array.len() as i64 - 1))])
553 }
554 PathPrimary::ExprOrPred(expr) => self.eval_expr_or_predicate(expr),
555 }
556 }
557
558 fn eval_accessor_op(&self, op: &AccessorOp) -> Result<Vec<Cow<'a, T>>> {
560 match op {
561 AccessorOp::MemberWildcard => self.eval_member_wildcard(),
562 AccessorOp::DescendantMemberWildcard(levels) => {
563 self.eval_descendant_member_wildcard(levels)
564 }
565 AccessorOp::ElementWildcard => self.eval_element_wildcard(),
566 AccessorOp::Member(name) => self.eval_member(name),
567 AccessorOp::Element(indices) => self.eval_element_accessor(indices),
568 AccessorOp::FilterExpr(pred) => self.eval_filter_expr(pred),
569 AccessorOp::Method(method) => self.eval_method(method),
570 }
571 }
572
573 fn eval_member_wildcard(&self) -> Result<Vec<Cow<'a, T>>> {
574 let set = match self.current.as_array() {
575 Some(array) if self.is_lax() => array.list(),
576 _ => vec![self.current],
577 };
578 let mut new_set = vec![];
579 for v in set {
580 let object = lax!(self, v.as_object(), Error::WildcardMemberAccess);
581 for v in object.list_value() {
582 new_set.push(Cow::Borrowed(v));
583 }
584 }
585 Ok(new_set)
586 }
587
588 fn eval_descendant_member_wildcard(&self, levels: &LevelRange) -> Result<Vec<Cow<'a, T>>> {
589 let mut set = match self.current.as_array() {
590 Some(array) if self.is_lax() => array.list(),
591 _ => vec![self.current],
592 };
593 let mut level_start = vec![0, set.len()];
596 for l in 1..=levels.end() {
597 let last_level_range = level_start[l as usize - 1]..level_start[l as usize];
598 for i in last_level_range {
599 if let Some(object) = set[i].as_object() {
600 set.extend(object.list_value());
601 }
602 }
603 if set.len() == level_start[l as usize] {
604 break;
606 }
607 level_start.push(set.len());
608 }
609 let last_level = level_start.len() - 2;
611 let level_range = levels.to_range(last_level);
612 let set_range = level_start[level_range.start]..level_start[level_range.end];
613 let new_set = set[set_range].iter().cloned().map(Cow::Borrowed).collect();
614 Ok(new_set)
615 }
616
617 fn eval_element_wildcard(&self) -> Result<Vec<Cow<'a, T>>> {
618 if !self.current.is_array() && self.is_lax() {
619 return Ok(vec![Cow::Borrowed(self.current)]);
621 }
622 let array = lax!(self, self.current.as_array(), Error::WildcardArrayAccess);
623 if self.is_first() {
624 return Ok(array.get(0).map(Cow::Borrowed).into_iter().collect());
625 }
626 Ok(array.list().into_iter().map(Cow::Borrowed).collect())
627 }
628
629 fn eval_member(&self, name: &str) -> Result<Vec<Cow<'a, T>>> {
631 let set = match self.current.as_array() {
632 Some(array) if self.is_lax() => array.list(),
633 _ => vec![self.current],
634 };
635 let mut new_set = vec![];
636 for v in set {
637 let object = lax!(self, v.as_object(), Error::MemberAccess);
638 let elem = lax!(self, object.get(name), Error::NoKey(name.into()));
639 new_set.push(Cow::Borrowed(elem));
640 }
641 Ok(new_set)
642 }
643
644 fn eval_element_accessor(&self, indices: &[ArrayIndex]) -> Result<Vec<Cow<'a, T>>> {
646 enum ArrayOrScalar<'a, T: JsonRef<'a>> {
648 Array(T::Array),
649 Scalar(T),
650 }
651 impl<'a, T: JsonRef<'a>> ArrayOrScalar<'a, T> {
652 fn get(&self, index: usize) -> Option<T> {
653 match self {
654 ArrayOrScalar::Array(array) => array.get(index),
655 ArrayOrScalar::Scalar(scalar) if index == 0 => Some(*scalar),
656 _ => None,
657 }
658 }
659 }
660 let array = match self.current.as_array() {
661 Some(array) => ArrayOrScalar::Array(array),
662 None if self.is_lax() => ArrayOrScalar::Scalar(self.current),
663 None => return Err(Error::ArrayAccess),
664 };
665 let mut elems = Vec::with_capacity(indices.len());
666 for index in indices {
667 let eval_index = |expr: &Expr| {
668 let set = Self {
670 array: self.current,
672 ..*self
673 }
674 .eval_expr(expr)?;
675 if set.len() != 1 {
676 return Err(Error::ArrayIndexNotNumeric);
677 }
678 set[0]
679 .as_ref()
680 .as_number()
681 .ok_or(Error::ArrayIndexNotNumeric)?
682 .to_i64()
683 .ok_or(Error::ArrayIndexOutOfRange)
684 };
685 match index {
686 ArrayIndex::Index(expr) => {
687 let index = eval_index(expr)?;
688 let index =
689 lax!(self, index.try_into().ok(), Error::ArrayIndexOutOfBounds; continue);
690 let elem = lax!(self, array.get(index), Error::ArrayIndexOutOfBounds; continue);
691 elems.push(Cow::Borrowed(elem));
692 }
693 ArrayIndex::Slice(begin, end) => {
694 let begin = eval_index(begin)?;
695 let end = eval_index(end)?;
696 let begin: usize = match begin.try_into() {
697 Ok(i) => i,
698 Err(_) if self.is_lax() => 0,
699 Err(_) => return Err(Error::ArrayIndexOutOfBounds),
700 };
701 let end: usize =
702 lax!(self, end.try_into().ok(), Error::ArrayIndexOutOfBounds; continue);
703 if begin > end && !self.is_lax() {
704 return Err(Error::ArrayIndexOutOfBounds);
705 }
706 for i in begin..=end {
707 let elem = lax!(self, array.get(i), Error::ArrayIndexOutOfBounds; break);
708 elems.push(Cow::Borrowed(elem));
709 }
710 }
711 }
712 }
713 Ok(elems)
714 }
715
716 fn eval_filter_expr(&self, pred: &Predicate) -> Result<Vec<Cow<'a, T>>> {
717 let set = match self.current.as_array() {
718 Some(array) if self.is_lax() => array.list(),
719 _ => vec![self.current],
720 };
721 let mut new_set = vec![];
722 for v in set {
723 if self.with_current(v).eval_predicate(pred)?.is_true() {
724 new_set.push(Cow::Borrowed(v));
725 if self.is_first() {
726 break;
727 }
728 }
729 }
730 Ok(new_set)
731 }
732
733 fn eval_method(&self, method: &Method) -> Result<Vec<Cow<'a, T>>> {
735 if self.current.is_array()
737 && self.is_lax()
738 && !matches!(method, Method::Size | Method::Type)
739 {
740 let mut new_set = vec![];
741 for v in self.current.as_array().unwrap().list() {
742 new_set.extend(self.with_current(v).eval_method(method)?);
743 }
744 return Ok(new_set);
745 }
746 match method {
747 Method::Type => self.eval_method_type().map(|v| vec![v]),
748 Method::Size => self.eval_method_size().map(|v| vec![v]),
749 Method::Double => self.eval_method_double().map(|v| vec![v]),
750 Method::Ceiling => self.eval_method_ceiling().map(|v| vec![v]),
751 Method::Floor => self.eval_method_floor().map(|v| vec![v]),
752 Method::Abs => self.eval_method_abs().map(|v| vec![v]),
753 Method::Keyvalue => self.eval_method_keyvalue(),
754 }
755 }
756
757 fn eval_method_type(&self) -> Result<Cow<'a, T>> {
758 let s = if self.current.is_null() {
759 "null"
760 } else if self.current.is_bool() {
761 "boolean"
762 } else if self.current.is_number() {
763 "number"
764 } else if self.current.is_string() {
765 "string"
766 } else if self.current.is_array() {
767 "array"
768 } else if self.current.is_object() {
769 "object"
770 } else {
771 unreachable!()
772 };
773 Ok(Cow::Owned(T::from_string(s)))
774 }
775
776 fn eval_method_size(&self) -> Result<Cow<'a, T>> {
777 let size = if let Some(array) = self.current.as_array() {
778 array.len()
780 } else if self.is_lax() {
781 1
783 } else {
784 return Err(Error::SizeNotArray);
785 };
786 Ok(Cow::Owned(T::from_u64(size as u64)))
787 }
788
789 fn eval_method_double(&self) -> Result<Cow<'a, T>> {
790 if let Some(s) = self.current.as_str() {
791 let n = s.parse::<f64>().map_err(|_| Error::InvalidDouble)?;
792 if n.is_infinite() || n.is_nan() {
793 return Err(Error::InvalidDouble);
794 }
795 Ok(Cow::Owned(T::from_f64(n)))
796 } else if self.current.is_number() {
797 Ok(Cow::Borrowed(self.current))
798 } else {
799 Err(Error::DoubleTypeError)
800 }
801 }
802
803 fn eval_method_ceiling(&self) -> Result<Cow<'a, T>> {
804 let n = self
805 .current
806 .as_number()
807 .ok_or(Error::MethodNotNumeric("ceiling"))?;
808 Ok(Cow::Owned(T::from_number(n.ceil())))
809 }
810
811 fn eval_method_floor(&self) -> Result<Cow<'a, T>> {
812 let n = self
813 .current
814 .as_number()
815 .ok_or(Error::MethodNotNumeric("floor"))?;
816 Ok(Cow::Owned(T::from_number(n.floor())))
817 }
818
819 fn eval_method_abs(&self) -> Result<Cow<'a, T>> {
820 let n = self
821 .current
822 .as_number()
823 .ok_or(Error::MethodNotNumeric("abs"))?;
824 Ok(Cow::Owned(T::from_number(n.abs())))
825 }
826
827 fn eval_method_keyvalue(&self) -> Result<Vec<Cow<'a, T>>> {
828 let object = self.current.as_object().ok_or(Error::KeyValueNotObject)?;
829 Ok(object
830 .list()
831 .into_iter()
832 .map(|(k, v)| {
833 Cow::Owned(T::object([
834 ("key", T::from_string(k)),
835 ("value", v.to_owned()),
836 ("id", T::from_i64(0)), ]))
838 })
839 .collect())
840 }
841
842 fn eval_value(&self, value: &Value) -> Result<Cow<'a, T>> {
844 Ok(match value {
845 Value::Null => Cow::Owned(T::null()),
846 Value::Boolean(b) => Cow::Owned(T::bool(*b)),
847 Value::Number(n) => Cow::Owned(T::from_number(n.clone())),
848 Value::String(s) => Cow::Owned(T::from_string(s)),
849 Value::Variable(v) => Cow::Borrowed(self.get_variable(v)?),
850 })
851 }
852}
853
854fn eval_compare<T: Json>(op: CompareOp, left: T::Borrowed<'_>, right: T::Borrowed<'_>) -> Truth {
858 use CompareOp::*;
859 if left.is_array() || left.is_object() || right.is_array() || right.is_object() {
861 return Truth::Unknown;
862 }
863 if left.is_null() && right.is_null() {
865 return compare_ord(op, (), ()).into();
866 }
867 if left.is_null() || right.is_null() {
868 return (op == CompareOp::Ne).into();
869 }
870 if let (Some(left), Some(right)) = (left.as_bool(), right.as_bool()) {
871 return compare_ord(op, left, right).into();
872 }
873 if let (Some(left), Some(right)) = (left.as_number(), right.as_number()) {
874 return match op {
875 Eq => left.equal(&right),
876 Ne => !left.equal(&right),
877 Gt => right.less_than(&left),
878 Ge => !left.less_than(&right),
879 Lt => left.less_than(&right),
880 Le => !right.less_than(&left),
881 }
882 .into();
883 }
884 if let (Some(left), Some(right)) = (left.as_str(), right.as_str()) {
885 return compare_ord(op, left, right).into();
886 }
887 Truth::Unknown
889}
890
891fn eval_unary_op<T: Json>(op: UnaryOp, value: T::Borrowed<'_>) -> Result<T> {
893 let n = value
894 .as_number()
895 .ok_or_else(|| Error::UnaryOperandNotNumeric(op))?;
896 Ok(match op {
897 UnaryOp::Plus => value.to_owned(),
898 UnaryOp::Minus => T::from_number(n.neg()),
899 })
900}
901
902fn eval_binary_op<T: Json>(
904 op: BinaryOp,
905 left: T::Borrowed<'_>,
906 right: T::Borrowed<'_>,
907) -> Result<T> {
908 let left = left
909 .as_number()
910 .ok_or_else(|| Error::LeftOperandNotNumeric(op))?;
911 let right = right
912 .as_number()
913 .ok_or_else(|| Error::RightOperandNotNumeric(op))?;
914 Ok(T::from_number(match op {
915 BinaryOp::Add => left.add(&right),
916 BinaryOp::Sub => left.sub(&right),
917 BinaryOp::Mul => left.mul(&right),
918 BinaryOp::Div => left.div(&right)?,
919 BinaryOp::Rem => left.rem(&right)?,
920 }))
921}
922
923fn compare_ord<T: Ord>(op: CompareOp, left: T, right: T) -> bool {
925 use CompareOp::*;
926 match op {
927 Eq => left == right,
928 Ne => left != right,
929 Gt => left > right,
930 Ge => left >= right,
931 Lt => left < right,
932 Le => left <= right,
933 }
934}
935
936pub trait NumberExt: Sized {
938 fn equal(&self, other: &Self) -> bool;
939 fn less_than(&self, other: &Self) -> bool;
940 fn neg(&self) -> Self;
941 fn add(&self, other: &Self) -> Self;
942 fn sub(&self, other: &Self) -> Self;
943 fn mul(&self, other: &Self) -> Self;
944 fn div(&self, other: &Self) -> Result<Self>;
945 fn rem(&self, other: &Self) -> Result<Self>;
946 fn ceil(&self) -> Self;
947 fn floor(&self) -> Self;
948 fn abs(&self) -> Self;
949 fn to_i64(&self) -> Option<i64>;
950}
951
952impl NumberExt for Number {
953 fn equal(&self, other: &Self) -> bool {
954 self.as_f64().unwrap() == other.as_f64().unwrap()
957 }
958
959 fn less_than(&self, other: &Self) -> bool {
960 self.as_f64().unwrap() < other.as_f64().unwrap()
961 }
962
963 fn neg(&self) -> Self {
964 if let Some(n) = self.as_i64() {
965 Number::from(-n)
966 } else if let Some(n) = self.as_f64() {
967 Number::from_f64(-n).unwrap()
968 } else {
969 unreachable!()
971 }
972 }
973
974 fn add(&self, other: &Self) -> Self {
975 if let (Some(a), Some(b)) = (self.as_i64(), other.as_i64()) {
976 Number::from(a + b)
977 } else if let (Some(a), Some(b)) = (self.as_f64(), other.as_f64()) {
978 Number::from_f64(a + b).unwrap()
979 } else {
980 unreachable!()
981 }
982 }
983
984 fn sub(&self, other: &Self) -> Self {
985 if let (Some(a), Some(b)) = (self.as_i64(), other.as_i64()) {
986 Number::from(a - b)
987 } else if let (Some(a), Some(b)) = (self.as_f64(), other.as_f64()) {
988 Number::from_f64(a - b).unwrap()
989 } else {
990 unreachable!()
991 }
992 }
993
994 fn mul(&self, other: &Self) -> Self {
995 if let (Some(a), Some(b)) = (self.as_i64(), other.as_i64()) {
996 Number::from(a * b)
997 } else if let (Some(a), Some(b)) = (self.as_f64(), other.as_f64()) {
998 Number::from_f64(a * b).unwrap()
999 } else {
1000 unreachable!()
1001 }
1002 }
1003
1004 fn div(&self, other: &Self) -> Result<Self> {
1005 if let (Some(a), Some(b)) = (self.as_f64(), other.as_f64()) {
1006 if b == 0.0 {
1007 return Err(Error::DivisionByZero);
1008 }
1009 Ok(Number::from_f64(a / b).unwrap())
1010 } else {
1011 unreachable!()
1012 }
1013 }
1014
1015 fn rem(&self, other: &Self) -> Result<Self> {
1016 if let (Some(a), Some(b)) = (self.as_i64(), other.as_i64()) {
1017 if b == 0 {
1018 return Err(Error::DivisionByZero);
1019 }
1020 Ok(Number::from(a % b))
1021 } else if let (Some(a), Some(b)) = (self.as_f64(), other.as_f64()) {
1022 if b == 0.0 {
1023 return Err(Error::DivisionByZero);
1024 }
1025 Ok(Number::from_f64(a % b).unwrap())
1026 } else {
1027 unreachable!()
1028 }
1029 }
1030
1031 fn ceil(&self) -> Self {
1032 if self.is_f64() {
1033 Number::from(self.as_f64().unwrap().ceil() as i64)
1034 } else {
1035 self.clone()
1036 }
1037 }
1038
1039 fn floor(&self) -> Self {
1040 if self.is_f64() {
1041 Number::from(self.as_f64().unwrap().floor() as i64)
1042 } else {
1043 self.clone()
1044 }
1045 }
1046
1047 fn abs(&self) -> Self {
1048 if let Some(n) = self.as_i64() {
1049 Number::from(n.abs())
1050 } else if let Some(n) = self.as_f64() {
1051 Number::from_f64(n.abs()).unwrap()
1052 } else {
1053 unreachable!()
1054 }
1055 }
1056
1057 fn to_i64(&self) -> Option<i64> {
1062 const INT_MIN: i64 = -(1 << 53) + 1;
1063 const INT_MAX: i64 = (1 << 53) - 1;
1064 if let Some(i) = self.as_i64() {
1065 if (INT_MIN..=INT_MAX).contains(&i) {
1066 Some(i)
1067 } else {
1068 None
1069 }
1070 } else if let Some(f) = self.as_f64() {
1071 if (INT_MIN as f64..=INT_MAX as f64).contains(&f) {
1072 Some(f as i64)
1073 } else {
1074 None
1075 }
1076 } else {
1077 unreachable!()
1078 }
1079 }
1080}