rocket/form/name/view.rs
1use crate::form::name::*;
2
3/// A sliding-prefix view into a [`Name`].
4///
5/// A [`NameView`] maintains a sliding key view into a [`Name`]. The current key
6/// ([`key()`]) can be [`shift()`ed](NameView::shift()) one key to the right.
7/// The `Name` prefix including the current key can be extracted via
8/// [`as_name()`] and the prefix _not_ including the current key via
9/// [`parent()`].
10///
11/// [`key()`]: NameView::key()
12/// [`as_name()`]: NameView::as_name()
13/// [`parent()`]: NameView::parent()
14///
15/// This is best illustrated via an example:
16///
17/// ```rust
18/// use rocket::form::name::NameView;
19///
20/// // The view begins at the first key. Illustrated: `(a).b[c:d]` where
21/// // parenthesis enclose the current key.
22/// let mut view = NameView::new("a.b[c:d]");
23/// assert_eq!(view.key().unwrap(), "a");
24/// assert_eq!(view.as_name(), "a");
25/// assert_eq!(view.parent(), None);
26///
27/// // Shifted once to the right views the second key: `a.(b)[c:d]`.
28/// view.shift();
29/// assert_eq!(view.key().unwrap(), "b");
30/// assert_eq!(view.as_name(), "a.b");
31/// assert_eq!(view.parent().unwrap(), "a");
32///
33/// // Shifting again now has predictable results: `a.b[(c:d)]`.
34/// view.shift();
35/// assert_eq!(view.key().unwrap(), "c:d");
36/// assert_eq!(view.as_name(), "a.b[c:d]");
37/// assert_eq!(view.parent().unwrap(), "a.b");
38///
39/// // Shifting past the end means we have no further keys.
40/// view.shift();
41/// assert_eq!(view.key(), None);
42/// assert_eq!(view.key_lossy(), "");
43/// assert_eq!(view.as_name(), "a.b[c:d]");
44/// assert_eq!(view.parent().unwrap(), "a.b[c:d]");
45///
46/// view.shift();
47/// assert_eq!(view.key(), None);
48/// assert_eq!(view.as_name(), "a.b[c:d]");
49/// assert_eq!(view.parent().unwrap(), "a.b[c:d]");
50/// ```
51///
52/// # Equality
53///
54/// `PartialEq`, `Eq`, and `Hash` all operate on the name prefix including the
55/// current key. Only key values are compared; delimiters are insignificant.
56/// Again, illustrated via examples:
57///
58/// ```rust
59/// use rocket::form::name::NameView;
60///
61/// let mut view = NameView::new("a.b[c:d]");
62/// assert_eq!(view, "a");
63///
64/// // Shifted once to the right views the second key: `a.(b)[c:d]`.
65/// view.shift();
66/// assert_eq!(view.key().unwrap(), "b");
67/// assert_eq!(view.as_name(), "a.b");
68/// assert_eq!(view, "a.b");
69/// assert_eq!(view, "a[b]");
70///
71/// // Shifting again now has predictable results: `a.b[(c:d)]`.
72/// view.shift();
73/// assert_eq!(view, "a.b[c:d]");
74/// assert_eq!(view, "a.b.c:d");
75/// assert_eq!(view, "a[b].c:d");
76/// assert_eq!(view, "a[b]c:d");
77/// ```
78#[derive(Copy, Clone)]
79pub struct NameView<'v> {
80 name: &'v Name,
81 start: usize,
82 end: usize,
83}
84
85impl<'v> NameView<'v> {
86 /// Initializes a new `NameView` at the first key of `name`.
87 ///
88 /// # Example
89 ///
90 /// ```rust
91 /// use rocket::form::name::NameView;
92 ///
93 /// let mut view = NameView::new("a.b[c:d]");
94 /// assert_eq!(view.key().unwrap(), "a");
95 /// assert_eq!(view.as_name(), "a");
96 /// assert_eq!(view.parent(), None);
97 /// ```
98 pub fn new<N: Into<&'v Name>>(name: N) -> Self {
99 let mut view = NameView { name: name.into(), start: 0, end: 0 };
100 view.shift();
101 view
102 }
103
104 /// Shifts the current key once to the right.
105 ///
106 /// # Examples
107 ///
108 /// ```rust
109 /// use rocket::form::name::NameView;
110 ///
111 /// let mut view = NameView::new("a.b[c:d][d.e]");
112 /// assert_eq!(view.key().unwrap(), "a");
113 ///
114 /// view.shift();
115 /// assert_eq!(view.key().unwrap(), "b");
116 ///
117 /// view.shift();
118 /// assert_eq!(view.key().unwrap(), "c:d");
119 ///
120 /// view.shift();
121 /// assert_eq!(view.key().unwrap(), "d.e");
122 /// ```
123 ///
124 /// Malformed strings can have interesting results:
125 ///
126 /// ```rust
127 /// use rocket::form::name::NameView;
128 ///
129 /// let mut view = NameView::new("a[c.d");
130 /// assert_eq!(view.key_lossy(), "a");
131 ///
132 /// view.shift();
133 /// assert_eq!(view.key_lossy(), "c.d");
134 ///
135 /// let mut view = NameView::new("a[c[.d]");
136 /// assert_eq!(view.key_lossy(), "a");
137 ///
138 /// view.shift();
139 /// assert_eq!(view.key_lossy(), "c[.d");
140 ///
141 /// view.shift();
142 /// assert_eq!(view.key(), None);
143 ///
144 /// let mut view = NameView::new("foo[c[.d]]");
145 /// assert_eq!(view.key_lossy(), "foo");
146 ///
147 /// view.shift();
148 /// assert_eq!(view.key_lossy(), "c[.d");
149 ///
150 /// view.shift();
151 /// assert_eq!(view.key_lossy(), "]");
152 ///
153 /// view.shift();
154 /// assert_eq!(view.key(), None);
155 /// ```
156 pub fn shift(&mut self) {
157 const START_DELIMS: &[char] = &['.', '['];
158
159 let string = &self.name[self.end..];
160 let bytes = string.as_bytes();
161 let shift = match bytes.get(0) {
162 None | Some(b'=') => 0,
163 Some(b'[') => match memchr::memchr(b']', bytes) {
164 Some(j) => j + 1,
165 None => bytes.len(),
166 },
167 Some(b'.') => match string[1..].find(START_DELIMS) {
168 Some(j) => j + 1,
169 None => bytes.len(),
170 },
171 _ => match string.find(START_DELIMS) {
172 Some(j) => j,
173 None => bytes.len()
174 }
175 };
176
177 debug_assert!(self.end + shift <= self.name.len());
178 *self = NameView {
179 name: self.name,
180 start: self.end,
181 end: self.end + shift,
182 };
183 }
184
185 /// Returns the key currently viewed by `self` if it is non-empty.
186 ///
187 /// ```text
188 /// food.bart[bar:foo].blam[0_0][][1000]=some-value
189 /// name |----------------------------------|
190 /// non-empty key |--| |--| |-----| |--| |-| |--|
191 /// empty key |-|
192 /// ```
193 ///
194 /// # Example
195 ///
196 /// ```rust
197 /// use rocket::form::name::NameView;
198 ///
199 /// let mut view = NameView::new("a[b]");
200 /// assert_eq!(view.key().unwrap(), "a");
201 ///
202 /// view.shift();
203 /// assert_eq!(view.key().unwrap(), "b");
204 ///
205 /// view.shift();
206 /// assert_eq!(view.key(), None);
207 /// # view.shift(); assert_eq!(view.key(), None);
208 /// # view.shift(); assert_eq!(view.key(), None);
209 /// ```
210 pub fn key(&self) -> Option<&'v Key> {
211 let lossy_key = self.key_lossy();
212 if lossy_key.is_empty() {
213 return None;
214 }
215
216 Some(lossy_key)
217 }
218
219 /// Returns the key currently viewed by `self`, even if it is non-empty.
220 ///
221 /// ```text
222 /// food.bart[bar:foo].blam[0_0][][1000]=some-value
223 /// name |----------------------------------|
224 /// non-empty key |--| |--| |-----| |--| |-| |--|
225 /// empty key |-|
226 /// ```
227 ///
228 /// # Example
229 ///
230 /// ```rust
231 /// use rocket::form::name::NameView;
232 ///
233 /// let mut view = NameView::new("a[b]");
234 /// assert_eq!(view.key_lossy(), "a");
235 ///
236 /// view.shift();
237 /// assert_eq!(view.key_lossy(), "b");
238 ///
239 /// view.shift();
240 /// assert_eq!(view.key_lossy(), "");
241 /// # view.shift(); assert_eq!(view.key_lossy(), "");
242 /// # view.shift(); assert_eq!(view.key_lossy(), "");
243 /// ```
244 pub fn key_lossy(&self) -> &'v Key {
245 let view = &self.name[self.start..self.end];
246 let key = match view.as_bytes().get(0) {
247 Some(b'.') => &view[1..],
248 Some(b'[') if view.ends_with(']') => &view[1..view.len() - 1],
249 Some(b'[') if self.is_at_last() => &view[1..],
250 _ => view
251 };
252
253 key.as_str().into()
254 }
255
256 /// Returns the `Name` _up to and including_ the current key.
257 ///
258 /// # Example
259 ///
260 /// ```rust
261 /// use rocket::form::name::NameView;
262 ///
263 /// let mut view = NameView::new("a[b]");
264 /// assert_eq!(view.as_name(), "a");
265 ///
266 /// view.shift();
267 /// assert_eq!(view.as_name(), "a[b]");
268 /// # view.shift(); assert_eq!(view.as_name(), "a[b]");
269 /// # view.shift(); assert_eq!(view.as_name(), "a[b]");
270 /// ```
271 pub fn as_name(&self) -> &'v Name {
272 &self.name[..self.end]
273 }
274
275 /// Returns the `Name` _prior to_ the current key.
276 ///
277 /// # Example
278 ///
279 /// ```rust
280 /// use rocket::form::name::NameView;
281 ///
282 /// let mut view = NameView::new("a[b]");
283 /// assert_eq!(view.parent(), None);
284 ///
285 /// view.shift();
286 /// assert_eq!(view.parent().unwrap(), "a");
287 ///
288 /// view.shift();
289 /// assert_eq!(view.parent().unwrap(), "a[b]");
290 /// # view.shift(); assert_eq!(view.parent().unwrap(), "a[b]");
291 /// # view.shift(); assert_eq!(view.parent().unwrap(), "a[b]");
292 /// ```
293 pub fn parent(&self) -> Option<&'v Name> {
294 if self.start > 0 {
295 Some(&self.name[..self.start])
296 } else {
297 None
298 }
299 }
300
301 /// Returns the underlying `Name`.
302 ///
303 /// # Example
304 ///
305 /// ```rust
306 /// use rocket::form::name::NameView;
307 ///
308 /// let mut view = NameView::new("a[b]");
309 /// assert_eq!(view.source(), "a[b]");
310 ///
311 /// view.shift();
312 /// assert_eq!(view.source(), "a[b]");
313 ///
314 /// view.shift();
315 /// assert_eq!(view.source(), "a[b]");
316 ///
317 /// # view.shift(); assert_eq!(view.source(), "a[b]");
318 /// # view.shift(); assert_eq!(view.source(), "a[b]");
319 /// ```
320 pub fn source(&self) -> &'v Name {
321 self.name
322 }
323
324 // This is the last key. The next `shift()` will exhaust `self`.
325 fn is_at_last(&self) -> bool {
326 self.end == self.name.len()
327 }
328
329 // There are no more keys. A `shift` will do nothing.
330 pub(crate) fn exhausted(&self) -> bool {
331 self.start == self.name.len()
332 }
333}
334
335impl std::fmt::Debug for NameView<'_> {
336 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
337 self.as_name().fmt(f)
338 }
339}
340
341impl std::fmt::Display for NameView<'_> {
342 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
343 self.as_name().fmt(f)
344 }
345}
346
347impl<'a, 'b> PartialEq<NameView<'b>> for NameView<'a> {
348 fn eq(&self, other: &NameView<'b>) -> bool {
349 self.as_name() == other.as_name()
350 }
351}
352
353impl<B: PartialEq<Name>> PartialEq<B> for NameView<'_> {
354 fn eq(&self, other: &B) -> bool {
355 other == self.as_name()
356 }
357}
358
359impl Eq for NameView<'_> { }
360
361impl std::hash::Hash for NameView<'_> {
362 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
363 self.as_name().hash(state)
364 }
365}
366
367impl std::borrow::Borrow<Name> for NameView<'_> {
368 fn borrow(&self) -> &Name {
369 self.as_name()
370 }
371}