protobuf_parse/
protobuf_rel_path.rs
1#![doc(hidden)]
2
3use std::fmt;
4use std::iter;
5use std::mem;
6use std::ops::Deref;
7
8use crate::protobuf_abs_path::ProtobufAbsPath;
9use crate::protobuf_ident::ProtobufIdent;
10use crate::ProtobufIdentRef;
11
12impl From<String> for ProtobufRelPath {
13 fn from(s: String) -> ProtobufRelPath {
14 ProtobufRelPath::new(s)
15 }
16}
17
18impl From<&'_ str> for ProtobufRelPath {
19 fn from(s: &str) -> ProtobufRelPath {
20 ProtobufRelPath::from(s.to_owned())
21 }
22}
23
24impl ProtobufRelPathRef {
25 pub fn as_str(&self) -> &str {
26 &self
27 }
28
29 pub fn empty() -> &'static ProtobufRelPathRef {
30 Self::new("")
31 }
32
33 pub fn new(path: &str) -> &ProtobufRelPathRef {
34 assert!(!path.starts_with('.'));
35 unsafe { mem::transmute(path) }
37 }
38
39 pub fn is_empty(&self) -> bool {
40 self.0.is_empty()
41 }
42
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
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
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
74 pub fn self_and_parents(&self) -> Vec<&ProtobufRelPathRef> {
75 let mut tmp = self;
76
77 let mut r = Vec::new();
78
79 r.push(self);
80
81 while let Some(parent) = tmp.parent() {
82 r.push(parent);
83 tmp = parent;
84 }
85
86 r
87 }
88
89 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
101 pub fn append_ident(&self, simple: &ProtobufIdentRef) -> ProtobufRelPath {
102 self.append(&ProtobufRelPath::from(simple.to_owned()))
103 }
104
105 pub fn to_absolute(&self) -> ProtobufAbsPath {
106 self.to_owned().into_absolute()
107 }
108
109 pub fn to_owned(&self) -> ProtobufRelPath {
110 ProtobufRelPath {
111 path: self.0.to_owned(),
112 }
113 }
114}
115
116impl ProtobufRelPath {
117 pub fn as_ref(&self) -> &ProtobufRelPathRef {
118 &self
119 }
120
121 pub fn empty() -> ProtobufRelPath {
122 ProtobufRelPath {
123 path: String::new(),
124 }
125 }
126
127 pub fn new<S: Into<String>>(path: S) -> ProtobufRelPath {
128 let path = path.into();
129 ProtobufRelPathRef::new(&path);
131 ProtobufRelPath { path }
132 }
133
134 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
141 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)]
152pub struct ProtobufRelPath {
153 pub(crate) path: String,
154}
155
156#[doc(hidden)]
157#[derive(Debug, Eq, PartialEq, Hash)]
158#[repr(transparent)]
159pub struct ProtobufRelPathRef(str);
160
161impl Deref for ProtobufRelPathRef {
162 type Target = str;
163
164 fn deref(&self) -> &str {
165 &self.0
166 }
167}
168
169impl Deref for ProtobufRelPath {
170 type Target = ProtobufRelPathRef;
171
172 fn deref(&self) -> &ProtobufRelPathRef {
173 ProtobufRelPathRef::new(&self.path)
174 }
175}
176
177impl From<ProtobufIdent> for ProtobufRelPath {
178 fn from(s: ProtobufIdent) -> ProtobufRelPath {
179 ProtobufRelPath { path: s.into() }
180 }
181}
182
183impl fmt::Display for ProtobufRelPathRef {
184 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
185 write!(f, "{}", &self.0)
186 }
187}
188
189impl fmt::Display for ProtobufRelPath {
190 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
191 write!(f, "{}", self.path)
192 }
193}
194
195#[cfg(test)]
196mod test {
197 use super::*;
198
199 #[test]
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]
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]
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}