1use crate::child_name::ChildName;
6use crate::error::MonikerError;
7use cm_rust::{FidlIntoNative, NativeIntoFidl};
8use core::cmp::{self, Ordering, PartialEq};
9use std::fmt;
10use std::hash::Hash;
11
12#[derive(Eq, PartialEq, Clone, Hash, Default)]
17pub struct Moniker {
18 path: Vec<ChildName>,
19}
20
21impl Moniker {
22 pub fn new(path: Vec<ChildName>) -> Self {
23 Self { path }
24 }
25
26 pub fn path(&self) -> &Vec<ChildName> {
27 &self.path
28 }
29
30 pub fn path_mut(&mut self) -> &mut Vec<ChildName> {
31 &mut self.path
32 }
33
34 pub fn parse<T: AsRef<str>>(path: &[T]) -> Result<Self, MonikerError> {
35 let path: Result<Vec<ChildName>, MonikerError> =
36 path.iter().map(ChildName::parse).collect();
37 Ok(Self::new(path?))
38 }
39
40 pub fn parse_str(input: &str) -> Result<Self, MonikerError> {
41 if input.is_empty() {
42 return Err(MonikerError::invalid_moniker(input));
43 }
44 if input == "/" || input == "." || input == "./" {
45 return Ok(Self::new(vec![]));
46 }
47
48 let stripped = match input.strip_prefix("/") {
50 Some(s) => s,
51 None => match input.strip_prefix("./") {
52 Some(s) => s,
53 None => input,
54 },
55 };
56 let path =
57 stripped.split('/').map(ChildName::parse).collect::<Result<_, MonikerError>>()?;
58 Ok(Self::new(path))
59 }
60
61 pub fn concat(&self, other: &Moniker) -> Self {
63 let mut path = self.path().clone();
64 let mut other_path = other.path().clone();
65 path.append(&mut other_path);
66 Self::new(path)
67 }
68
69 pub fn has_prefix(&self, prefix: &Moniker) -> bool {
71 if self.path().len() < prefix.path().len() {
72 return false;
73 }
74
75 prefix.path().iter().enumerate().all(|item| *item.1 == self.path()[item.0])
76 }
77
78 pub fn root() -> Self {
79 Self::new(vec![])
80 }
81
82 pub fn leaf(&self) -> Option<&ChildName> {
83 self.path().last()
84 }
85
86 pub fn is_root(&self) -> bool {
87 self.path().is_empty()
88 }
89
90 pub fn parent(&self) -> Option<Self> {
91 if self.is_root() {
92 None
93 } else {
94 let l = self.path().len() - 1;
95 Some(Self::new(self.path()[..l].to_vec()))
96 }
97 }
98
99 pub fn child(&self, child: ChildName) -> Self {
100 let mut path = self.path().clone();
101 path.push(child);
102 Self::new(path)
103 }
104
105 pub fn next(&mut self) -> Option<ChildName> {
106 let path = self.path_mut();
107 if path.is_empty() {
108 return None;
109 }
110 Some(path.remove(0))
111 }
112
113 pub fn strip_prefix(&self, prefix: &Moniker) -> Result<Self, MonikerError> {
115 if !self.has_prefix(prefix) {
116 return Err(MonikerError::MonikerDoesNotHavePrefix {
117 moniker: self.to_string(),
118 prefix: prefix.to_string(),
119 });
120 }
121
122 let prefix_len = prefix.path().len();
123 let mut path = self.path().clone();
124 path.drain(0..prefix_len);
125 Ok(Self::new(path))
126 }
127}
128
129impl FidlIntoNative<Moniker> for String {
130 fn fidl_into_native(self) -> Moniker {
131 self.parse().unwrap()
134 }
135}
136
137impl NativeIntoFidl<String> for Moniker {
138 fn native_into_fidl(self) -> String {
139 self.to_string()
140 }
141}
142
143impl TryFrom<Vec<&str>> for Moniker {
144 type Error = MonikerError;
145
146 fn try_from(rep: Vec<&str>) -> Result<Self, MonikerError> {
147 Self::parse(&rep)
148 }
149}
150
151impl TryFrom<&str> for Moniker {
152 type Error = MonikerError;
153
154 fn try_from(input: &str) -> Result<Self, MonikerError> {
155 Self::parse_str(input)
156 }
157}
158
159impl std::str::FromStr for Moniker {
160 type Err = MonikerError;
161 fn from_str(s: &str) -> Result<Self, Self::Err> {
162 Self::parse_str(s)
163 }
164}
165
166impl cmp::Ord for Moniker {
167 fn cmp(&self, other: &Self) -> cmp::Ordering {
168 let min_size = cmp::min(self.path().len(), other.path().len());
169 for i in 0..min_size {
170 if self.path()[i] < other.path()[i] {
171 return cmp::Ordering::Less;
172 } else if self.path()[i] > other.path()[i] {
173 return cmp::Ordering::Greater;
174 }
175 }
176 if self.path().len() > other.path().len() {
177 return cmp::Ordering::Greater;
178 } else if self.path().len() < other.path().len() {
179 return cmp::Ordering::Less;
180 }
181
182 cmp::Ordering::Equal
183 }
184}
185
186impl PartialOrd for Moniker {
187 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
188 Some(self.cmp(other))
189 }
190}
191
192impl fmt::Display for Moniker {
193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 if self.path().is_empty() {
195 write!(f, ".")?;
196 } else {
197 write!(f, "{}", self.path()[0])?;
198 for segment in self.path()[1..].iter() {
199 write!(f, "/{}", segment)?;
200 }
201 }
202 Ok(())
203 }
204}
205
206impl fmt::Debug for Moniker {
207 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
208 write!(f, "{self}")
209 }
210}
211
212#[cfg(test)]
213mod tests {
214 use super::*;
215 use cm_types::Name;
216
217 #[test]
218 fn monikers() {
219 let root = Moniker::root();
220 assert_eq!(true, root.is_root());
221 assert_eq!(".", format!("{}", root));
222 assert_eq!(root, Moniker::new(vec![]));
223 assert_eq!(root, Moniker::try_from(vec![]).unwrap());
224
225 let m = Moniker::new(vec![
226 ChildName::try_new("a", None).unwrap(),
227 ChildName::try_new("b", Some("coll")).unwrap(),
228 ]);
229 assert_eq!(false, m.is_root());
230 assert_eq!("a/coll:b", format!("{}", m));
231 assert_eq!(m, Moniker::try_from(vec!["a", "coll:b"]).unwrap());
232 assert_eq!(m.leaf().map(|m| m.collection()).flatten(), Some(&Name::new("coll").unwrap()));
233 assert_eq!(m.leaf().map(|m| m.name().as_str()), Some("b"));
234 assert_eq!(m.leaf(), Some(&ChildName::try_from("coll:b").unwrap()));
235 }
236
237 #[test]
238 fn moniker_parent() {
239 let root = Moniker::root();
240 assert_eq!(true, root.is_root());
241 assert_eq!(None, root.parent());
242
243 let m = Moniker::new(vec![
244 ChildName::try_new("a", None).unwrap(),
245 ChildName::try_new("b", None).unwrap(),
246 ]);
247 assert_eq!("a/b", format!("{}", m));
248 assert_eq!("a", format!("{}", m.parent().unwrap()));
249 assert_eq!(".", format!("{}", m.parent().unwrap().parent().unwrap()));
250 assert_eq!(None, m.parent().unwrap().parent().unwrap().parent());
251 assert_eq!(m.leaf(), Some(&ChildName::try_from("b").unwrap()));
252 }
253
254 #[test]
255 fn moniker_concat() {
256 let scope_root: Moniker = vec!["a:test1", "b:test2"].try_into().unwrap();
257
258 let relative: Moniker = vec!["c:test3", "d:test4"].try_into().unwrap();
259 let descendant = scope_root.concat(&relative);
260 assert_eq!("a:test1/b:test2/c:test3/d:test4", format!("{}", descendant));
261
262 let relative: Moniker = vec![].try_into().unwrap();
263 let descendant = scope_root.concat(&relative);
264 assert_eq!("a:test1/b:test2", format!("{}", descendant));
265 }
266
267 #[test]
268 fn moniker_next() {
269 let mut root = Moniker::root();
270 assert_eq!(None, root.next());
271
272 let mut m = Moniker::new(vec![
273 ChildName::try_new("a", None).unwrap(),
274 ChildName::try_new("b", None).unwrap(),
275 ]);
276 assert_eq!("a", format!("{}", m.next().unwrap()));
277 assert_eq!("b", format!("{}", m.next().unwrap()));
278 assert_eq!(None, m.next());
279 assert_eq!(None, m.next());
280 }
281
282 #[test]
283 fn moniker_parse_str() {
284 assert_eq!(Moniker::try_from("/foo").unwrap(), Moniker::try_from(vec!["foo"]).unwrap());
285 assert_eq!(Moniker::try_from("./foo").unwrap(), Moniker::try_from(vec!["foo"]).unwrap());
286 assert_eq!(Moniker::try_from("foo").unwrap(), Moniker::try_from(vec!["foo"]).unwrap());
287 assert_eq!(Moniker::try_from("/").unwrap(), Moniker::try_from(vec![]).unwrap());
288 assert_eq!(Moniker::try_from("./").unwrap(), Moniker::try_from(vec![]).unwrap());
289
290 assert!(Moniker::try_from("//foo").is_err());
291 assert!(Moniker::try_from(".//foo").is_err());
292 assert!(Moniker::try_from("/./foo").is_err());
293 assert!(Moniker::try_from("../foo").is_err());
294 assert!(Moniker::try_from(".foo").is_err());
295 }
296}