Skip to main content

zyn_core/path/
segment.rs

1/// A single segment in a [`MetaPath`](super::MetaPath).
2///
3/// # Examples
4///
5/// ```ignore
6/// use zyn::path::Segment;
7///
8/// let key: Segment = "serde".into();
9/// let index: Segment = 0usize.into();
10///
11/// assert!(key.is_key());
12/// assert!(index.is_index());
13/// assert_eq!(key.to_string(), "serde");
14/// assert_eq!(index.to_string(), "0");
15/// ```
16#[derive(Clone, Debug, PartialEq, Eq)]
17pub enum Segment {
18    /// A named key segment (e.g., `serde` in `"serde.rename"`).
19    Key(String),
20    /// A positional index segment (e.g., `0` in `"derive[0]"`).
21    Index(usize),
22}
23
24impl Segment {
25    /// Returns `true` if this is a key segment.
26    pub fn is_key(&self) -> bool {
27        matches!(self, Self::Key(_))
28    }
29
30    /// Returns `true` if this is an index segment.
31    pub fn is_index(&self) -> bool {
32        matches!(self, Self::Index(_))
33    }
34
35    /// Returns the key string if this is a key segment.
36    pub fn as_key(&self) -> Option<&str> {
37        match self {
38            Self::Key(k) => Some(k),
39            _ => None,
40        }
41    }
42
43    /// Returns the index value if this is an index segment.
44    pub fn as_index(&self) -> Option<usize> {
45        match self {
46            Self::Index(i) => Some(*i),
47            _ => None,
48        }
49    }
50}
51
52impl From<String> for Segment {
53    fn from(key: String) -> Self {
54        Self::Key(key)
55    }
56}
57
58impl From<&str> for Segment {
59    fn from(key: &str) -> Self {
60        Self::Key(key.to_owned())
61    }
62}
63
64impl From<usize> for Segment {
65    fn from(index: usize) -> Self {
66        Self::Index(index)
67    }
68}
69
70impl std::fmt::Display for Segment {
71    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72        match self {
73            Self::Key(k) => write!(f, "{}", k),
74            Self::Index(i) => write!(f, "{}", i),
75        }
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    mod predicates {
84        use super::*;
85
86        #[test]
87        fn key_is_key() {
88            let seg: Segment = "foo".into();
89            assert!(seg.is_key());
90            assert!(!seg.is_index());
91        }
92
93        #[test]
94        fn index_is_index() {
95            let seg: Segment = 0usize.into();
96            assert!(seg.is_index());
97            assert!(!seg.is_key());
98        }
99    }
100
101    mod conversions {
102        use super::*;
103
104        #[test]
105        fn as_key_some() {
106            let seg: Segment = "foo".into();
107            assert_eq!(seg.as_key(), Some("foo"));
108        }
109
110        #[test]
111        fn as_key_none() {
112            let seg: Segment = 0usize.into();
113            assert!(seg.as_key().is_none());
114        }
115
116        #[test]
117        fn as_index_some() {
118            let seg: Segment = 3usize.into();
119            assert_eq!(seg.as_index(), Some(3));
120        }
121
122        #[test]
123        fn as_index_none() {
124            let seg: Segment = "foo".into();
125            assert!(seg.as_index().is_none());
126        }
127    }
128
129    mod display {
130        use super::*;
131
132        #[test]
133        fn key_display() {
134            let seg: Segment = "serde".into();
135            assert_eq!(seg.to_string(), "serde");
136        }
137
138        #[test]
139        fn index_display() {
140            let seg: Segment = 42usize.into();
141            assert_eq!(seg.to_string(), "42");
142        }
143    }
144
145    mod from {
146        use super::*;
147
148        #[test]
149        fn from_str() {
150            let seg: Segment = "hello".into();
151            assert_eq!(seg, Segment::Key("hello".into()));
152        }
153
154        #[test]
155        fn from_string() {
156            let seg: Segment = String::from("hello").into();
157            assert_eq!(seg, Segment::Key("hello".into()));
158        }
159
160        #[test]
161        fn from_usize() {
162            let seg: Segment = 5usize.into();
163            assert_eq!(seg, Segment::Index(5));
164        }
165    }
166}