1use std::fmt::{Display, Formatter};
2
3mod iter_any;
4mod iter_txn;
5mod parse;
6
7pub use iter_txn::JsonPathIter;
8
9pub trait JsonPathEval {
11 type Iter<'a>
12 where
13 Self: 'a;
14 fn json_path<'a>(&'a self, path: &'a JsonPath<'a>) -> Self::Iter<'a>;
15}
16
17#[derive(Debug, Clone, PartialEq)]
18pub struct JsonPath<'a> {
19 tokens: Vec<JsonPathToken<'a>>,
20}
21
22impl<'a> AsRef<[JsonPathToken<'a>]> for JsonPath<'a> {
23 fn as_ref(&self) -> &[JsonPathToken<'a>] {
24 &self.tokens
25 }
26}
27
28#[derive(Debug, Clone, PartialEq)]
29pub(super) enum JsonPathToken<'a> {
30 Root,
31 Current,
32 Member(&'a str),
33 Index(i32),
34 Wildcard,
35 RecursiveDescend,
36 Slice(u32, u32, u32),
37 MemberUnion(Vec<&'a str>),
38 IndexUnion(Vec<i32>),
39}
40
41impl<'a> Display for JsonPathToken<'a> {
42 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
43 match self {
44 JsonPathToken::Root => write!(f, r#"$"#),
45 JsonPathToken::Current => write!(f, "@"),
46 JsonPathToken::Member(key) => {
47 if key.chars().any(char::is_whitespace) {
48 write!(f, "['{}']", key)
49 } else {
50 write!(f, ".{}", key)
51 }
52 }
53 JsonPathToken::Index(index) => write!(f, "[{}]", index),
54 JsonPathToken::Wildcard => write!(f, ".*"),
55 JsonPathToken::RecursiveDescend => write!(f, ".."),
56 JsonPathToken::Slice(from, to, by) => write!(f, "[{}:{}:{}]", from, to, by),
57 JsonPathToken::MemberUnion(members) => {
58 let mut i = members.iter();
59 write!(f, "[")?;
60 if let Some(m) = i.next() {
61 write!(f, "{}", m)?;
62 }
63 while let Some(m) = i.next() {
64 write!(f, ", {}", m)?;
65 }
66 write!(f, "]")
67 }
68 JsonPathToken::IndexUnion(indices) => {
69 let mut i = indices.iter();
70 write!(f, "[")?;
71 if let Some(m) = i.next() {
72 write!(f, "{}", m)?;
73 }
74 while let Some(m) = i.next() {
75 write!(f, ", {}", m)?;
76 }
77 write!(f, "]")
78 }
79 }
80 }
81}
82
83#[derive(Debug, thiserror::Error)]
84pub enum ParseError {
85 #[error("{0}")]
86 InvalidJsonPath(String),
87}