1use core::fmt;
7use std::fmt::{Display, Formatter};
8use std::sync::Arc;
9
10use itertools::Itertools;
11
12#[derive(Clone, Debug, PartialEq, Eq, Hash)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15pub enum Field {
16 Name(Arc<str>),
18 ElementType,
20}
21
22impl From<&str> for Field {
23 fn from(value: &str) -> Self {
24 Field::Name(value.into())
25 }
26}
27
28impl From<Arc<str>> for Field {
29 fn from(value: Arc<str>) -> Self {
30 Self::Name(value)
31 }
32}
33
34impl From<&Arc<str>> for Field {
35 fn from(value: &Arc<str>) -> Self {
36 Self::Name(value.clone())
37 }
38}
39
40impl From<String> for Field {
41 fn from(value: String) -> Self {
42 Field::Name(value.into())
43 }
44}
45
46impl Display for Field {
47 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
48 match self {
49 Field::Name(name) => write!(f, "${name}"),
50 Field::ElementType => write!(f, "[]"),
51 }
52 }
53}
54
55impl Field {
56 pub fn is_named(&self) -> bool {
58 matches!(self, Field::Name(_))
59 }
60}
61
62#[derive(Clone, Debug, PartialEq, Eq, Hash)]
66#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
67pub struct FieldPath(Vec<Field>);
68
69impl FieldPath {
70 pub fn root() -> Self {
72 Self(vec![])
73 }
74
75 pub fn from_name<F: Into<Field>>(name: F) -> Self {
77 Self(vec![name.into()])
78 }
79
80 pub fn path(&self) -> &[Field] {
82 &self.0
83 }
84
85 pub fn is_root(&self) -> bool {
87 self.0.is_empty()
88 }
89
90 pub fn push<F: Into<Field>>(mut self, field: F) -> Self {
92 self.0.push(field.into());
93 self
94 }
95
96 pub fn starts_with_field(&self, field: &Field) -> bool {
99 assert!(matches!(field, Field::Name(_)));
100 let first = self.0.first();
101 assert!(matches!(first, Some(Field::Name(_))));
102 first.is_some_and(|f| f == field)
103 }
104
105 pub fn step_into(mut self) -> Option<Self> {
107 if self.0.is_empty() {
108 return None;
109 }
110 self.0 = self.0.iter().skip(1).cloned().collect();
111 Some(self)
112 }
113}
114
115impl FromIterator<Field> for FieldPath {
116 fn from_iter<T: IntoIterator<Item = Field>>(iter: T) -> Self {
117 FieldPath(iter.into_iter().collect())
118 }
119}
120
121impl From<Field> for FieldPath {
122 fn from(value: Field) -> Self {
123 FieldPath(vec![value])
124 }
125}
126
127impl From<Vec<Field>> for FieldPath {
128 fn from(value: Vec<Field>) -> Self {
129 FieldPath(value)
130 }
131}
132
133impl Display for FieldPath {
134 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
135 Display::fmt(&self.0.iter().format("."), f)
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn test_field_path() {
145 let path = FieldPath::from_name("A").push("B").push("C");
146 assert_eq!(path.to_string(), "$A.$B.$C");
147
148 let fields = vec!["A", "B", "C"]
149 .into_iter()
150 .map(Field::from)
151 .collect_vec();
152 assert_eq!(path.path(), &fields);
153
154 let vec_path = FieldPath::from(fields);
155 assert_eq!(vec_path.to_string(), "$A.$B.$C");
156 assert_eq!(path, vec_path);
157 }
158}