1 #![doc(hidden)]
2 
3 use std::fmt;
4 use std::iter;
5 use std::mem;
6 use std::ops::Deref;
7 
8 use crate::protobuf_abs_path::ProtobufAbsPath;
9 use crate::protobuf_ident::ProtobufIdent;
10 use crate::ProtobufIdentRef;
11 
12 impl From<String> for ProtobufRelPath {
from(s: String) -> ProtobufRelPath13     fn from(s: String) -> ProtobufRelPath {
14         ProtobufRelPath::new(s)
15     }
16 }
17 
18 impl From<&'_ str> for ProtobufRelPath {
from(s: &str) -> ProtobufRelPath19     fn from(s: &str) -> ProtobufRelPath {
20         ProtobufRelPath::from(s.to_owned())
21     }
22 }
23 
24 impl ProtobufRelPathRef {
as_str(&self) -> &str25     pub fn as_str(&self) -> &str {
26         &self
27     }
28 
empty() -> &'static ProtobufRelPathRef29     pub fn empty() -> &'static ProtobufRelPathRef {
30         Self::new("")
31     }
32 
new(path: &str) -> &ProtobufRelPathRef33     pub fn new(path: &str) -> &ProtobufRelPathRef {
34         assert!(!path.starts_with('.'));
35         // SAFETY: repr(transparent)
36         unsafe { mem::transmute(path) }
37     }
38 
is_empty(&self) -> bool39     pub fn is_empty(&self) -> bool {
40         self.0.is_empty()
41     }
42 
split_first_rem(&self) -> Option<(&ProtobufIdentRef, &ProtobufRelPathRef)>43     pub fn split_first_rem(&self) -> Option<(&ProtobufIdentRef, &ProtobufRelPathRef)> {
44         if self.is_empty() {
45             None
46         } else {
47             match self.0.find('.') {
48                 Some(i) => Some((
49                     ProtobufIdentRef::new(&self.0[..i]),
50                     ProtobufRelPathRef::new(&self.0[i + 1..]),
51                 )),
52                 None => Some((ProtobufIdentRef::new(&self.0), ProtobufRelPathRef::empty())),
53             }
54         }
55     }
56 
components(&self) -> impl Iterator<Item = &ProtobufIdentRef>57     pub fn components(&self) -> impl Iterator<Item = &ProtobufIdentRef> {
58         iter::once(&self.0)
59             .filter(|s| !s.is_empty())
60             .flat_map(|p| p.split('.').map(|s| ProtobufIdentRef::new(s)))
61     }
62 
parent(&self) -> Option<&ProtobufRelPathRef>63     fn parent(&self) -> Option<&ProtobufRelPathRef> {
64         if self.0.is_empty() {
65             None
66         } else {
67             match self.0.rfind('.') {
68                 Some(i) => Some(ProtobufRelPathRef::new(&self.0[..i])),
69                 None => Some(ProtobufRelPathRef::empty()),
70             }
71         }
72     }
73 
self_and_parents(&self) -> Vec<&ProtobufRelPathRef>74     pub fn self_and_parents(&self) -> Vec<&ProtobufRelPathRef> {
75         let mut tmp = self.clone();
76 
77         let mut r = Vec::new();
78 
79         r.push(self.clone());
80 
81         while let Some(parent) = tmp.parent() {
82             r.push(parent);
83             tmp = parent;
84         }
85 
86         r
87     }
88 
append(&self, simple: &ProtobufRelPathRef) -> ProtobufRelPath89     pub fn append(&self, simple: &ProtobufRelPathRef) -> ProtobufRelPath {
90         if self.is_empty() {
91             simple.to_owned()
92         } else if simple.is_empty() {
93             self.to_owned()
94         } else {
95             ProtobufRelPath {
96                 path: format!("{}.{}", &self.0, &simple.0),
97             }
98         }
99     }
100 
append_ident(&self, simple: &ProtobufIdentRef) -> ProtobufRelPath101     pub fn append_ident(&self, simple: &ProtobufIdentRef) -> ProtobufRelPath {
102         self.append(&ProtobufRelPath::from(simple.to_owned()))
103     }
104 
to_absolute(&self) -> ProtobufAbsPath105     pub fn to_absolute(&self) -> ProtobufAbsPath {
106         self.to_owned().into_absolute()
107     }
108 
to_owned(&self) -> ProtobufRelPath109     pub fn to_owned(&self) -> ProtobufRelPath {
110         ProtobufRelPath {
111             path: self.0.to_owned(),
112         }
113     }
114 }
115 
116 impl ProtobufRelPath {
as_ref(&self) -> &ProtobufRelPathRef117     pub fn as_ref(&self) -> &ProtobufRelPathRef {
118         &self
119     }
120 
empty() -> ProtobufRelPath121     pub fn empty() -> ProtobufRelPath {
122         ProtobufRelPath {
123             path: String::new(),
124         }
125     }
126 
new<S: Into<String>>(path: S) -> ProtobufRelPath127     pub fn new<S: Into<String>>(path: S) -> ProtobufRelPath {
128         let path = path.into();
129         // Validate
130         ProtobufRelPathRef::new(&path);
131         ProtobufRelPath { path }
132     }
133 
from_components<'a, I: IntoIterator<Item = &'a ProtobufIdentRef>>( i: I, ) -> ProtobufRelPath134     pub fn from_components<'a, I: IntoIterator<Item = &'a ProtobufIdentRef>>(
135         i: I,
136     ) -> ProtobufRelPath {
137         let v: Vec<&str> = i.into_iter().map(|c| c.as_str()).collect();
138         ProtobufRelPath::from(v.join("."))
139     }
140 
into_absolute(self) -> ProtobufAbsPath141     pub fn into_absolute(self) -> ProtobufAbsPath {
142         if self.is_empty() {
143             ProtobufAbsPath::root()
144         } else {
145             ProtobufAbsPath::from(format!(".{}", self))
146         }
147     }
148 }
149 
150 #[doc(hidden)]
151 #[derive(Debug, Eq, PartialEq, Clone, Hash)]
152 pub struct ProtobufRelPath {
153     pub(crate) path: String,
154 }
155 
156 #[doc(hidden)]
157 #[derive(Debug, Eq, PartialEq, Hash)]
158 #[repr(transparent)]
159 pub struct ProtobufRelPathRef(str);
160 
161 impl Deref for ProtobufRelPathRef {
162     type Target = str;
163 
deref(&self) -> &str164     fn deref(&self) -> &str {
165         &self.0
166     }
167 }
168 
169 impl Deref for ProtobufRelPath {
170     type Target = ProtobufRelPathRef;
171 
deref(&self) -> &ProtobufRelPathRef172     fn deref(&self) -> &ProtobufRelPathRef {
173         ProtobufRelPathRef::new(&self.path)
174     }
175 }
176 
177 impl From<ProtobufIdent> for ProtobufRelPath {
from(s: ProtobufIdent) -> ProtobufRelPath178     fn from(s: ProtobufIdent) -> ProtobufRelPath {
179         ProtobufRelPath { path: s.into() }
180     }
181 }
182 
183 impl fmt::Display for ProtobufRelPathRef {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result184     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
185         write!(f, "{}", &self.0)
186     }
187 }
188 
189 impl fmt::Display for ProtobufRelPath {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result190     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
191         write!(f, "{}", self.path)
192     }
193 }
194 
195 #[cfg(test)]
196 mod test {
197     use super::*;
198 
199     #[test]
parent()200     fn parent() {
201         assert_eq!(None, ProtobufRelPathRef::empty().parent());
202         assert_eq!(
203             Some(ProtobufRelPathRef::empty()),
204             ProtobufRelPath::new("aaa".to_owned()).parent()
205         );
206         assert_eq!(
207             Some(ProtobufRelPathRef::new("abc")),
208             ProtobufRelPath::new("abc.def".to_owned()).parent()
209         );
210         assert_eq!(
211             Some(ProtobufRelPathRef::new("abc.def")),
212             ProtobufRelPath::new("abc.def.gh".to_owned()).parent()
213         );
214     }
215 
216     #[test]
self_and_parents()217     fn self_and_parents() {
218         assert_eq!(
219             vec![
220                 ProtobufRelPathRef::new("ab.cde.fghi"),
221                 ProtobufRelPathRef::new("ab.cde"),
222                 ProtobufRelPathRef::new("ab"),
223                 ProtobufRelPathRef::empty(),
224             ],
225             ProtobufRelPath::new("ab.cde.fghi".to_owned()).self_and_parents()
226         );
227     }
228 
229     #[test]
components()230     fn components() {
231         assert_eq!(
232             Vec::<&ProtobufIdentRef>::new(),
233             ProtobufRelPath::empty().components().collect::<Vec<_>>()
234         );
235         assert_eq!(
236             vec![ProtobufIdentRef::new("ab")],
237             ProtobufRelPath::new("ab").components().collect::<Vec<_>>()
238         );
239         assert_eq!(
240             vec![ProtobufIdentRef::new("ab"), ProtobufIdentRef::new("cd")],
241             ProtobufRelPath::new("ab.cd")
242                 .components()
243                 .collect::<Vec<_>>()
244         );
245     }
246 }
247