1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use json_pointer::{JsonPointer, ParseError};
use serde::{Deserialize, Deserializer, Serialize};
use std::ops::Add;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct JSONPath(JsonPointer<String, Vec<String>>);

impl Default for JSONPath {
    fn default() -> Self {
        Self(JsonPointer::new(Vec::new()))
    }
}

#[derive(Debug, thiserror::Error)]
pub enum JSONPathError {
    /// An invalid escape sequence was encountered, either a `~` escape or a
    /// `%` escape.
    #[error("An invalid escape sequence was encountered, either a `~` escape or a `%` escape.")]
    InvalidEscape,
    /// An error caused by not having a leading slash on the JSON pointer.
    ///
    /// For example, the string `a/b/c` is not a valid JSON pointer, while
    /// `/a/b/c` is.
    #[error("An error caused by not having a leading slash on the JSON pointer.")]
    NoLeadingSlash,
}

impl JSONPath {
    pub fn new<S: AsRef<str>>(value: S) -> Result<JSONPath, JSONPathError> {
        let ptr = value.as_ref().parse::<JsonPointer<_, _>>();
        match ptr {
            Ok(ptr) => Ok(JSONPath(ptr)),
            Err(ParseError::NoLeadingSlash) => Err(JSONPathError::NoLeadingSlash),
            Err(ParseError::InvalidEscape(_)) => Err(JSONPathError::InvalidEscape),
        }
    }

    pub fn empty() -> Self {
        Self::new("/").expect("Can't fail")
    }

    pub fn take(self) -> JsonPointer<String, Vec<String>> {
        self.0
    }
}

impl Serialize for JSONPath {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let val = self.0.to_string();
        Ok(serializer.serialize_str(&val)?)
    }
}

impl Add for JSONPath {
    type Output = Self;

    fn add(self, other: Self) -> Self::Output {
        // TODO: Fix it because it's an unwrap that shouldn't be here as we should be sure that it
        // works.
        Self::new(format!("{}{}", self.0.to_string(), other.0.to_string())).unwrap()
    }
}

impl<'de> Deserialize<'de> for JSONPath {
    fn deserialize<D>(deserializer: D) -> Result<JSONPath, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        let ptr = s
            .parse::<JsonPointer<_, _>>()
            .map_err(|e| serde::de::Error::custom(format!("{:?}", e)))?;
        Ok(JSONPath(ptr))
    }
}