1use serde_json::Number;
19
20use crate::{
21 ast::*,
22 json::{ArrayRef, Cow, Json, JsonRef, ObjectRef},
23};
24
25pub type Result<T> = std::result::Result<T, Error>;
26
27#[non_exhaustive]
29#[derive(Debug, thiserror::Error, PartialEq, Eq)]
30pub enum Error {
31 #[error("JSON object does not contain key \"{0}\"")]
33 NoKey(Box<str>),
34 #[error("jsonpath array accessor can only be applied to an array")]
35 ArrayAccess,
36 #[error("jsonpath wildcard array accessor can only be applied to an array")]
37 WildcardArrayAccess,
38 #[error("jsonpath member accessor can only be applied to an object")]
39 MemberAccess,
40 #[error("jsonpath wildcard member accessor can only be applied to an object")]
41 WildcardMemberAccess,
42 #[error("jsonpath array subscript is out of bounds")]
43 ArrayIndexOutOfBounds,
44
45 #[error("jsonpath array subscript is out of integer range")]
46 ArrayIndexOutOfRange,
47 #[error("jsonpath array subscript is not a single numeric value")]
48 ArrayIndexNotNumeric,
49 #[error("could not find jsonpath variable \"{0}\"")]
50 NoVariable(Box<str>),
51 #[error("\"vars\" argument is not an object")]
52 VarsNotObject,
53 #[error("operand of unary jsonpath operator {0} is not a numeric value")]
54 UnaryOperandNotNumeric(UnaryOp),
55 #[error("left operand of jsonpath operator {0} is not a single numeric value")]
56 LeftOperandNotNumeric(BinaryOp),
57 #[error("right operand of jsonpath operator {0} is not a single numeric value")]
58 RightOperandNotNumeric(BinaryOp),
59 #[error("jsonpath item method .{0}() can only be applied to a numeric value")]
60 MethodNotNumeric(&'static str),
61 #[error("jsonpath item method .size() can only be applied to an array")]
62 SizeNotArray,
63 #[error("jsonpath item method .double() can only be applied to a string or numeric value")]
64 DoubleTypeError,
65 #[error("numeric argument of jsonpath item method .double() is out of range for type double precision")]
66 DoubleOutOfRange,
67 #[error("string argument of jsonpath item method .double() is not a valid representation of a double precision number")]
68 InvalidDouble,
69 #[error("jsonpath item method .keyvalue() can only be applied to an object")]
70 KeyValueNotObject,
71 #[error("division by zero")]
72 DivisionByZero,
73 #[error("single boolean result is expected")]
74 ExpectSingleBoolean,
75 #[error("jsonpath item method .datetime() can only be applied to a string")]
76 DatetimeNotString,
77 #[error("datetime format is not recognized: {0}")]
78 DatetimeFormatNotRecognized(Box<str>),
79 #[error("datetime format is zoned but not timed")]
80 DatetimeZonedNotTimed,
81 #[error("invalid datetime input: {0}")]
82 InvalidDatetimeInput(Box<str>),
83 #[error("invalid datetime format separator: {0}")]
84 DatetimeInvalidSeparator(Box<str>),
85 #[error("invalid value {0} for {1}")]
86 DatetimeInvalidValue(Box<str>, Box<str>),
87 #[error("trailing characters remain in input string after datetime format")]
88 DatetimeTrailingInput,
89 #[error("unmatched format character {0}")]
90 DatetimeUnmatchedChar(Box<str>),
91 #[error("input string is too short for datetime format")]
92 DatetimeInputTooShort,
93 #[error("cannot convert value from {0} to {1} without time zone usage")]
94 DatetimeConvertWithoutTz(Box<str>, Box<str>),
95 #[error("invalid datetime template: {0}")]
96 InvalidDatetimeTemplate(Box<str>),
97 #[error("template directive {0} is not supported by jsonpath")]
98 UnsupportedDatetimeDirective(Box<str>),
99}
100
101impl Error {
102 pub const fn can_silent(&self) -> bool {
103 !matches!(
104 self,
105 Self::NoVariable(_) | Self::DatetimeConvertWithoutTz(_, _)
106 )
107 }
108
109 pub const fn is_structural(&self) -> bool {
111 matches!(
112 self,
113 Self::NoKey(_)
114 | Self::ArrayAccess
115 | Self::WildcardArrayAccess
116 | Self::MemberAccess
117 | Self::WildcardMemberAccess
118 | Self::ArrayIndexOutOfBounds
119 )
120 }
121}
122
123#[derive(Debug, Clone, Copy, PartialEq, Eq)]
125enum Truth {
126 True,
127 False,
128 Unknown,
129}
130
131impl From<bool> for Truth {
132 fn from(b: bool) -> Self {
133 if b {
134 Truth::True
135 } else {
136 Truth::False
137 }
138 }
139}
140
141impl Truth {
142 fn is_true(self) -> bool {
144 matches!(self, Truth::True)
145 }
146
147 #[allow(unused)]
149 fn is_false(self) -> bool {
150 matches!(self, Truth::False)
151 }
152
153 fn is_unknown(self) -> bool {
155 matches!(self, Truth::Unknown)
156 }
157
158 fn and(self, other: Self) -> Self {
160 match (self, other) {
161 (Truth::True, Truth::True) => Truth::True,
162 (Truth::False, _) | (_, Truth::False) => Truth::False,
163 _ => Truth::Unknown,
164 }
165 }
166
167 fn or(self, other: Self) -> Self {
169 match (self, other) {
170 (Truth::True, _) | (_, Truth::True) => Truth::True,
171 (Truth::False, Truth::False) => Truth::False,
172 _ => Truth::Unknown,
173 }
174 }
175
176 fn not(self) -> Self {
178 match self {
179 Truth::True => Truth::False,
180 Truth::False => Truth::True,
181 Truth::Unknown => Truth::Unknown,
182 }
183 }
184
185 fn merge(self, other: Self) -> Self {
186 match (self, other) {
187 (Truth::True, _) | (_, Truth::True) => Truth::True,
188 (Truth::Unknown, _) | (_, Truth::Unknown) => Truth::Unknown,
189 (Truth::False, Truth::False) => Truth::False,
190 }
191 }
192
193 fn to_json<T: Json>(self) -> T {
195 match self {
196 Truth::True => T::bool(true),
197 Truth::False => T::bool(false),
198 Truth::Unknown => T::null(),
199 }
200 }
201}
202
203fn unwrap_datetime_markers<'a, T: JsonRef<'a>>(
204 set: Vec<Cow<'a, T::Owned>>,
205) -> Vec<Cow<'a, T::Owned>> {
206 let mut out = Vec::with_capacity(set.len());
207 for c in set {
208 let owned = c.into_owned();
209 let is_marker = check_marker::<T::Owned>(&owned);
210 if let Some(iso) = is_marker {
211 out.push(Cow::Owned(<T::Owned as crate::json::Json>::from_string(
212 &iso,
213 )));
214 } else {
215 out.push(Cow::Owned(owned));
216 }
217 }
218 out
219}
220
221fn check_marker<J: crate::json::Json>(v: &J) -> Option<String> {
222 crate::datetime::extract_marker(v.as_ref()).map(|(iso, _)| iso)
223}
224
225impl JsonPath {
226 pub fn query<'a, T: JsonRef<'a>>(&self, value: T) -> Result<Vec<Cow<'a, T::Owned>>> {
228 Evaluator {
229 root: value,
230 current: value,
231 vars: T::null(),
232 array: T::null(),
233 mode: self.mode,
234 first: false,
235 use_tz: false,
236 silent: false,
237 }
238 .eval_expr_or_predicate(&self.expr)
239 .map(unwrap_datetime_markers::<T>)
240 }
241
242 pub fn query_with_vars<'a, T: JsonRef<'a>>(
244 &self,
245 value: T,
246 vars: T,
247 ) -> Result<Vec<Cow<'a, T::Owned>>> {
248 if !vars.is_object() {
249 return Err(Error::VarsNotObject);
250 }
251 Evaluator {
252 root: value,
253 current: value,
254 vars,
255 array: T::null(),
256 mode: self.mode,
257 first: false,
258 use_tz: false,
259 silent: false,
260 }
261 .eval_expr_or_predicate(&self.expr)
262 .map(unwrap_datetime_markers::<T>)
263 }
264
265 pub fn query_first<'a, T: JsonRef<'a>>(&self, value: T) -> Result<Option<Cow<'a, T::Owned>>> {
267 Evaluator {
268 root: value,
269 current: value,
270 vars: T::null(),
271 array: T::null(),
272 mode: self.mode,
273 first: true,
274 use_tz: false,
275 silent: false,
276 }
277 .eval_expr_or_predicate(&self.expr)
278 .map(unwrap_datetime_markers::<T>)
279 .map(|set| set.into_iter().next())
280 }
281
282 pub fn query_first_with_vars<'a, T: JsonRef<'a>>(
284 &self,
285 value: T,
286 vars: T,
287 ) -> Result<Option<Cow<'a, T::Owned>>> {
288 if !vars.is_object() {
289 return Err(Error::VarsNotObject);
290 }
291 Evaluator {
292 root: value,
293 current: value,
294 vars,
295 array: T::null(),
296 mode: self.mode,
297 first: true,
298 use_tz: false,
299 silent: false,
300 }
301 .eval_expr_or_predicate(&self.expr)
302 .map(unwrap_datetime_markers::<T>)
303 .map(|set| set.into_iter().next())
304 }
305
306 pub fn exists<'a, T: JsonRef<'a>>(&self, value: T) -> Result<bool> {
308 self.query_first(value).map(|v| v.is_some())
309 }
310
311 pub fn exists_with_vars<'a, T: JsonRef<'a>>(&self, value: T, vars: T) -> Result<bool> {
314 self.query_first_with_vars(value, vars).map(|v| v.is_some())
315 }
316
317 pub fn query_tz<'a, T: JsonRef<'a>>(&self, value: T) -> Result<Vec<Cow<'a, T::Owned>>> {
320 Evaluator {
321 root: value,
322 current: value,
323 vars: T::null(),
324 array: T::null(),
325 mode: self.mode,
326 first: false,
327 use_tz: true,
328 silent: false,
329 }
330 .eval_expr_or_predicate(&self.expr)
331 .map(unwrap_datetime_markers::<T>)
332 }
333
334 pub fn query_with_vars_tz<'a, T: JsonRef<'a>>(
335 &self,
336 value: T,
337 vars: T,
338 ) -> Result<Vec<Cow<'a, T::Owned>>> {
339 if !vars.is_object() {
340 return Err(Error::VarsNotObject);
341 }
342 Evaluator {
343 root: value,
344 current: value,
345 vars,
346 array: T::null(),
347 mode: self.mode,
348 first: false,
349 use_tz: true,
350 silent: false,
351 }
352 .eval_expr_or_predicate(&self.expr)
353 .map(unwrap_datetime_markers::<T>)
354 }
355
356 pub fn query_first_tz<'a, T: JsonRef<'a>>(
357 &self,
358 value: T,
359 ) -> Result<Option<Cow<'a, T::Owned>>> {
360 Evaluator {
361 root: value,
362 current: value,
363 vars: T::null(),
364 array: T::null(),
365 mode: self.mode,
366 first: true,
367 use_tz: true,
368 silent: false,
369 }
370 .eval_expr_or_predicate(&self.expr)
371 .map(unwrap_datetime_markers::<T>)
372 .map(|set| set.into_iter().next())
373 }
374
375 pub fn query_first_with_vars_tz<'a, T: JsonRef<'a>>(
376 &self,
377 value: T,
378 vars: T,
379 ) -> Result<Option<Cow<'a, T::Owned>>> {
380 if !vars.is_object() {
381 return Err(Error::VarsNotObject);
382 }
383 Evaluator {
384 root: value,
385 current: value,
386 vars,
387 array: T::null(),
388 mode: self.mode,
389 first: true,
390 use_tz: true,
391 silent: false,
392 }
393 .eval_expr_or_predicate(&self.expr)
394 .map(unwrap_datetime_markers::<T>)
395 .map(|set| set.into_iter().next())
396 }
397
398 pub fn exists_tz<'a, T: JsonRef<'a>>(&self, value: T) -> Result<bool> {
399 self.query_first_tz(value).map(|v| v.is_some())
400 }
401
402 pub fn exists_with_vars_tz<'a, T: JsonRef<'a>>(&self, value: T, vars: T) -> Result<bool> {
403 self.query_first_with_vars_tz(value, vars)
404 .map(|v| v.is_some())
405 }
406
407 pub fn query_silent<'a, T: JsonRef<'a>>(&self, value: T) -> Result<Vec<Cow<'a, T::Owned>>> {
410 Evaluator {
411 root: value,
412 current: value,
413 vars: T::null(),
414 array: T::null(),
415 mode: self.mode,
416 first: false,
417 use_tz: false,
418 silent: true,
419 }
420 .eval_expr_or_predicate(&self.expr)
421 .map(unwrap_datetime_markers::<T>)
422 }
423
424 pub fn query_with_vars_silent<'a, T: JsonRef<'a>>(
425 &self,
426 value: T,
427 vars: T,
428 ) -> Result<Vec<Cow<'a, T::Owned>>> {
429 if !vars.is_object() {
430 return Err(Error::VarsNotObject);
431 }
432 Evaluator {
433 root: value,
434 current: value,
435 vars,
436 array: T::null(),
437 mode: self.mode,
438 first: false,
439 use_tz: false,
440 silent: true,
441 }
442 .eval_expr_or_predicate(&self.expr)
443 .map(unwrap_datetime_markers::<T>)
444 }
445
446 pub fn query_first_silent<'a, T: JsonRef<'a>>(
447 &self,
448 value: T,
449 ) -> Result<Option<Cow<'a, T::Owned>>> {
450 Evaluator {
451 root: value,
452 current: value,
453 vars: T::null(),
454 array: T::null(),
455 mode: self.mode,
456 first: true,
457 use_tz: false,
458 silent: true,
459 }
460 .eval_expr_or_predicate(&self.expr)
461 .map(unwrap_datetime_markers::<T>)
462 .map(|set| set.into_iter().next())
463 }
464
465 pub fn query_first_with_vars_silent<'a, T: JsonRef<'a>>(
466 &self,
467 value: T,
468 vars: T,
469 ) -> Result<Option<Cow<'a, T::Owned>>> {
470 if !vars.is_object() {
471 return Err(Error::VarsNotObject);
472 }
473 Evaluator {
474 root: value,
475 current: value,
476 vars,
477 array: T::null(),
478 mode: self.mode,
479 first: true,
480 use_tz: false,
481 silent: true,
482 }
483 .eval_expr_or_predicate(&self.expr)
484 .map(unwrap_datetime_markers::<T>)
485 .map(|set| set.into_iter().next())
486 }
487
488 pub fn exists_silent<'a, T: JsonRef<'a>>(&self, value: T) -> Result<bool> {
489 self.query_silent(value).map(|set| !set.is_empty())
490 }
491
492 pub fn exists_with_vars_silent<'a, T: JsonRef<'a>>(&self, value: T, vars: T) -> Result<bool> {
493 self.query_with_vars_silent(value, vars)
494 .map(|set| !set.is_empty())
495 }
496}
497
498#[derive(Debug, Clone, Copy)]
500struct Evaluator<'a, T: Json + 'a> {
501 current: T::Borrowed<'a>,
503 root: T::Borrowed<'a>,
505 array: T::Borrowed<'a>,
507 vars: T::Borrowed<'a>,
509 mode: Mode,
512 first: bool,
514 use_tz: bool,
515 silent: bool,
516}
517
518macro_rules! lax {
520 ($self:expr, $expr:expr, $err:expr) => {
522 match $expr {
523 Some(x) => x,
524 None if $self.is_lax() => return Ok(vec![]),
525 None => return Err($err),
526 }
527 };
528 ($self:expr, $expr:expr, $err:expr; continue) => {
530 match $expr {
531 Some(x) => x,
532 None if $self.is_lax() => continue,
533 None => return Err($err),
534 }
535 };
536 ($self:expr, $expr:expr, $err:expr; break) => {
538 match $expr {
539 Some(x) => x,
540 None if $self.is_lax() => break,
541 None => return Err($err),
542 }
543 };
544 ($self:expr, $expr:expr) => {
546 match $expr {
547 Ok(x) => x,
548 Err(e @ Error::NoVariable(_)) => return Err(e),
549 Err(_) => return Ok(Truth::Unknown),
550 }
551 };
552}
553
554impl<'a, T: Json> Evaluator<'a, T> {
555 fn is_lax(&self) -> bool {
557 matches!(self.mode, Mode::Lax)
558 }
559
560 fn is_first(&self) -> bool {
562 self.first && self.is_lax()
563 }
564
565 fn with_current<'b>(&self, current: T::Borrowed<'b>) -> Evaluator<'b, T>
567 where
568 'a: 'b,
569 {
570 Evaluator {
571 current,
572 root: T::borrow(self.root),
573 vars: T::borrow(self.vars),
574 array: T::borrow(self.array),
575 mode: self.mode,
576 first: self.first,
577 use_tz: self.use_tz,
578 silent: self.silent,
579 }
580 }
581
582 fn all(&self) -> Self {
583 Evaluator {
584 first: false,
585 ..*self
586 }
587 }
588
589 fn first(&self) -> Self {
590 Evaluator {
591 first: true,
592 ..*self
593 }
594 }
595
596 fn get_variable(&self, name: &str) -> Result<T::Borrowed<'a>> {
598 self.vars
599 .as_object()
600 .ok_or_else(|| Error::NoVariable(name.into()))?
602 .get(name)
603 .ok_or_else(|| Error::NoVariable(name.into()))
604 }
605
606 fn eval_expr_or_predicate(&self, expr: &ExprOrPredicate) -> Result<Vec<Cow<'a, T>>> {
608 match expr {
609 ExprOrPredicate::Expr(expr) => self.eval_expr(expr),
610 ExprOrPredicate::Pred(pred) => self
611 .eval_predicate(pred)
612 .map(|t| vec![Cow::Owned(t.to_json())]),
613 }
614 }
615
616 fn eval_predicate(&self, pred: &Predicate) -> Result<Truth> {
618 match pred {
619 Predicate::Compare(op, left, right) => {
620 let left = lax!(self, self.all().eval_expr(left));
621 let right = lax!(self, self.all().eval_expr(right));
622
623 let mut result = Truth::False;
624 'product: for r in right.iter() {
627 for l in left.iter() {
628 let res = eval_compare::<T>(*op, l.as_ref(), r.as_ref(), self.use_tz)?;
629 if res.is_unknown() && !self.is_lax() {
630 return Ok(Truth::Unknown);
631 }
632 result = result.merge(res);
633 if result.is_true() && self.is_lax() {
634 break 'product;
635 }
636 }
637 }
638 Ok(result)
639 }
640 Predicate::Exists(expr) => {
641 let set = lax!(self, self.first().eval_expr(expr));
642 Ok(Truth::from(!set.is_empty()))
645 }
646 Predicate::And(left, right) => {
647 let left = self.eval_predicate(left)?;
648 let right = self.eval_predicate(right)?;
649 Ok(left.and(right))
650 }
651 Predicate::Or(left, right) => {
652 let left = self.eval_predicate(left)?;
653 let right = self.eval_predicate(right)?;
654 Ok(left.or(right))
655 }
656 Predicate::Not(inner) => {
657 let inner = self.eval_predicate(inner)?;
658 Ok(inner.not())
659 }
660 Predicate::IsUnknown(inner) => {
661 let inner = self.eval_predicate(inner)?;
662 Ok(Truth::from(inner.is_unknown()))
663 }
664 Predicate::StartsWith(expr, prefix) => {
665 let set = lax!(self, self.all().eval_expr(expr));
666 let prefix = self.eval_value(prefix)?;
667 let prefix = prefix.as_ref().as_str().unwrap();
668 let mut result = Truth::False;
669 for v in set {
670 let res = match v.as_ref().as_str() {
671 Some(s) => s.starts_with(prefix).into(),
672 None => Truth::Unknown,
673 };
674 if res.is_unknown() && !self.is_lax() {
675 return Ok(Truth::Unknown);
676 }
677 result = result.merge(res);
678 if result.is_true() && self.is_lax() {
679 break;
680 }
681 }
682 Ok(result)
683 }
684 Predicate::LikeRegex(expr, regex) => {
685 let set = lax!(self, self.all().eval_expr(expr));
686 let mut result = Truth::False;
687 for v in set {
688 let res = match v.as_ref().as_str() {
689 Some(s) => regex.is_match(s).into(),
690 None => Truth::Unknown,
691 };
692 if res.is_unknown() && !self.is_lax() {
693 return Ok(Truth::Unknown);
694 }
695 result = result.merge(res);
696 if result.is_true() && self.is_lax() {
697 break;
698 }
699 }
700 Ok(result)
701 }
702 }
703 }
704
705 fn eval_expr(&self, expr: &Expr) -> Result<Vec<Cow<'a, T>>> {
707 match expr {
708 Expr::PathPrimary(primary) => self.eval_path_primary(primary),
709 Expr::Accessor(base, op) => {
710 let set = self.all().eval_expr(base)?;
711 let mut new_set = vec![];
712 for v in &set {
713 match v {
714 Cow::Owned(v) => {
715 let sset = self.with_current(v.as_ref()).eval_accessor_op(op)?;
716 new_set.extend(
717 sset.into_iter().map(|cow| Cow::Owned(cow.into_owned())),
721 )
722 }
723 Cow::Borrowed(v) => {
724 new_set.extend(self.with_current(*v).eval_accessor_op(op)?);
725 }
726 }
727 if self.is_first() && !new_set.is_empty() {
728 break;
729 }
730 }
731 Ok(new_set)
732 }
733 Expr::UnaryOp(op, expr) => {
734 let set = self.eval_expr(expr)?;
735 let mut new_set = Vec::with_capacity(set.len());
736 let item_skip = self.silent && self.is_lax();
737 'outer: for v in set {
738 let v = v.as_ref();
739 if v.is_array() && self.is_lax() {
740 for v in v.as_array().unwrap().list() {
741 match eval_unary_op(*op, v) {
742 Ok(r) => new_set.push(Cow::Owned(r)),
743 Err(_) if item_skip => break 'outer,
744 Err(e) => return Err(e),
745 }
746 }
747 } else {
748 match eval_unary_op(*op, v) {
749 Ok(r) => new_set.push(Cow::Owned(r)),
750 Err(e) if item_skip && e.can_silent() => continue,
751 Err(e) => return Err(e),
752 }
753 }
754 }
755 Ok(new_set)
756 }
757 Expr::BinaryOp(op, left, right) => {
758 let left = self.eval_expr(left)?;
759 let right = self.eval_expr(right)?;
760 if left.len() != 1 {
761 return Err(Error::LeftOperandNotNumeric(*op));
762 }
763 if right.len() != 1 {
764 return Err(Error::RightOperandNotNumeric(*op));
765 }
766 let left = if self.is_lax() {
768 if let Some(array) = left[0].as_ref().as_array() {
769 if array.len() != 1 {
770 return Err(Error::LeftOperandNotNumeric(*op));
771 }
772 array.get(0).unwrap()
773 } else {
774 left[0].as_ref()
775 }
776 } else {
777 left[0].as_ref()
778 };
779 let right = if self.is_lax() {
781 if let Some(array) = right[0].as_ref().as_array() {
782 if array.len() != 1 {
783 return Err(Error::RightOperandNotNumeric(*op));
784 }
785 array.get(0).unwrap()
786 } else {
787 right[0].as_ref()
788 }
789 } else {
790 right[0].as_ref()
791 };
792 Ok(vec![Cow::Owned(eval_binary_op(*op, left, right)?)])
793 }
794 }
795 }
796
797 fn eval_path_primary(&self, primary: &PathPrimary) -> Result<Vec<Cow<'a, T>>> {
799 match primary {
800 PathPrimary::Root => Ok(vec![Cow::Borrowed(self.root)]),
801 PathPrimary::Current => Ok(vec![Cow::Borrowed(self.current)]),
802 PathPrimary::Value(v) => Ok(vec![self.eval_value(v)?]),
803 PathPrimary::Last => {
804 let array = self
805 .array
806 .as_array()
807 .expect("LAST is allowed only in array subscripts");
808 Ok(vec![Cow::Owned(T::from_i64(array.len() as i64 - 1))])
809 }
810 PathPrimary::ExprOrPred(expr) => self.eval_expr_or_predicate(expr),
811 }
812 }
813
814 fn eval_accessor_op(&self, op: &AccessorOp) -> Result<Vec<Cow<'a, T>>> {
816 match op {
817 AccessorOp::MemberWildcard => self.eval_member_wildcard(),
818 AccessorOp::DescendantMemberWildcard(levels) => {
819 self.eval_descendant_member_wildcard(levels)
820 }
821 AccessorOp::ElementWildcard => self.eval_element_wildcard(),
822 AccessorOp::Member(name) => self.eval_member(name),
823 AccessorOp::Element(indices) => self.eval_element_accessor(indices),
824 AccessorOp::FilterExpr(pred) => self.eval_filter_expr(pred),
825 AccessorOp::Method(method) => self.eval_method(method),
826 }
827 }
828
829 fn eval_member_wildcard(&self) -> Result<Vec<Cow<'a, T>>> {
830 let set = match self.current.as_array() {
831 Some(array) if self.is_lax() => array.list(),
832 _ => vec![self.current],
833 };
834 let mut new_set = vec![];
835 for v in set {
836 let object = lax!(self, v.as_object(), Error::WildcardMemberAccess);
837 for v in object.list_value() {
838 new_set.push(Cow::Borrowed(v));
839 }
840 }
841 Ok(new_set)
842 }
843
844 fn eval_descendant_member_wildcard(&self, levels: &LevelRange) -> Result<Vec<Cow<'a, T>>> {
845 let mut set = match self.current.as_array() {
846 Some(array) if self.is_lax() => array.list(),
847 _ => vec![self.current],
848 };
849 let mut level_start = vec![0, set.len()];
852 for l in 1..=levels.end() {
853 let last_level_range = level_start[l as usize - 1]..level_start[l as usize];
854 for i in last_level_range {
855 if let Some(object) = set[i].as_object() {
856 set.extend(object.list_value());
857 }
858 }
859 if set.len() == level_start[l as usize] {
860 break;
862 }
863 level_start.push(set.len());
864 }
865 let last_level = level_start.len() - 2;
867 let level_range = levels.to_range(last_level);
868 let set_range = level_start[level_range.start]..level_start[level_range.end];
869 let new_set = set[set_range].iter().cloned().map(Cow::Borrowed).collect();
870 Ok(new_set)
871 }
872
873 fn eval_element_wildcard(&self) -> Result<Vec<Cow<'a, T>>> {
874 if !self.current.is_array() && self.is_lax() {
875 return Ok(vec![Cow::Borrowed(self.current)]);
877 }
878 let array = lax!(self, self.current.as_array(), Error::WildcardArrayAccess);
879 if self.is_first() && !self.silent {
880 return Ok(array.get(0).map(Cow::Borrowed).into_iter().collect());
881 }
882 Ok(array.list().into_iter().map(Cow::Borrowed).collect())
883 }
884
885 fn eval_member(&self, name: &str) -> Result<Vec<Cow<'a, T>>> {
887 let set = match self.current.as_array() {
888 Some(array) if self.is_lax() => array.list(),
889 _ => vec![self.current],
890 };
891 let mut new_set = vec![];
892 for v in set {
893 let object = match v.as_object() {
894 Some(o) => o,
895 None if self.is_lax() => return Ok(vec![]),
896 None => return Err(Error::MemberAccess),
897 };
898 let elem = match object.get(name) {
899 Some(e) => e,
900 None if self.silent && self.first => continue,
901 None if self.is_lax() => return Ok(vec![]),
902 None => return Err(Error::NoKey(name.into())),
903 };
904 new_set.push(Cow::Borrowed(elem));
905 }
906 Ok(new_set)
907 }
908
909 fn eval_element_accessor(&self, indices: &[ArrayIndex]) -> Result<Vec<Cow<'a, T>>> {
911 enum ArrayOrScalar<'a, T: JsonRef<'a>> {
913 Array(T::Array),
914 Scalar(T),
915 }
916 impl<'a, T: JsonRef<'a>> ArrayOrScalar<'a, T> {
917 fn get(&self, index: usize) -> Option<T> {
918 match self {
919 ArrayOrScalar::Array(array) => array.get(index),
920 ArrayOrScalar::Scalar(scalar) if index == 0 => Some(*scalar),
921 _ => None,
922 }
923 }
924 }
925 let array = match self.current.as_array() {
926 Some(array) => ArrayOrScalar::Array(array),
927 None if self.is_lax() => ArrayOrScalar::Scalar(self.current),
928 None => return Err(Error::ArrayAccess),
929 };
930 let mut elems = Vec::with_capacity(indices.len());
931 for index in indices {
932 let eval_index = |expr: &Expr| {
933 let set = Self {
935 array: self.current,
937 ..*self
938 }
939 .eval_expr(expr)?;
940 if set.len() != 1 {
941 return Err(Error::ArrayIndexNotNumeric);
942 }
943 set[0]
944 .as_ref()
945 .as_number()
946 .ok_or(Error::ArrayIndexNotNumeric)?
947 .to_i64()
948 .ok_or(Error::ArrayIndexOutOfRange)
949 };
950 match index {
951 ArrayIndex::Index(expr) => {
952 let index = eval_index(expr)?;
953 let index =
954 lax!(self, index.try_into().ok(), Error::ArrayIndexOutOfBounds; continue);
955 let elem = lax!(self, array.get(index), Error::ArrayIndexOutOfBounds; continue);
956 elems.push(Cow::Borrowed(elem));
957 }
958 ArrayIndex::Slice(begin, end) => {
959 let begin = eval_index(begin)?;
960 let end = eval_index(end)?;
961 let begin: usize = match begin.try_into() {
962 Ok(i) => i,
963 Err(_) if self.is_lax() => 0,
964 Err(_) => return Err(Error::ArrayIndexOutOfBounds),
965 };
966 let end: usize =
967 lax!(self, end.try_into().ok(), Error::ArrayIndexOutOfBounds; continue);
968 if begin > end && !self.is_lax() {
969 return Err(Error::ArrayIndexOutOfBounds);
970 }
971 for i in begin..=end {
972 let elem = lax!(self, array.get(i), Error::ArrayIndexOutOfBounds; break);
973 elems.push(Cow::Borrowed(elem));
974 }
975 }
976 }
977 }
978 Ok(elems)
979 }
980
981 fn eval_filter_expr(&self, pred: &Predicate) -> Result<Vec<Cow<'a, T>>> {
982 let set = match self.current.as_array() {
983 Some(array) if self.is_lax() => array.list(),
984 _ => vec![self.current],
985 };
986 let mut new_set = vec![];
987 for v in set {
988 if self.with_current(v).eval_predicate(pred)?.is_true() {
989 new_set.push(Cow::Borrowed(v));
990 if self.is_first() {
991 break;
992 }
993 }
994 }
995 Ok(new_set)
996 }
997
998 fn eval_method(&self, method: &Method) -> Result<Vec<Cow<'a, T>>> {
1000 if self.current.is_array()
1002 && self.is_lax()
1003 && !matches!(method, Method::Size | Method::Type)
1004 {
1005 let mut new_set = vec![];
1006 for v in self.current.as_array().unwrap().list() {
1007 new_set.extend(self.with_current(v).eval_method(method)?);
1008 }
1009 return Ok(new_set);
1010 }
1011 match method {
1012 Method::Type => self.eval_method_type().map(|v| vec![v]),
1013 Method::Size => self.eval_method_size().map(|v| vec![v]),
1014 Method::Double => self.eval_method_double().map(|v| vec![v]),
1015 Method::Ceiling => self.eval_method_ceiling().map(|v| vec![v]),
1016 Method::Floor => self.eval_method_floor().map(|v| vec![v]),
1017 Method::Abs => self.eval_method_abs().map(|v| vec![v]),
1018 Method::Keyvalue => self.eval_method_keyvalue(),
1019 Method::Datetime { template } => self
1020 .eval_method_datetime(template.as_deref())
1021 .map(|v| vec![v]),
1022 }
1023 }
1024
1025 fn eval_method_datetime(&self, template: Option<&str>) -> Result<Cow<'a, T>> {
1026 let input = self.current.as_str().ok_or(Error::DatetimeNotString)?;
1027 let parsed = match template {
1028 None => crate::datetime::iso::try_13_formats(input)?,
1029 Some(t) => crate::datetime::template::parse_apply(input, t)?,
1030 };
1031 Ok(Cow::Owned(parsed.to_marker_object::<T>()))
1032 }
1033
1034 fn eval_method_type(&self) -> Result<Cow<'a, T>> {
1035 if let Some((_, kind)) = crate::datetime::extract_marker(self.current) {
1036 return Ok(Cow::Owned(T::from_string(kind.as_str())));
1037 }
1038 let s = if self.current.is_null() {
1039 "null"
1040 } else if self.current.is_bool() {
1041 "boolean"
1042 } else if self.current.is_number() {
1043 "number"
1044 } else if self.current.is_string() {
1045 "string"
1046 } else if self.current.is_array() {
1047 "array"
1048 } else if self.current.is_object() {
1049 "object"
1050 } else {
1051 unreachable!()
1052 };
1053 Ok(Cow::Owned(T::from_string(s)))
1054 }
1055
1056 fn eval_method_size(&self) -> Result<Cow<'a, T>> {
1057 let size = if let Some(array) = self.current.as_array() {
1058 array.len()
1060 } else if self.is_lax() {
1061 1
1063 } else {
1064 return Err(Error::SizeNotArray);
1065 };
1066 Ok(Cow::Owned(T::from_u64(size as u64)))
1067 }
1068
1069 fn eval_method_double(&self) -> Result<Cow<'a, T>> {
1070 if let Some(s) = self.current.as_str() {
1071 let n = s.parse::<f64>().map_err(|_| Error::InvalidDouble)?;
1072 if n.is_infinite() || n.is_nan() {
1073 return Err(Error::InvalidDouble);
1074 }
1075 Ok(Cow::Owned(T::from_f64(n)))
1076 } else if self.current.is_number() {
1077 let n = self
1078 .current
1079 .as_number()
1080 .and_then(|n| n.as_f64())
1081 .ok_or(Error::DoubleOutOfRange)?;
1082 if n.is_infinite() || n.is_nan() {
1083 return Err(Error::DoubleOutOfRange);
1084 }
1085 Ok(Cow::Borrowed(self.current))
1086 } else {
1087 Err(Error::DoubleTypeError)
1088 }
1089 }
1090
1091 fn eval_method_ceiling(&self) -> Result<Cow<'a, T>> {
1092 let n = self
1093 .current
1094 .as_number()
1095 .ok_or(Error::MethodNotNumeric("ceiling"))?;
1096 Ok(Cow::Owned(T::from_number(n.ceil())))
1097 }
1098
1099 fn eval_method_floor(&self) -> Result<Cow<'a, T>> {
1100 let n = self
1101 .current
1102 .as_number()
1103 .ok_or(Error::MethodNotNumeric("floor"))?;
1104 Ok(Cow::Owned(T::from_number(n.floor())))
1105 }
1106
1107 fn eval_method_abs(&self) -> Result<Cow<'a, T>> {
1108 let n = self
1109 .current
1110 .as_number()
1111 .ok_or(Error::MethodNotNumeric("abs"))?;
1112 Ok(Cow::Owned(T::from_number(n.abs())))
1113 }
1114
1115 fn eval_method_keyvalue(&self) -> Result<Vec<Cow<'a, T>>> {
1116 use std::hash::Hasher;
1117 let object = self.current.as_object().ok_or(Error::KeyValueNotObject)?;
1118 let mut hasher = rustc_hash::FxHasher::default();
1119 let entries: Vec<_> = object.list();
1120 for (k, _) in &entries {
1121 hasher.write(k.as_bytes());
1122 hasher.write_u8(0);
1123 }
1124 let id = hasher.finish() as i64;
1125 Ok(entries
1126 .into_iter()
1127 .map(|(k, v)| {
1128 Cow::Owned(T::object([
1129 ("key", T::from_string(k)),
1130 ("value", v.to_owned()),
1131 ("id", T::from_i64(id)),
1132 ]))
1133 })
1134 .collect())
1135 }
1136
1137 fn eval_value(&self, value: &Value) -> Result<Cow<'a, T>> {
1139 Ok(match value {
1140 Value::Null => Cow::Owned(T::null()),
1141 Value::Boolean(b) => Cow::Owned(T::bool(*b)),
1142 Value::Number(n) => Cow::Owned(T::from_number(n.clone())),
1143 Value::String(s) => Cow::Owned(T::from_string(s)),
1144 Value::Variable(v) => Cow::Borrowed(self.get_variable(v)?),
1145 })
1146 }
1147}
1148
1149fn eval_compare<T: Json>(
1153 op: CompareOp,
1154 left: T::Borrowed<'_>,
1155 right: T::Borrowed<'_>,
1156 use_tz: bool,
1157) -> Result<Truth> {
1158 use CompareOp::*;
1159 let left_marker = crate::datetime::extract_marker(left);
1160 let right_marker = crate::datetime::extract_marker(right);
1161 if left_marker.is_some() || right_marker.is_some() {
1162 return eval_compare_datetime(op, left_marker, right_marker, use_tz);
1163 }
1164 if left.is_array() || left.is_object() || right.is_array() || right.is_object() {
1166 return Ok(Truth::Unknown);
1167 }
1168 if left.is_null() && right.is_null() {
1169 return Ok(compare_ord(op, (), ()).into());
1170 }
1171 if left.is_null() || right.is_null() {
1172 return Ok((op == CompareOp::Ne).into());
1173 }
1174 if let (Some(left), Some(right)) = (left.as_bool(), right.as_bool()) {
1175 return Ok(compare_ord(op, left, right).into());
1176 }
1177 if let (Some(left), Some(right)) = (left.as_number(), right.as_number()) {
1178 return Ok(match op {
1179 Eq => left.equal(&right),
1180 Ne => !left.equal(&right),
1181 Gt => right.less_than(&left),
1182 Ge => !left.less_than(&right),
1183 Lt => left.less_than(&right),
1184 Le => !right.less_than(&left),
1185 }
1186 .into());
1187 }
1188 if let (Some(left), Some(right)) = (left.as_str(), right.as_str()) {
1189 return Ok(compare_ord(op, left, right).into());
1190 }
1191 Ok(Truth::Unknown)
1192}
1193
1194fn eval_compare_datetime(
1195 op: CompareOp,
1196 left: Option<(String, crate::datetime::DatetimeKind)>,
1197 right: Option<(String, crate::datetime::DatetimeKind)>,
1198 use_tz: bool,
1199) -> Result<Truth> {
1200 use crate::datetime::DatetimeKind as K;
1201 let (Some((l_iso, l_kind)), Some((r_iso, r_kind))) = (left, right) else {
1202 return Ok(Truth::Unknown);
1203 };
1204 let needs_tz = match (l_kind, r_kind) {
1205 (a, b) if a == b => false,
1206 (K::Date, K::Timestamp) | (K::Timestamp, K::Date) => false,
1207 (K::TimestampTz, _) | (_, K::TimestampTz) => true,
1208 (K::TimeTz, _) | (_, K::TimeTz) => true,
1209 (K::Date, K::Time) | (K::Time, K::Date) => return Ok(Truth::Unknown),
1210 (K::Timestamp, K::Time) | (K::Time, K::Timestamp) => return Ok(Truth::Unknown),
1211 _ => return Ok(Truth::Unknown),
1212 };
1213 if needs_tz && !use_tz {
1214 let (from, target_kind) = if matches!(l_kind, K::TimestampTz | K::TimeTz) {
1215 (r_kind, l_kind)
1216 } else {
1217 (l_kind, r_kind)
1218 };
1219 let has_date = matches!(l_kind, K::Date | K::Timestamp | K::TimestampTz)
1220 || matches!(r_kind, K::Date | K::Timestamp | K::TimestampTz);
1221 let to = if has_date {
1222 "timestamptz"
1223 } else {
1224 target_kind.as_tag()
1225 };
1226 return Err(Error::DatetimeConvertWithoutTz(
1227 from.as_tag().into(),
1228 to.into(),
1229 ));
1230 }
1231 let ord = match compare_datetime_kinds(&l_iso, l_kind, &r_iso, r_kind, use_tz) {
1232 Some(o) => o,
1233 None => return Ok(Truth::Unknown),
1234 };
1235 use CompareOp::*;
1236 Ok(match op {
1237 Eq => ord.is_eq(),
1238 Ne => !ord.is_eq(),
1239 Gt => ord.is_gt(),
1240 Ge => !ord.is_lt(),
1241 Lt => ord.is_lt(),
1242 Le => !ord.is_gt(),
1243 }
1244 .into())
1245}
1246
1247fn compare_datetime_kinds(
1248 l_iso: &str,
1249 l_kind: crate::datetime::DatetimeKind,
1250 r_iso: &str,
1251 r_kind: crate::datetime::DatetimeKind,
1252 use_tz: bool,
1253) -> Option<std::cmp::Ordering> {
1254 use crate::datetime::DatetimeKind as K;
1255 if l_kind == r_kind {
1256 match l_kind {
1257 K::Date | K::Timestamp => return cmp_date_or_ts(l_iso, l_kind, r_iso, r_kind),
1258 K::Time => return Some(l_iso.cmp(r_iso)),
1259 K::TimestampTz => {
1260 let l_inst = to_instant(l_iso, l_kind)?;
1261 let r_inst = to_instant(r_iso, r_kind)?;
1262 return Some(l_inst.cmp(&r_inst));
1263 }
1264 K::TimeTz => return cmp_timetz_pair(l_iso, l_kind, r_iso, r_kind),
1265 }
1266 }
1267 if matches!(
1268 (l_kind, r_kind),
1269 (K::Date, K::Timestamp) | (K::Timestamp, K::Date)
1270 ) {
1271 return cmp_date_or_ts(l_iso, l_kind, r_iso, r_kind);
1272 }
1273 let l_is_time = matches!(l_kind, K::Time | K::TimeTz);
1274 let r_is_time = matches!(r_kind, K::Time | K::TimeTz);
1275 let l_is_dated = matches!(l_kind, K::Date | K::Timestamp | K::TimestampTz);
1276 let r_is_dated = matches!(r_kind, K::Date | K::Timestamp | K::TimestampTz);
1277 if (l_is_time && r_is_dated) || (l_is_dated && r_is_time) {
1278 return None;
1279 }
1280 if matches!(
1283 (l_kind, r_kind),
1284 (K::Time, K::TimeTz) | (K::TimeTz, K::Time) | (K::TimeTz, K::TimeTz) | (K::Time, K::Time)
1285 ) {
1286 if !use_tz
1287 && matches!(
1288 (l_kind, r_kind),
1289 (K::Time, K::TimeTz) | (K::TimeTz, K::Time)
1290 )
1291 {
1292 return None;
1293 }
1294 return cmp_timetz_pair(l_iso, l_kind, r_iso, r_kind);
1295 }
1296 if !use_tz {
1298 return None;
1299 }
1300 if has_wide_year(l_iso) || has_wide_year(r_iso) {
1304 return cmp_date_or_ts(l_iso, l_kind, r_iso, r_kind);
1305 }
1306 let l_inst = to_instant(l_iso, l_kind)?;
1307 let r_inst = to_instant(r_iso, r_kind)?;
1308 Some(l_inst.cmp(&r_inst))
1309}
1310
1311fn has_wide_year(iso: &str) -> bool {
1312 match iso.find('-') {
1313 Some(idx) => idx > 4,
1314 None => false,
1315 }
1316}
1317
1318fn cmp_date_or_ts(
1319 l_iso: &str,
1320 l_kind: crate::datetime::DatetimeKind,
1321 r_iso: &str,
1322 r_kind: crate::datetime::DatetimeKind,
1323) -> Option<std::cmp::Ordering> {
1324 use crate::datetime::DatetimeKind as K;
1325 let (ly, lm, ld, l_time) = parse_ymd_and_time(l_iso)?;
1326 let (ry, rm, rd, r_time) = parse_ymd_and_time(r_iso)?;
1327 match (ly, lm, ld).cmp(&(ry, rm, rd)) {
1328 std::cmp::Ordering::Equal => {}
1329 ord => return Some(ord),
1330 }
1331 let l_t = if l_kind == K::Date {
1332 "T00:00:00"
1333 } else {
1334 l_time
1335 };
1336 let r_t = if r_kind == K::Date {
1337 "T00:00:00"
1338 } else {
1339 r_time
1340 };
1341 Some(l_t.cmp(r_t))
1342}
1343
1344fn parse_ymd_and_time(iso: &str) -> Option<(u64, u32, u32, &str)> {
1345 let dash1 = iso.find('-')?;
1346 let year: u64 = iso[..dash1].parse().ok()?;
1347 let rest = &iso[dash1 + 1..];
1348 let dash2 = rest.find('-')?;
1349 let month: u32 = rest[..dash2].parse().ok()?;
1350 let after_dash = &rest[dash2 + 1..];
1351 let day_end = after_dash
1352 .find(|c: char| !c.is_ascii_digit())
1353 .unwrap_or(after_dash.len());
1354 let day: u32 = after_dash[..day_end].parse().ok()?;
1355 let time_part = &after_dash[day_end..];
1356 Some((year, month, day, time_part))
1357}
1358
1359fn cmp_timetz_pair(
1360 l_iso: &str,
1361 l_kind: crate::datetime::DatetimeKind,
1362 r_iso: &str,
1363 r_kind: crate::datetime::DatetimeKind,
1364) -> Option<std::cmp::Ordering> {
1365 let (l_wall, l_off) = parse_time_pair(l_iso, l_kind)?;
1366 let (r_wall, r_off) = parse_time_pair(r_iso, r_kind)?;
1367 let l_utc = l_wall - l_off;
1368 let r_utc = r_wall - r_off;
1369 let ord = l_utc.cmp(&r_utc);
1370 if ord != std::cmp::Ordering::Equal {
1371 return Some(ord);
1372 }
1373 Some(r_off.cmp(&l_off))
1374}
1375
1376fn parse_time_pair(iso: &str, kind: crate::datetime::DatetimeKind) -> Option<(i64, i64)> {
1377 use crate::datetime::DatetimeKind as K;
1378 match kind {
1379 K::Time => {
1380 let t: jiff::civil::Time = iso.parse().ok()?;
1381 Some((time_to_seconds(t), 0))
1382 }
1383 K::TimeTz => {
1384 let (time_part, off_part) = split_offset(iso)?;
1385 let t: jiff::civil::Time = time_part.parse().ok()?;
1386 let off = parse_offset(off_part)?.seconds() as i64;
1387 Some((time_to_seconds(t), off))
1388 }
1389 _ => None,
1390 }
1391}
1392
1393fn time_to_seconds(t: jiff::civil::Time) -> i64 {
1394 i64::from(t.hour()) * 3600 + i64::from(t.minute()) * 60 + i64::from(t.second())
1395}
1396
1397fn to_instant(iso: &str, kind: crate::datetime::DatetimeKind) -> Option<jiff::Timestamp> {
1398 use crate::datetime::DatetimeKind as K;
1399 match kind {
1400 K::Date => {
1401 let d: jiff::civil::Date = iso.parse().ok()?;
1402 let dt = d.at(0, 0, 0, 0);
1403 dt.to_zoned(jiff::tz::TimeZone::UTC)
1404 .ok()
1405 .map(|z| z.timestamp())
1406 }
1407 K::Time => {
1408 let t: jiff::civil::Time = iso.parse().ok()?;
1410 let today = jiff::civil::date(1970, 1, 1);
1411 let dt = today.at(t.hour(), t.minute(), t.second(), t.subsec_nanosecond());
1412 dt.to_zoned(jiff::tz::TimeZone::UTC)
1413 .ok()
1414 .map(|z| z.timestamp())
1415 }
1416 K::TimeTz => {
1417 let (time_part, off_part) = split_offset(iso)?;
1419 let t: jiff::civil::Time = time_part.parse().ok()?;
1420 let off = parse_offset(off_part)?;
1421 let today = jiff::civil::date(1970, 1, 1);
1422 let dt = today.at(t.hour(), t.minute(), t.second(), t.subsec_nanosecond());
1423 let zoned = dt.to_zoned(jiff::tz::TimeZone::fixed(off)).ok()?;
1424 Some(zoned.timestamp())
1425 }
1426 K::Timestamp => {
1427 let dt: jiff::civil::DateTime = iso.parse().ok()?;
1428 dt.to_zoned(jiff::tz::TimeZone::UTC)
1429 .ok()
1430 .map(|z| z.timestamp())
1431 }
1432 K::TimestampTz => {
1433 let (dt_part, off_part) = split_offset(iso)?;
1434 let dt: jiff::civil::DateTime = dt_part.parse().ok()?;
1435 let off = parse_offset(off_part)?;
1436 let zoned = dt.to_zoned(jiff::tz::TimeZone::fixed(off)).ok()?;
1437 Some(zoned.timestamp())
1438 }
1439 }
1440}
1441
1442fn split_offset(s: &str) -> Option<(&str, &str)> {
1443 let bytes = s.as_bytes();
1445 for i in (1..bytes.len()).rev() {
1446 if bytes[i] == b'+' || bytes[i] == b'-' {
1447 return Some((&s[..i], &s[i..]));
1448 }
1449 }
1450 None
1451}
1452
1453fn parse_offset(s: &str) -> Option<jiff::tz::Offset> {
1454 let bytes = s.as_bytes();
1456 if bytes.len() != 6 || (bytes[0] != b'+' && bytes[0] != b'-') {
1457 return None;
1458 }
1459 let sign = if bytes[0] == b'-' { -1 } else { 1 };
1460 let h: i8 = std::str::from_utf8(&bytes[1..3]).ok()?.parse().ok()?;
1461 let m: i8 = std::str::from_utf8(&bytes[4..6]).ok()?.parse().ok()?;
1462 let total_min = sign * (i32::from(h) * 60 + i32::from(m));
1463 jiff::tz::Offset::from_seconds(total_min * 60).ok()
1464}
1465
1466fn eval_unary_op<T: Json>(op: UnaryOp, value: T::Borrowed<'_>) -> Result<T> {
1468 let n = value.as_number().ok_or(Error::UnaryOperandNotNumeric(op))?;
1469 Ok(match op {
1470 UnaryOp::Plus => value.to_owned(),
1471 UnaryOp::Minus => T::from_number(n.neg()),
1472 })
1473}
1474
1475fn eval_binary_op<T: Json>(
1477 op: BinaryOp,
1478 left: T::Borrowed<'_>,
1479 right: T::Borrowed<'_>,
1480) -> Result<T> {
1481 let left = left.as_number().ok_or(Error::LeftOperandNotNumeric(op))?;
1482 let right = right.as_number().ok_or(Error::RightOperandNotNumeric(op))?;
1483 Ok(T::from_number(match op {
1484 BinaryOp::Add => left.add(&right),
1485 BinaryOp::Sub => left.sub(&right),
1486 BinaryOp::Mul => left.mul(&right),
1487 BinaryOp::Div => left.div(&right)?,
1488 BinaryOp::Rem => left.rem(&right)?,
1489 }))
1490}
1491
1492fn compare_ord<T: Ord>(op: CompareOp, left: T, right: T) -> bool {
1494 use CompareOp::*;
1495 match op {
1496 Eq => left == right,
1497 Ne => left != right,
1498 Gt => left > right,
1499 Ge => left >= right,
1500 Lt => left < right,
1501 Le => left <= right,
1502 }
1503}
1504
1505pub trait NumberExt: Sized {
1507 fn equal(&self, other: &Self) -> bool;
1508 fn less_than(&self, other: &Self) -> bool;
1509 fn neg(&self) -> Self;
1510 fn add(&self, other: &Self) -> Self;
1511 fn sub(&self, other: &Self) -> Self;
1512 fn mul(&self, other: &Self) -> Self;
1513 fn div(&self, other: &Self) -> Result<Self>;
1514 fn rem(&self, other: &Self) -> Result<Self>;
1515 fn ceil(&self) -> Self;
1516 fn floor(&self) -> Self;
1517 fn abs(&self) -> Self;
1518 fn to_i64(&self) -> Option<i64>;
1519}
1520
1521impl NumberExt for Number {
1522 fn equal(&self, other: &Self) -> bool {
1523 self.as_f64().unwrap() == other.as_f64().unwrap()
1526 }
1527
1528 fn less_than(&self, other: &Self) -> bool {
1529 self.as_f64().unwrap() < other.as_f64().unwrap()
1530 }
1531
1532 fn neg(&self) -> Self {
1533 if let Some(n) = self.as_i64() {
1534 Number::from(-n)
1535 } else if let Some(n) = self.as_f64() {
1536 Number::from_f64(-n).unwrap()
1537 } else {
1538 unreachable!()
1540 }
1541 }
1542
1543 fn add(&self, other: &Self) -> Self {
1544 if let (Some(a), Some(b)) = (self.as_i64(), other.as_i64()) {
1545 Number::from(a + b)
1546 } else if let (Some(a), Some(b)) = (self.as_f64(), other.as_f64()) {
1547 Number::from_f64(a + b).unwrap()
1548 } else {
1549 unreachable!()
1550 }
1551 }
1552
1553 fn sub(&self, other: &Self) -> Self {
1554 if let (Some(a), Some(b)) = (self.as_i64(), other.as_i64()) {
1555 Number::from(a - b)
1556 } else if let (Some(a), Some(b)) = (self.as_f64(), other.as_f64()) {
1557 Number::from_f64(a - b).unwrap()
1558 } else {
1559 unreachable!()
1560 }
1561 }
1562
1563 fn mul(&self, other: &Self) -> Self {
1564 if let (Some(a), Some(b)) = (self.as_i64(), other.as_i64()) {
1565 Number::from(a * b)
1566 } else if let (Some(a), Some(b)) = (self.as_f64(), other.as_f64()) {
1567 Number::from_f64(a * b).unwrap()
1568 } else {
1569 unreachable!()
1570 }
1571 }
1572
1573 fn div(&self, other: &Self) -> Result<Self> {
1574 if let (Some(a), Some(b)) = (self.as_f64(), other.as_f64()) {
1575 if b == 0.0 {
1576 return Err(Error::DivisionByZero);
1577 }
1578 Ok(Number::from_f64(a / b).unwrap())
1579 } else {
1580 unreachable!()
1581 }
1582 }
1583
1584 fn rem(&self, other: &Self) -> Result<Self> {
1585 if let (Some(a), Some(b)) = (self.as_i64(), other.as_i64()) {
1586 if b == 0 {
1587 return Err(Error::DivisionByZero);
1588 }
1589 return Ok(Number::from(a % b));
1590 }
1591 if let Some(r) = exact_decimal_rem(self, other) {
1592 return Ok(r);
1593 }
1594 if let (Some(a), Some(b)) = (self.as_f64(), other.as_f64()) {
1595 if b == 0.0 {
1596 return Err(Error::DivisionByZero);
1597 }
1598 Ok(Number::from_f64(a % b).unwrap())
1599 } else {
1600 unreachable!()
1601 }
1602 }
1603
1604 fn ceil(&self) -> Self {
1605 if self.is_f64() {
1606 Number::from(self.as_f64().unwrap().ceil() as i64)
1607 } else {
1608 self.clone()
1609 }
1610 }
1611
1612 fn floor(&self) -> Self {
1613 if self.is_f64() {
1614 Number::from(self.as_f64().unwrap().floor() as i64)
1615 } else {
1616 self.clone()
1617 }
1618 }
1619
1620 fn abs(&self) -> Self {
1621 if let Some(n) = self.as_i64() {
1622 Number::from(n.abs())
1623 } else if let Some(n) = self.as_f64() {
1624 Number::from_f64(n.abs()).unwrap()
1625 } else {
1626 unreachable!()
1627 }
1628 }
1629
1630 fn to_i64(&self) -> Option<i64> {
1635 const INT_MIN: i64 = -(1 << 53) + 1;
1636 const INT_MAX: i64 = (1 << 53) - 1;
1637 if let Some(i) = self.as_i64() {
1638 if (INT_MIN..=INT_MAX).contains(&i) {
1639 Some(i)
1640 } else {
1641 None
1642 }
1643 } else if let Some(f) = self.as_f64() {
1644 if (INT_MIN as f64..=INT_MAX as f64).contains(&f) {
1645 Some(f as i64)
1646 } else {
1647 None
1648 }
1649 } else {
1650 unreachable!()
1651 }
1652 }
1653}
1654
1655fn exact_decimal_rem(a: &Number, b: &Number) -> Option<Number> {
1656 let (a_int, a_scale) = decimal_parts(&a.to_string())?;
1657 let (b_int, b_scale) = decimal_parts(&b.to_string())?;
1658 let scale = a_scale.max(b_scale);
1659 let a_pow = 10_i128.checked_pow((scale - a_scale) as u32)?;
1660 let b_pow = 10_i128.checked_pow((scale - b_scale) as u32)?;
1661 let a_scaled = a_int.checked_mul(a_pow)?;
1662 let b_scaled = b_int.checked_mul(b_pow)?;
1663 if b_scaled == 0 {
1664 return None;
1665 }
1666 let r = a_scaled % b_scaled;
1667 let s = render_decimal(r, scale);
1668 if scale == 0 {
1669 Some(Number::from(s.parse::<i64>().ok()?))
1670 } else {
1671 Number::from_f64(s.parse::<f64>().ok()?)
1672 }
1673}
1674
1675fn decimal_parts(s: &str) -> Option<(i128, usize)> {
1676 if s.contains('e') || s.contains('E') {
1677 return None;
1678 }
1679 let (sign, body) = match s.strip_prefix('-') {
1680 Some(rest) => (-1_i128, rest),
1681 None => (1_i128, s),
1682 };
1683 let (int_str, frac_str) = match body.split_once('.') {
1684 Some((i, f)) => (i, f),
1685 None => (body, ""),
1686 };
1687 let scale = frac_str.len();
1688 let int_part: i128 = if int_str.is_empty() {
1689 0
1690 } else {
1691 int_str.parse().ok()?
1692 };
1693 let frac_part: i128 = if frac_str.is_empty() {
1694 0
1695 } else {
1696 frac_str.parse().ok()?
1697 };
1698 let pow = 10_i128.checked_pow(scale as u32)?;
1699 let scaled = int_part.checked_mul(pow)?.checked_add(frac_part)?;
1700 Some((sign * scaled, scale))
1701}
1702
1703fn render_decimal(r: i128, scale: usize) -> String {
1704 if scale == 0 {
1705 return r.to_string();
1706 }
1707 let neg = r < 0;
1708 let abs = r.unsigned_abs().to_string();
1709 let padded = if abs.len() <= scale {
1710 format!("0.{:0>width$}", abs, width = scale)
1711 } else {
1712 let dot = abs.len() - scale;
1713 format!("{}.{}", &abs[..dot], &abs[dot..])
1714 };
1715 let mut trimmed = padded.trim_end_matches('0').to_string();
1716 if trimmed.ends_with('.') {
1717 trimmed.pop();
1718 }
1719 if neg && trimmed != "0" {
1720 format!("-{trimmed}")
1721 } else {
1722 trimmed
1723 }
1724}