json_predicate/
json_path.rs

1use json_pointer::{JsonPointer, ParseError};
2use serde::{Deserialize, Deserializer, Serialize};
3use std::ops::Add;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct JSONPath(JsonPointer<String, Vec<String>>);
7
8impl Default for JSONPath {
9    fn default() -> Self {
10        Self(JsonPointer::new(Vec::new()))
11    }
12}
13
14#[derive(Debug, thiserror::Error)]
15pub enum JSONPathError {
16    /// An invalid escape sequence was encountered, either a `~` escape or a
17    /// `%` escape.
18    #[error("An invalid escape sequence was encountered, either a `~` escape or a `%` escape.")]
19    InvalidEscape,
20    /// An error caused by not having a leading slash on the JSON pointer.
21    ///
22    /// For example, the string `a/b/c` is not a valid JSON pointer, while
23    /// `/a/b/c` is.
24    #[error("An error caused by not having a leading slash on the JSON pointer.")]
25    NoLeadingSlash,
26}
27
28impl JSONPath {
29    pub fn new<S: AsRef<str>>(value: S) -> Result<JSONPath, JSONPathError> {
30        let ptr = value.as_ref().parse::<JsonPointer<_, _>>();
31        match ptr {
32            Ok(ptr) => Ok(JSONPath(ptr)),
33            Err(ParseError::NoLeadingSlash) => Err(JSONPathError::NoLeadingSlash),
34            Err(ParseError::InvalidEscape(_)) => Err(JSONPathError::InvalidEscape),
35        }
36    }
37
38    pub fn empty() -> Self {
39        Self::new("/").expect("Can't fail")
40    }
41
42    pub fn take(self) -> JsonPointer<String, Vec<String>> {
43        self.0
44    }
45}
46
47impl Serialize for JSONPath {
48    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
49    where
50        S: serde::Serializer,
51    {
52        let val = self.0.to_string();
53        serializer.serialize_str(&val)
54    }
55}
56
57impl Add for JSONPath {
58    type Output = Self;
59
60    fn add(self, other: Self) -> Self::Output {
61        // TODO: Fix it because it's an unwrap that shouldn't be here as we should be sure that it
62        // works.
63        Self::new(format!("{}{}", self.0, other.0)).unwrap()
64    }
65}
66
67impl<'de> Deserialize<'de> for JSONPath {
68    fn deserialize<D>(deserializer: D) -> Result<JSONPath, D::Error>
69    where
70        D: Deserializer<'de>,
71    {
72        let s = String::deserialize(deserializer)?;
73        let ptr = s
74            .parse::<JsonPointer<_, _>>()
75            .map_err(|e| serde::de::Error::custom(format!("{:?}", e)))?;
76        Ok(JSONPath(ptr))
77    }
78}