1use std::fmt::{self, Display};
2
3#[derive(Clone, Debug)]
5pub enum PathSegment {
6 Index(usize),
8 Key(String),
10 Variant(String),
12 Unknown,
14}
15
16#[derive(Clone, Debug, Default)]
18pub struct Path {
19 segments: Vec<PathSegment>,
21}
22
23impl Path {
24 pub fn new(segments: Vec<PathSegment>) -> Self {
26 Self { segments }
27 }
28
29 pub fn join(&self, segment: PathSegment) -> Self {
32 let mut path = self.clone();
33 path.segments.push(segment);
34 path
35 }
36
37 pub fn join_index(&self, index: usize) -> Self {
40 self.join(PathSegment::Index(index))
41 }
42
43 pub fn join_key(&self, key: impl Display) -> Self {
46 self.join(PathSegment::Key(format!("{key}")))
47 }
48
49 pub fn join_path(&self, other: &Self) -> Self {
52 let mut path = self.clone();
53 path.segments.extend(other.segments.clone());
54 path
55 }
56
57 pub fn join_variant(&self, variant: &str) -> Self {
60 self.join(PathSegment::Variant(variant.to_owned()))
61 }
62}
63
64impl Display for Path {
65 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
66 if self.segments.is_empty() {
67 return formatter.write_str(".");
68 }
69
70 let mut separator = "";
71
72 for segment in &self.segments {
73 match segment {
74 PathSegment::Index(index) => {
75 write!(formatter, "[{index}]")?;
76 }
77 PathSegment::Key(key) | PathSegment::Variant(key) => {
78 write!(formatter, "{separator}{key}")?;
79 }
80 PathSegment::Unknown => {
81 write!(formatter, "{separator}?")?;
82 }
83 }
84
85 separator = ".";
86 }
87
88 Ok(())
89 }
90}