1#![forbid(unsafe_code)]
99#![doc(html_logo_url = "https://raw.githubusercontent.com/V0ldek/rsonpath/main/img/rsonquery-logo.svg")]
100#![cfg_attr(
102 not(debug_assertions),
103 warn(missing_docs, clippy::missing_errors_doc, clippy::missing_panics_doc,)
104)]
105#![cfg_attr(not(debug_assertions), warn(rustdoc::missing_crate_level_docs))]
106#![cfg_attr(not(test), warn(clippy::unwrap_used))]
108#![cfg_attr(
110 not(debug_assertions),
111 warn(clippy::print_stderr, clippy::print_stdout, clippy::todo)
112)]
113#![cfg_attr(docsrs, feature(doc_cfg))]
115
116pub mod builder;
117pub mod error;
118pub mod num;
119mod parser;
120pub mod prelude;
121pub mod str;
122
123use std::{
124 fmt::{self, Display},
125 ops::Deref,
126};
127
128#[derive(Debug, Clone, Default)]
130pub struct Parser {
131 options: ParserOptions,
132}
133
134#[derive(Debug, Clone, Default)]
136pub struct ParserBuilder {
137 options: ParserOptions,
138}
139
140#[derive(Debug, Clone)]
141struct ParserOptions {
142 recursion_limit: Option<usize>,
143 relaxed_whitespace: bool,
144}
145
146impl ParserBuilder {
147 #[inline]
149 #[must_use]
150 pub fn new() -> Self {
151 Self {
152 options: ParserOptions::default(),
153 }
154 }
155
156 #[inline]
180 pub fn set_recursion_limit(&mut self, value: Option<usize>) -> &mut Self {
181 self.options.recursion_limit = value;
182 self
183 }
184
185 #[inline]
205 pub fn allow_surrounding_whitespace(&mut self, value: bool) -> &mut Self {
206 self.options.relaxed_whitespace = value;
207 self
208 }
209
210 #[inline]
212 #[must_use]
213 pub fn build(&self) -> Parser {
214 Parser {
215 options: self.options.clone(),
216 }
217 }
218}
219
220impl ParserOptions {
221 fn is_leading_whitespace_allowed(&self) -> bool {
222 self.relaxed_whitespace
223 }
224
225 fn is_trailing_whitespace_allowed(&self) -> bool {
226 self.relaxed_whitespace
227 }
228}
229
230impl Default for ParserOptions {
231 #[inline(always)]
232 fn default() -> Self {
233 Self {
234 recursion_limit: Some(Parser::RECURSION_LIMIT_DEFAULT),
235 relaxed_whitespace: false,
236 }
237 }
238}
239
240impl From<ParserBuilder> for Parser {
241 #[inline(always)]
242 fn from(value: ParserBuilder) -> Self {
243 Self { options: value.options }
244 }
245}
246
247pub type Result<T> = std::result::Result<T, error::ParseError>;
249
250#[inline]
283pub fn parse(str: &str) -> Result<JsonPathQuery> {
284 Parser::default().parse(str)
285}
286
287impl Parser {
288 pub const RECURSION_LIMIT_DEFAULT: usize = 128;
292
293 #[inline]
307 pub fn parse(&self, str: &str) -> Result<JsonPathQuery> {
308 crate::parser::parse_with_options(str, &self.options)
309 }
310}
311
312#[derive(Debug, PartialEq, Eq, Clone, Hash)]
318#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
319#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
320pub enum Segment {
321 Child(Selectors),
324 Descendant(Selectors),
327}
328
329#[cfg(feature = "arbitrary")]
331#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
332impl<'a> arbitrary::Arbitrary<'a> for Selectors {
333 #[inline]
334 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
335 let first = u.arbitrary::<Selector>()?;
336 let mut rest = u.arbitrary::<Vec<Selector>>()?;
337 rest.push(first);
338
339 Ok(Self::many(rest))
340 }
341}
342
343#[derive(Debug, PartialEq, Eq, Clone, Hash)]
347#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
348pub struct Selectors {
349 inner: Vec<Selector>,
350}
351
352#[derive(Debug, PartialEq, Eq, Clone, Hash)]
355#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
356#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
357pub enum Selector {
358 Name(str::JsonString),
361 Wildcard,
363 Index(Index),
366 Slice(Slice),
369 Filter(LogicalExpr),
372}
373
374impl From<str::JsonString> for Selector {
375 #[inline]
376 fn from(value: str::JsonString) -> Self {
377 Self::Name(value)
378 }
379}
380
381impl From<Index> for Selector {
382 #[inline]
383 fn from(value: Index) -> Self {
384 Self::Index(value)
385 }
386}
387
388impl From<Slice> for Selector {
389 #[inline]
390 fn from(value: Slice) -> Self {
391 Self::Slice(value)
392 }
393}
394
395impl From<LogicalExpr> for Selector {
396 #[inline]
397 fn from(value: LogicalExpr) -> Self {
398 Self::Filter(value)
399 }
400}
401
402#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
404#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
405pub enum Index {
406 FromStart(num::JsonUInt),
408 FromEnd(num::JsonNonZeroUInt),
412}
413
414#[cfg(feature = "arbitrary")]
416#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
417impl<'a> arbitrary::Arbitrary<'a> for Index {
418 #[inline]
419 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
420 let num = u.arbitrary::<num::JsonInt>()?;
421 Ok(Self::from(num))
422 }
423}
424
425impl<N: Into<num::JsonInt>> From<N> for Index {
426 #[inline]
427 fn from(value: N) -> Self {
428 let value = value.into();
429 if value.as_i64() >= 0 {
430 Self::FromStart(value.abs())
431 } else {
432 Self::FromEnd(value.abs().try_into().expect("checked for zero already"))
433 }
434 }
435}
436
437#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
439#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
440pub enum Step {
441 Forward(num::JsonUInt),
443 Backward(num::JsonNonZeroUInt),
445}
446
447#[cfg(feature = "arbitrary")]
449#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
450impl<'a> arbitrary::Arbitrary<'a> for Step {
451 #[inline]
452 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
453 let num = u.arbitrary::<num::JsonInt>()?;
454 Ok(Self::from(num))
455 }
456}
457
458impl From<num::JsonInt> for Step {
459 #[inline]
460 fn from(value: num::JsonInt) -> Self {
461 if value.as_i64() >= 0 {
462 Self::Forward(value.abs())
463 } else {
464 Self::Backward(value.abs().try_into().expect("checked for zero already"))
465 }
466 }
467}
468
469#[derive(Debug, PartialEq, Eq, Clone, Hash)]
490#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
491#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
492pub struct Slice {
493 start: Index,
494 end: Option<Index>,
495 step: Step,
496}
497
498impl Slice {
499 pub(crate) const DEFAULT_START_FORWARDS: Index = Index::FromStart(num::JsonUInt::ZERO);
500 #[inline(always)]
502 pub(crate) fn default_start_backwards() -> Index {
503 Index::FromEnd(1.try_into().expect("const 1 is nonzero"))
504 }
505 pub(crate) const DEFAULT_STEP: Step = Step::Forward(num::JsonUInt::ONE);
506
507 #[inline(always)]
509 #[must_use]
510 pub fn new(start: Index, end: Option<Index>, step: Step) -> Self {
511 Self { start, end, step }
512 }
513
514 #[inline(always)]
516 #[must_use]
517 pub fn start(&self) -> Index {
518 self.start
519 }
520
521 #[inline(always)]
523 #[must_use]
524 pub fn end(&self) -> Option<Index> {
525 self.end
526 }
527
528 #[inline(always)]
530 #[must_use]
531 pub fn step(&self) -> Step {
532 self.step
533 }
534}
535
536impl Default for Slice {
537 #[inline]
538 fn default() -> Self {
539 Self {
540 start: Index::FromStart(0.into()),
541 end: None,
542 step: Step::Forward(1.into()),
543 }
544 }
545}
546
547#[derive(Debug, PartialEq, Eq, Clone, Hash)]
549#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
550#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
551pub enum Literal {
552 String(str::JsonString),
554 Number(num::JsonNumber),
557 Bool(bool),
559 Null,
561}
562
563impl<S> From<S> for Literal
564where
565 S: Into<str::JsonString>,
566{
567 #[inline(always)]
568 fn from(value: S) -> Self {
569 Self::String(value.into())
570 }
571}
572
573impl From<num::JsonInt> for Literal {
574 #[inline(always)]
575 fn from(value: num::JsonInt) -> Self {
576 Self::Number(num::JsonNumber::Int(value))
577 }
578}
579
580impl From<num::JsonFloat> for Literal {
581 #[inline(always)]
582 fn from(value: num::JsonFloat) -> Self {
583 Self::Number(num::JsonNumber::Float(value))
584 }
585}
586
587impl From<num::JsonNumber> for Literal {
588 #[inline(always)]
589 fn from(value: num::JsonNumber) -> Self {
590 Self::Number(value)
591 }
592}
593
594impl From<bool> for Literal {
595 #[inline(always)]
596 fn from(value: bool) -> Self {
597 Self::Bool(value)
598 }
599}
600
601#[derive(Debug, PartialEq, Eq, Clone, Hash)]
607#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
608#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
609pub enum LogicalExpr {
610 Or(LogicalExprNode, LogicalExprNode),
612 And(LogicalExprNode, LogicalExprNode),
614 Not(LogicalExprNode),
616 Comparison(ComparisonExpr),
619 Test(TestExpr),
621}
622
623impl LogicalExpr {
624 fn precedence(&self) -> usize {
625 match self {
626 Self::Or(_, _) => 2,
627 Self::And(_, _) => 3,
628 Self::Comparison(_) => 4,
629 Self::Not(_) => 5,
630 Self::Test(_) => 10,
631 }
632 }
633}
634
635type LogicalExprNode = Box<LogicalExpr>;
636
637#[derive(Debug, PartialEq, Eq, Clone, Hash)]
639#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
640#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
641pub enum TestExpr {
642 Relative(JsonPathQuery),
644 Absolute(JsonPathQuery),
646}
647
648#[derive(Debug, PartialEq, Eq, Clone, Hash)]
667#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
668#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
669pub struct ComparisonExpr {
670 lhs: Comparable,
671 op: ComparisonOp,
672 rhs: Comparable,
673}
674
675impl ComparisonExpr {
676 #[inline]
678 #[must_use]
679 pub fn lhs(&self) -> &Comparable {
680 &self.lhs
681 }
682
683 #[inline]
685 #[must_use]
686 pub fn op(&self) -> ComparisonOp {
687 self.op
688 }
689
690 #[inline]
692 #[must_use]
693 pub fn rhs(&self) -> &Comparable {
694 &self.rhs
695 }
696
697 #[inline]
699 #[must_use]
700 pub fn from_parts(lhs: Comparable, op: ComparisonOp, rhs: Comparable) -> Self {
701 Self { lhs, op, rhs }
702 }
703}
704
705#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
707#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
708#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
709pub enum ComparisonOp {
710 EqualTo,
712 NotEqualTo,
714 LesserOrEqualTo,
716 GreaterOrEqualTo,
718 LessThan,
720 GreaterThan,
722}
723
724#[derive(Debug, PartialEq, Eq, Clone, Hash)]
726#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
727#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
728pub enum Comparable {
729 Literal(Literal),
731 RelativeSingularQuery(SingularJsonPathQuery),
733 AbsoluteSingularQuery(SingularJsonPathQuery),
735}
736
737impl From<Literal> for Comparable {
738 #[inline(always)]
739 fn from(value: Literal) -> Self {
740 Self::Literal(value)
741 }
742}
743
744#[derive(Debug, PartialEq, Eq, Clone, Hash)]
753#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
754#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
755pub struct SingularJsonPathQuery {
756 segments: Vec<SingularSegment>,
757}
758
759impl SingularJsonPathQuery {
760 #[inline]
762 pub fn segments(&self) -> impl Iterator<Item = &'_ SingularSegment> {
763 self.segments.iter()
764 }
765}
766
767#[derive(Debug, PartialEq, Eq, Clone, Hash)]
769#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
770#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
771pub enum SingularSegment {
772 Name(str::JsonString),
774 Index(Index),
776}
777
778impl FromIterator<SingularSegment> for SingularJsonPathQuery {
779 #[inline]
780 fn from_iter<T: IntoIterator<Item = SingularSegment>>(iter: T) -> Self {
781 Self {
782 segments: iter.into_iter().collect(),
783 }
784 }
785}
786
787impl From<SingularSegment> for Segment {
788 #[inline]
789 fn from(value: SingularSegment) -> Self {
790 match value {
791 SingularSegment::Name(n) => Self::Child(Selectors::one(Selector::Name(n))),
792 SingularSegment::Index(i) => Self::Child(Selectors::one(Selector::Index(i))),
793 }
794 }
795}
796
797#[derive(Debug, PartialEq, Eq, Clone, Hash)]
799#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
800#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
801pub struct JsonPathQuery {
802 segments: Vec<Segment>,
803}
804
805impl FromIterator<Segment> for JsonPathQuery {
806 #[inline]
807 fn from_iter<T: IntoIterator<Item = Segment>>(iter: T) -> Self {
808 Self {
809 segments: iter.into_iter().collect(),
810 }
811 }
812}
813
814impl JsonPathQuery {
815 fn try_to_singular(self) -> std::result::Result<SingularJsonPathQuery, Self> {
816 if self.segments.iter().all(Segment::is_singular) {
817 let mut singular_segments = Vec::with_capacity(self.segments.len());
818 for segment in self.segments {
819 singular_segments.push(segment.into_singular());
820 }
821 Ok(SingularJsonPathQuery {
822 segments: singular_segments,
823 })
824 } else {
825 Err(self)
826 }
827 }
828}
829
830impl JsonPathQuery {
831 #[inline(always)]
833 #[must_use]
834 pub fn segments(&self) -> &[Segment] {
835 &self.segments
836 }
837}
838
839impl Segment {
840 #[inline(always)]
842 #[must_use]
843 pub fn selectors(&self) -> &Selectors {
844 match self {
845 Self::Child(s) | Self::Descendant(s) => s,
846 }
847 }
848
849 #[inline(always)]
858 #[must_use]
859 pub fn is_child(&self) -> bool {
860 matches!(self, Self::Child(_))
861 }
862
863 #[inline(always)]
872 #[must_use]
873 pub fn is_descendant(&self) -> bool {
874 matches!(self, Self::Descendant(_))
875 }
876
877 fn is_singular(&self) -> bool {
878 match self {
879 Self::Child(s) => s.len() == 1 && s.first().is_singular(),
880 Self::Descendant(_) => false,
881 }
882 }
883
884 fn into_singular(self) -> SingularSegment {
885 assert!(self.is_singular());
886 match self {
887 Self::Child(mut s) => match s.inner.drain(..).next().expect("is_singular") {
888 Selector::Name(n) => SingularSegment::Name(n),
889 Selector::Index(i) => SingularSegment::Index(i),
890 _ => unreachable!(),
891 },
892 Self::Descendant(_) => unreachable!(),
893 }
894 }
895}
896
897impl Selectors {
898 #[inline(always)]
900 #[must_use]
901 pub fn one(selector: Selector) -> Self {
902 Self { inner: vec![selector] }
903 }
904
905 #[inline]
915 #[must_use]
916 pub fn many(vec: Vec<Selector>) -> Self {
917 assert!(!vec.is_empty(), "cannot create an empty Selectors collection");
918 Self { inner: vec }
919 }
920
921 #[inline]
923 #[must_use]
924 pub fn first(&self) -> &Selector {
925 &self.inner[0]
926 }
927
928 #[inline]
930 #[must_use]
931 pub fn as_slice(&self) -> &[Selector] {
932 self
934 }
935}
936
937impl Selector {
938 #[inline(always)]
947 #[must_use]
948 pub const fn is_name(&self) -> bool {
949 matches!(self, Self::Name(_))
950 }
951
952 #[inline(always)]
961 #[must_use]
962 pub const fn is_wildcard(&self) -> bool {
963 matches!(self, Self::Wildcard)
964 }
965
966 #[inline(always)]
975 #[must_use]
976 pub const fn is_index(&self) -> bool {
977 matches!(self, Self::Index(_))
978 }
979
980 #[inline(always)]
989 #[must_use]
990 pub const fn is_slice(&self) -> bool {
991 matches!(self, Self::Slice(_))
992 }
993
994 #[inline(always)]
1003 #[must_use]
1004 pub const fn is_filter(&self) -> bool {
1005 matches!(self, Self::Filter(_))
1006 }
1007
1008 fn is_singular(&self) -> bool {
1009 matches!(self, Self::Name(_) | Self::Index(_))
1010 }
1011}
1012
1013impl Index {
1014 #[inline(always)]
1023 #[must_use]
1024 pub const fn is_start_based(&self) -> bool {
1025 matches!(self, Self::FromStart(_))
1026 }
1027
1028 #[inline(always)]
1037 #[must_use]
1038 pub const fn is_end_based(&self) -> bool {
1039 matches!(self, Self::FromEnd(_))
1040 }
1041}
1042
1043impl Step {
1044 #[inline(always)]
1053 #[must_use]
1054 pub const fn is_forward(&self) -> bool {
1055 matches!(self, Self::Forward(_))
1056 }
1057
1058 #[inline(always)]
1067 #[must_use]
1068 pub const fn is_backward(&self) -> bool {
1069 matches!(self, Self::Backward(_))
1070 }
1071}
1072
1073impl Deref for Selectors {
1074 type Target = [Selector];
1075
1076 #[inline(always)]
1077 fn deref(&self) -> &Self::Target {
1078 &self.inner
1079 }
1080}
1081
1082impl Display for JsonPathQuery {
1083 #[inline]
1084 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1085 write!(f, "$")?;
1086 for s in &self.segments {
1087 write!(f, "{s}")?;
1088 }
1089 Ok(())
1090 }
1091}
1092
1093impl Display for Segment {
1094 #[inline]
1095 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1096 match self {
1097 Self::Child(s) => write!(f, "{s}"),
1098 Self::Descendant(s) => write!(f, "..{s}"),
1099 }
1100 }
1101}
1102
1103impl Display for Selectors {
1104 #[inline]
1105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1106 write!(f, "[{}", self.first())?;
1107 for s in self.inner.iter().skip(1) {
1108 write!(f, ", {s}")?;
1109 }
1110 write!(f, "]")?;
1111 Ok(())
1112 }
1113}
1114
1115impl Display for Selector {
1116 #[inline]
1117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1118 match self {
1119 Self::Name(n) => write!(f, "'{}'", str::escape(n.unquoted(), str::EscapeMode::SingleQuoted)),
1120 Self::Wildcard => write!(f, "*"),
1121 Self::Index(idx) => write!(f, "{idx}"),
1122 Self::Slice(slice) => write!(f, "{slice}"),
1123 Self::Filter(filter) => write!(f, "?{filter}"),
1124 }
1125 }
1126}
1127
1128impl Display for Index {
1129 #[inline]
1130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1131 match self {
1132 Self::FromStart(idx) => write!(f, "{idx}"),
1133 Self::FromEnd(idx) => write!(f, "-{idx}"),
1134 }
1135 }
1136}
1137
1138impl Display for Step {
1139 #[inline]
1140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1141 match self {
1142 Self::Forward(idx) => write!(f, "{idx}"),
1143 Self::Backward(idx) => write!(f, "-{idx}"),
1144 }
1145 }
1146}
1147
1148impl Display for Slice {
1149 #[inline]
1150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1151 if (self.step.is_forward() && self.start != Self::DEFAULT_START_FORWARDS)
1152 || (self.step.is_backward() && self.start != Self::default_start_backwards())
1153 {
1154 write!(f, "{}", self.start)?;
1155 }
1156 write!(f, ":")?;
1157 if let Some(end) = self.end {
1158 write!(f, "{end}")?;
1159 }
1160 if self.step != Self::DEFAULT_STEP {
1161 write!(f, ":{}", self.step)?;
1162 }
1163 Ok(())
1164 }
1165}
1166
1167impl Display for LogicalExpr {
1168 #[inline]
1169 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1170 match self {
1171 Self::Or(lhs, rhs) => {
1172 if lhs.precedence() <= self.precedence() {
1173 write!(f, "({lhs})")?;
1174 } else {
1175 write!(f, "{lhs}")?;
1176 }
1177 write!(f, " || ")?;
1178 if rhs.precedence() < self.precedence() {
1179 write!(f, "({rhs})")?;
1180 } else {
1181 write!(f, "{rhs}")?;
1182 }
1183 Ok(())
1184 }
1185 Self::And(lhs, rhs) => {
1186 if lhs.precedence() < self.precedence() {
1187 write!(f, "({lhs})")?;
1188 } else {
1189 write!(f, "{lhs}")?;
1190 }
1191 write!(f, " && ")?;
1192 if rhs.precedence() <= self.precedence() {
1193 write!(f, "({rhs})")?;
1194 } else {
1195 write!(f, "{rhs}")?;
1196 }
1197 Ok(())
1198 }
1199 Self::Not(expr) => {
1200 if expr.precedence() <= self.precedence() {
1201 write!(f, "!({expr})")
1202 } else {
1203 write!(f, "!{expr}")
1204 }
1205 }
1206 Self::Comparison(expr) => write!(f, "{expr}"),
1207 Self::Test(test) => write!(f, "{test}"),
1208 }
1209 }
1210}
1211
1212impl Display for ComparisonExpr {
1213 #[inline]
1214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1215 write!(f, "{} {} {}", self.lhs, self.op, self.rhs)
1216 }
1217}
1218
1219impl Display for TestExpr {
1220 #[inline]
1221 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1222 match self {
1223 Self::Relative(q) => {
1224 write!(f, "@")?;
1225 for s in q.segments() {
1226 write!(f, "{s}")?;
1227 }
1228 }
1229 Self::Absolute(q) => {
1230 write!(f, "$")?;
1231 for s in q.segments() {
1232 write!(f, "{s}")?;
1233 }
1234 }
1235 }
1236 Ok(())
1237 }
1238}
1239
1240impl Display for Comparable {
1241 #[inline]
1242 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1243 match self {
1244 Self::Literal(lit) => write!(f, "{lit}"),
1245 Self::RelativeSingularQuery(q) => {
1246 write!(f, "@")?;
1247 for s in q.segments() {
1248 write!(f, "{s}")?;
1249 }
1250 Ok(())
1251 }
1252 Self::AbsoluteSingularQuery(q) => {
1253 write!(f, "$")?;
1254 for s in q.segments() {
1255 write!(f, "{s}")?;
1256 }
1257 Ok(())
1258 }
1259 }
1260 }
1261}
1262
1263impl Display for Literal {
1264 #[inline]
1265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1266 match self {
1267 Self::String(s) => write!(f, "\"{}\"", str::escape(s.unquoted(), str::EscapeMode::DoubleQuoted)),
1268 Self::Number(n) => write!(f, "{n}"),
1269 Self::Bool(true) => write!(f, "true"),
1270 Self::Bool(false) => write!(f, "false"),
1271 Self::Null => write!(f, "null"),
1272 }
1273 }
1274}
1275
1276impl Display for ComparisonOp {
1277 #[inline]
1278 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1279 match self {
1280 Self::EqualTo => write!(f, "=="),
1281 Self::NotEqualTo => write!(f, "!="),
1282 Self::LesserOrEqualTo => write!(f, "<="),
1283 Self::GreaterOrEqualTo => write!(f, ">="),
1284 Self::LessThan => write!(f, "<"),
1285 Self::GreaterThan => write!(f, ">"),
1286 }
1287 }
1288}
1289
1290impl Display for SingularJsonPathQuery {
1291 #[inline]
1292 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1293 for s in &self.segments {
1294 write!(f, "[{s}]")?;
1295 }
1296 Ok(())
1297 }
1298}
1299
1300impl Display for SingularSegment {
1301 #[inline]
1302 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1303 match self {
1304 Self::Name(n) => write!(f, "['{}']", str::escape(n.unquoted(), str::EscapeMode::SingleQuoted)),
1305 Self::Index(i) => write!(f, "[{i}]"),
1306 }
1307 }
1308}
1309
1310#[cfg(test)]
1311mod tests {
1312 use super::*;
1313 use pretty_assertions::assert_eq;
1314
1315 #[test]
1316 fn leading_whitespace_is_disallowed() {
1317 let err = parse(" $").expect_err("should fail");
1318 let display = format!("{err}");
1319 let expected = r"error: query starting with whitespace
1320
1321 $
1322 ^^ leading whitespace is disallowed
1323 (bytes 0-1)
1324
1325
1326suggestion: did you mean `$` ?
1327";
1328 assert_eq!(display, expected);
1329 }
1330
1331 #[test]
1332 fn trailing_whitespace_is_disallowed() {
1333 let err = parse("$ ").expect_err("should fail");
1334 let display = format!("{err}");
1335 let expected = r"error: query ending with whitespace
1336
1337 $
1338 ^^ trailing whitespace is disallowed
1339 (bytes 1-2)
1340
1341
1342suggestion: did you mean `$` ?
1343";
1344 assert_eq!(display, expected);
1345 }
1346
1347 mod name_selector {
1348 use super::*;
1349 use pretty_assertions::assert_eq;
1350 use test_case::test_case;
1351
1352 fn parse_single_quoted_name_selector(src: &str) -> Result<JsonPathQuery> {
1353 let query_string = format!("$['{src}']");
1354 parse(&query_string)
1355 }
1356
1357 #[test_case("", ""; "empty")]
1358 #[test_case("dog", "dog"; "ascii")]
1359 #[test_case(r"\\", r"\"; "backslash")]
1360 #[test_case("unescaped 🔥 fire emoji", "unescaped 🔥 fire emoji"; "unescaped emoji")]
1361 #[test_case(r"escape \b backspace", "escape \u{0008} backspace"; "BS escape")]
1362 #[test_case(r"escape \t tab", "escape \t tab"; "HT escape")]
1363 #[test_case(r"escape \n endln", "escape \n endln"; "LF escape")]
1364 #[test_case(r"escape \f formfeed", "escape \u{000C} formfeed"; "FF escape")]
1365 #[test_case(r"escape \r carriage", "escape \r carriage"; "CR escape")]
1366 #[test_case(r#"escape \' apost"#, r"escape ' apost"; "apostrophe escape")]
1367 #[test_case(r"escape \/ slash", r"escape / slash"; "slash escape")]
1368 #[test_case(r"escape \\ backslash", r"escape \ backslash"; "backslash escape")]
1369 #[test_case(r"escape \u2112 script L", "escape â„’ script L"; "U+2112 Script Capital L escape")]
1370 #[test_case(r"escape \u211269 script L", "escape â„’69 script L"; "U+2112 Script Capital L escape followed by digits")]
1371 #[test_case(r"escape \u21a7 bar down arrow", "escape ↧ bar down arrow"; "U+21a7 Downwards Arrow From Bar (lowercase hex)")]
1372 #[test_case(r"escape \u21A7 bar down arrow", "escape ↧ bar down arrow"; "U+21A7 Downwards Arrow From Bar (uppercase hex)")]
1373 #[test_case(r"escape \ud83d\udd25 fire emoji", "escape 🔥 fire emoji"; "U+1F525 fire emoji escape (lowercase hex)")]
1374 #[test_case(r"escape \uD83D\uDD25 fire emoji", "escape 🔥 fire emoji"; "U+1F525 fire emoji escape (uppercase hex)")]
1375 fn parse_correct_single_quoted_name(src: &str, expected: &str) {
1376 let res = parse_single_quoted_name_selector(src).expect("should successfully parse");
1377 match res.segments().first() {
1378 Some(Segment::Child(selectors)) => match selectors.first() {
1379 Selector::Name(name) => assert_eq!(name.unquoted(), expected),
1380 _ => panic!("expected to parse a single name selector, got {res:?}"),
1381 },
1382 _ => panic!("expected to parse a single name selector, got {res:?}"),
1383 }
1384 }
1385
1386 #[test]
1387 fn parse_double_quoted_name_with_escaped_double_quote() {
1388 let query_string = r#"$["escape \" quote"]"#;
1389 let res = parse(query_string).expect("should successfully parse");
1390 match res.segments().first() {
1391 Some(Segment::Child(selectors)) => match selectors.first() {
1392 Selector::Name(name) => assert_eq!(name.unquoted(), "escape \" quote"),
1393 _ => panic!("expected to parse a single name selector, got {res:?}"),
1394 },
1395 _ => panic!("expected to parse a single name selector, got {res:?}"),
1396 }
1397 }
1398 }
1399}