1use std::{
2 fmt::{self, Display, Formatter},
3 rc::Rc,
4};
5
6use derive_getters::Getters;
7
8use super::query_key::{QueryKey, RawKey};
9
10#[derive(Debug, Clone, Copy)]
11pub enum JsonPathEntry<'a> {
12 Key(&'a str),
14 Index(usize),
15}
16
17#[derive(Debug, Clone)]
19pub enum OwnedJsonPathEntry {
20 Key(String),
21 Index(usize),
22}
23
24impl From<&JsonPathEntry<'_>> for OwnedJsonPathEntry {
25 fn from(entry: &JsonPathEntry) -> Self {
26 match entry {
27 JsonPathEntry::Key(key) => OwnedJsonPathEntry::Key(key.to_string()),
28 JsonPathEntry::Index(index) => OwnedJsonPathEntry::Index(*index),
29 }
30 }
31}
32
33#[derive(Debug, Clone)]
34pub enum JsonPath<'a> {
35 Root,
36 Node {
37 entry: JsonPathEntry<'a>,
38 parent: Rc<JsonPath<'a>>,
39 },
40}
41
42impl<'a> JsonPath<'a> {
43 pub fn push(&self, entry: JsonPathEntry<'a>) -> Self {
44 Self::Node {
45 entry,
46 parent: Rc::new(self.clone()),
47 }
48 }
49}
50
51impl Display for JsonPath<'_> {
53 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
54 match self {
55 JsonPath::Root => write!(f, "."),
56 JsonPath::Node { entry, parent } => {
57 match **parent {
58 JsonPath::Root => {}
59 _ => parent.fmt(f)?,
60 }
61 match entry {
62 JsonPathEntry::Key(key) => write!(f, ".{key}"),
63 JsonPathEntry::Index(index) => write!(f, "[{index}]"),
64 }
65 }
66 }
67 }
68}
69
70#[derive(Debug, Clone)]
71pub struct OwnedJsonPath(pub Vec<OwnedJsonPathEntry>);
72
73impl From<&JsonPath<'_>> for OwnedJsonPath {
74 fn from(json_path: &JsonPath) -> Self {
75 let mut key_path = Vec::new();
76 let mut current = json_path;
77 while let JsonPath::Node { entry, parent } = current {
78 key_path.push(OwnedJsonPathEntry::from(entry));
79 current = parent;
80 }
81 key_path.reverse();
82 OwnedJsonPath(key_path)
83 }
84}
85
86impl Display for OwnedJsonPath {
88 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
89 if self.0.is_empty() {
90 return write!(f, ".");
91 }
92 for entry in &self.0 {
93 match entry {
94 OwnedJsonPathEntry::Key(key) => write!(f, ".{key}")?,
95 OwnedJsonPathEntry::Index(index) => write!(f, "[{index}]")?,
96 }
97 }
98 Ok(())
99 }
100}
101
102#[derive(Debug, Clone, Getters)]
103pub struct ArrayContext<'a> {
104 path: JsonPath<'a>,
105}
106
107#[derive(Debug, Clone, Getters)]
108pub struct Context<'a> {
109 path: JsonPath<'a>,
110 array_context: Option<ArrayContext<'a>>,
111}
112
113impl<'a> Context<'a> {
114 pub fn new() -> Self {
115 Self::default()
116 }
117
118 pub fn push_raw_key(&self, raw_key: &'a RawKey) -> Context<'a> {
120 let entry = JsonPathEntry::Key(raw_key.as_str());
121 self.push_entry(entry)
122 }
123
124 pub fn push_index(&self, index: usize) -> Context<'a> {
125 let entry = JsonPathEntry::Index(index);
126 self.push_entry(entry)
127 }
128
129 pub fn push_query_key(&self, query_key: &'a QueryKey) -> Context<'a> {
131 let mut path = self.path.clone();
132 for atomic_query_key in query_key.keys() {
134 path = path.push(JsonPathEntry::Key(atomic_query_key.key().as_str()));
135 }
136 Self {
137 path,
138 ..self.clone()
139 }
140 }
141
142 pub fn enter_array(&self) -> Self {
143 Self {
144 array_context: Some(ArrayContext {
145 path: self.path.clone(),
146 }),
147 ..self.clone()
148 }
149 }
150
151 fn push_entry(&self, entry: JsonPathEntry<'a>) -> Context<'a> {
152 Self {
153 path: self.path.push(entry),
154 ..self.clone()
155 }
156 }
157}
158
159impl Default for Context<'_> {
160 fn default() -> Self {
161 Self {
162 path: JsonPath::Root,
163 array_context: None,
164 }
165 }
166}