1use std::fmt::Display;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub enum JsonPathElement {
5 Root,
6 Index(usize),
7 Key(String),
8}
9
10impl Display for JsonPathElement {
11 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12 let s = match self {
13 JsonPathElement::Root => "$".to_string(),
14 JsonPathElement::Index(index) => format!("{}", index),
15 JsonPathElement::Key(key) => key.to_string(),
16 };
17 write!(f, "{}", s)
18 }
19}
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct JsonPath(Vec<JsonPathElement>);
23
24impl Display for JsonPath {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 write!(
27 f,
28 "{}",
29 self.0
30 .iter()
31 .map(|e| format!("{}", e))
32 .collect::<Vec<String>>()
33 .join(".")
34 )
35 }
36}
37
38impl From<Vec<JsonPathElement>> for JsonPath {
39 fn from(elements: Vec<JsonPathElement>) -> Self {
40 Self(elements)
41 }
42}
43
44impl JsonPath {
45 pub fn extend<T: Into<JsonPath>>(mut self, elements: T) -> Self {
46 let mut elements = Into::<JsonPath>::into(elements).0;
47 if elements.first() == Some(&JsonPathElement::Root) {
48 elements = elements.into_iter().skip(1).collect();
49 }
50 let path = &mut self.0;
51 path.extend(elements);
52 self
53 }
54}
55
56impl Default for JsonPath {
57 fn default() -> Self {
58 Self(vec![JsonPathElement::Root])
59 }
60}
61
62#[derive(Debug, Clone, PartialEq, Eq)]
63pub struct JsonMatcherError {
64 pub path: JsonPath,
65 pub message: String,
66}
67
68impl JsonMatcherError {
69 pub fn at_root<T: Into<String>>(message: T) -> Self {
70 let message = message.into();
71 Self {
72 path: JsonPath::default(),
73 message,
74 }
75 }
76}
77
78impl Display for JsonMatcherError {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 write!(f, "{}: {}", self.path, self.message)
81 }
82}