1use serde::{Deserialize, Serialize};
7use std::fmt;
8
9#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
11#[serde(untagged)]
12pub enum Seg {
13 Key(String),
15 Index(usize),
17}
18
19impl Seg {
20 #[inline]
22 pub fn key(k: impl Into<String>) -> Self {
23 Seg::Key(k.into())
24 }
25
26 #[inline]
28 pub fn index(i: usize) -> Self {
29 Seg::Index(i)
30 }
31
32 #[inline]
34 pub fn is_key(&self) -> bool {
35 matches!(self, Seg::Key(_))
36 }
37
38 #[inline]
40 pub fn is_index(&self) -> bool {
41 matches!(self, Seg::Index(_))
42 }
43
44 #[inline]
46 pub fn as_key(&self) -> Option<&str> {
47 match self {
48 Seg::Key(k) => Some(k),
49 Seg::Index(_) => None,
50 }
51 }
52
53 #[inline]
55 pub fn as_index(&self) -> Option<usize> {
56 match self {
57 Seg::Key(_) => None,
58 Seg::Index(i) => Some(*i),
59 }
60 }
61}
62
63impl fmt::Display for Seg {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 match self {
66 Seg::Key(k) => write!(f, ".{}", k),
67 Seg::Index(i) => write!(f, "[{}]", i),
68 }
69 }
70}
71
72impl From<String> for Seg {
73 fn from(s: String) -> Self {
74 Seg::Key(s)
75 }
76}
77
78impl From<&str> for Seg {
79 fn from(s: &str) -> Self {
80 Seg::Key(s.to_owned())
81 }
82}
83
84impl From<usize> for Seg {
85 fn from(i: usize) -> Self {
86 Seg::Index(i)
87 }
88}
89
90#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
104pub struct Path(Vec<Seg>);
105
106impl Path {
107 #[inline]
109 pub fn new() -> Self {
110 Self(Vec::new())
111 }
112
113 #[inline]
115 pub fn root() -> Self {
116 Self::new()
117 }
118
119 #[inline]
121 pub fn from_segments(segments: Vec<Seg>) -> Self {
122 Self(segments)
123 }
124
125 #[inline]
127 pub fn with_capacity(capacity: usize) -> Self {
128 Self(Vec::with_capacity(capacity))
129 }
130
131 #[inline]
133 pub fn key(mut self, k: impl Into<String>) -> Self {
134 self.0.push(Seg::Key(k.into()));
135 self
136 }
137
138 #[inline]
140 pub fn index(mut self, i: usize) -> Self {
141 self.0.push(Seg::Index(i));
142 self
143 }
144
145 #[inline]
147 pub fn push(&mut self, seg: Seg) {
148 self.0.push(seg);
149 }
150
151 #[inline]
153 pub fn push_key(&mut self, k: impl Into<String>) {
154 self.0.push(Seg::Key(k.into()));
155 }
156
157 #[inline]
159 pub fn push_index(&mut self, i: usize) {
160 self.0.push(Seg::Index(i));
161 }
162
163 #[inline]
165 pub fn pop(&mut self) -> Option<Seg> {
166 self.0.pop()
167 }
168
169 #[inline]
171 pub fn segments(&self) -> &[Seg] {
172 &self.0
173 }
174
175 #[inline]
177 pub fn segments_mut(&mut self) -> &mut Vec<Seg> {
178 &mut self.0
179 }
180
181 #[inline]
183 pub fn is_empty(&self) -> bool {
184 self.0.is_empty()
185 }
186
187 #[inline]
189 pub fn len(&self) -> usize {
190 self.0.len()
191 }
192
193 #[inline]
195 pub fn first(&self) -> Option<&Seg> {
196 self.0.first()
197 }
198
199 #[inline]
201 pub fn last(&self) -> Option<&Seg> {
202 self.0.last()
203 }
204
205 #[inline]
207 pub fn join(&self, other: &Path) -> Path {
208 let mut result = self.clone();
209 result.0.extend(other.0.iter().cloned());
210 result
211 }
212
213 #[inline]
215 pub fn with_segment(&self, seg: Seg) -> Path {
216 let mut result = self.clone();
217 result.0.push(seg);
218 result
219 }
220
221 #[inline]
239 pub fn is_prefix_of(&self, other: &Path) -> bool {
240 if self.len() > other.len() {
241 return false;
242 }
243 self.0.iter().zip(other.0.iter()).all(|(a, b)| a == b)
244 }
245
246 #[inline]
248 pub fn extend(&mut self, other: &Path) {
249 self.0.extend(other.0.iter().cloned());
250 }
251
252 #[inline]
254 pub fn parent(&self) -> Option<Path> {
255 if self.0.is_empty() {
256 None
257 } else {
258 let mut p = self.clone();
259 p.pop();
260 Some(p)
261 }
262 }
263
264 #[inline]
266 pub fn starts_with(&self, prefix: &Path) -> bool {
267 self.0.starts_with(&prefix.0)
268 }
269
270 #[inline]
272 pub fn slice(&self, start: usize, end: usize) -> Path {
273 Path(self.0[start..end].to_vec())
274 }
275
276 #[inline]
278 pub fn iter(&self) -> impl Iterator<Item = &Seg> {
279 self.0.iter()
280 }
281}
282
283impl fmt::Display for Path {
284 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
285 if self.0.is_empty() {
286 write!(f, "$")
287 } else {
288 write!(f, "$")?;
289 for seg in &self.0 {
290 write!(f, "{}", seg)?;
291 }
292 Ok(())
293 }
294 }
295}
296
297impl FromIterator<Seg> for Path {
298 fn from_iter<I: IntoIterator<Item = Seg>>(iter: I) -> Self {
299 Path(iter.into_iter().collect())
300 }
301}
302
303impl IntoIterator for Path {
304 type Item = Seg;
305 type IntoIter = std::vec::IntoIter<Seg>;
306
307 fn into_iter(self) -> Self::IntoIter {
308 self.0.into_iter()
309 }
310}
311
312impl<'a> IntoIterator for &'a Path {
313 type Item = &'a Seg;
314 type IntoIter = std::slice::Iter<'a, Seg>;
315
316 fn into_iter(self) -> Self::IntoIter {
317 self.0.iter()
318 }
319}
320
321impl std::ops::Index<usize> for Path {
322 type Output = Seg;
323
324 fn index(&self, index: usize) -> &Self::Output {
325 &self.0[index]
326 }
327}
328
329#[macro_export]
346macro_rules! path {
347 () => {
348 $crate::Path::root()
349 };
350 ($($seg:expr),+ $(,)?) => {{
351 let mut p = $crate::Path::root();
352 $(
353 p.push($crate::path!(@seg $seg));
354 )+
355 p
356 }};
357 (@seg $seg:expr) => {
358 $crate::Seg::from($seg)
359 };
360}
361
362#[cfg(test)]
363mod tests {
364 use super::*;
365
366 #[test]
367 fn test_path_construction() {
368 let path = Path::root().key("users").index(0).key("name");
369 assert_eq!(path.len(), 3);
370 assert_eq!(path[0], Seg::Key("users".into()));
371 assert_eq!(path[1], Seg::Index(0));
372 assert_eq!(path[2], Seg::Key("name".into()));
373 }
374
375 #[test]
376 fn test_path_display() {
377 let path = Path::root().key("users").index(0).key("name");
378 assert_eq!(format!("{}", path), "$.users[0].name");
379 }
380
381 #[test]
382 fn test_path_macro() {
383 let p = path!("users", 0, "name");
384 assert_eq!(p.len(), 3);
385 assert_eq!(p[0], Seg::Key("users".into()));
386 assert_eq!(p[1], Seg::Index(0));
387 assert_eq!(p[2], Seg::Key("name".into()));
388 }
389
390 #[test]
391 fn test_path_join() {
392 let base = Path::root().key("data");
393 let sub = Path::root().key("items").index(0);
394 let joined = base.join(&sub);
395 assert_eq!(joined.len(), 3);
396 }
397
398 #[test]
399 fn test_path_parent() {
400 let path = Path::root().key("a").key("b");
401 let parent = path.parent().unwrap();
402 assert_eq!(parent.len(), 1);
403 assert_eq!(parent[0], Seg::Key("a".into()));
404 }
405
406 #[test]
407 fn test_path_serde() {
408 let path = Path::root().key("users").index(0);
409 let json = serde_json::to_string(&path).unwrap();
410 let parsed: Path = serde_json::from_str(&json).unwrap();
411 assert_eq!(path, parsed);
412 }
413}