yrs/json_path/
mod.rs

1use std::fmt::{Display, Formatter};
2
3mod iter_any;
4mod iter_txn;
5mod parse;
6
7pub use iter_txn::JsonPathIter;
8
9/// Trait implemented by types capable of evaluating JSON Paths.
10pub 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}