rocket_community/form/name/
name.rs

1use std::ops::Deref;
2
3use ref_cast::RefCast;
4
5use crate::form::name::*;
6use crate::http::RawStr;
7
8/// A field name composed of keys.
9///
10/// A form field name is composed of _keys_, delimited by `.` or `[]`. Keys, in
11/// turn, are composed of _indices_, delimited by `:`. The graphic below
12/// illustrates this composition for a single field in `$name=$value` format:
13///
14/// ```text
15///       food.bart[bar:foo].blam[0_0][1000]=some-value
16/// name  |--------------------------------|
17/// key   |--| |--| |-----|  |--| |-|  |--|
18/// index |--| |--| |-| |-|  |--| |-|  |--|
19/// ```
20///
21/// A `Name` is a wrapper around the field name string with methods to easily
22/// access its sub-components.
23///
24/// # Serialization
25///
26/// A value of this type is serialized exactly as an `&str` consisting of the
27/// entire field name.
28#[repr(transparent)]
29#[derive(RefCast)]
30pub struct Name(str);
31
32impl Name {
33    /// Wraps a string as a `Name`. This is cost-free.
34    ///
35    /// # Example
36    ///
37    /// ```rust
38    /// # extern crate rocket_community as rocket;
39    /// use rocket::form::name::Name;
40    ///
41    /// let name = Name::new("a.b.c");
42    /// assert_eq!(name.as_str(), "a.b.c");
43    /// ```
44    pub fn new<S: AsRef<str> + ?Sized>(string: &S) -> &Name {
45        Name::ref_cast(string.as_ref())
46    }
47
48    /// Returns an iterator over the keys of `self`, including empty keys.
49    ///
50    /// See the [top-level docs](Self) for a description of "keys".
51    ///
52    /// # Example
53    ///
54    /// ```rust
55    /// # extern crate rocket_community as rocket;
56    /// use rocket::form::name::Name;
57    ///
58    /// let name = Name::new("apple.b[foo:bar]zoo.[barb].bat");
59    /// let keys: Vec<_> = name.keys().map(|k| k.as_str()).collect();
60    /// assert_eq!(keys, &["apple", "b", "foo:bar", "zoo", "", "barb", "bat"]);
61    /// ```
62    pub fn keys(&self) -> impl Iterator<Item = &Key> {
63        struct Keys<'v>(NameView<'v>);
64
65        impl<'v> Iterator for Keys<'v> {
66            type Item = &'v Key;
67
68            fn next(&mut self) -> Option<Self::Item> {
69                if self.0.exhausted() {
70                    return None;
71                }
72
73                let key = self.0.key_lossy();
74                self.0.shift();
75                Some(key)
76            }
77        }
78
79        Keys(NameView::new(self))
80    }
81
82    /// Returns an iterator over overlapping name prefixes of `self`, each
83    /// succeeding prefix containing one more key than the previous.
84    ///
85    /// # Example
86    ///
87    /// ```rust
88    /// # extern crate rocket_community as rocket;
89    /// use rocket::form::name::Name;
90    ///
91    /// let name = Name::new("apple.b[foo:bar]");
92    /// let prefixes: Vec<_> = name.prefixes().map(|p| p.as_str()).collect();
93    /// assert_eq!(prefixes, &["apple", "apple.b", "apple.b[foo:bar]"]);
94    ///
95    /// let name = Name::new("a.b.[foo]");
96    /// let prefixes: Vec<_> = name.prefixes().map(|p| p.as_str()).collect();
97    /// assert_eq!(prefixes, &["a", "a.b", "a.b.", "a.b.[foo]"]);
98    /// ```
99    pub fn prefixes(&self) -> impl Iterator<Item = &Name> {
100        struct Prefixes<'v>(NameView<'v>);
101
102        impl<'v> Iterator for Prefixes<'v> {
103            type Item = &'v Name;
104
105            fn next(&mut self) -> Option<Self::Item> {
106                if self.0.exhausted() {
107                    return None;
108                }
109
110                let name = self.0.as_name();
111                self.0.shift();
112                Some(name)
113            }
114        }
115
116        Prefixes(NameView::new(self))
117    }
118
119    /// Borrows the underlying string.
120    ///
121    /// # Example
122    ///
123    /// ```rust
124    /// # extern crate rocket_community as rocket;
125    /// use rocket::form::name::Name;
126    ///
127    /// let name = Name::new("a.b.c");
128    /// assert_eq!(name.as_str(), "a.b.c");
129    /// ```
130    pub fn as_str(&self) -> &str {
131        &self.0
132    }
133}
134
135impl serde::Serialize for Name {
136    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
137    where
138        S: serde::Serializer,
139    {
140        self.0.serialize(ser)
141    }
142}
143
144impl<'de: 'a, 'a> serde::Deserialize<'de> for &'a Name {
145    fn deserialize<D>(de: D) -> Result<Self, D::Error>
146    where
147        D: serde::Deserializer<'de>,
148    {
149        <&'a str as serde::Deserialize<'de>>::deserialize(de).map(Name::new)
150    }
151}
152
153impl<'a, S: AsRef<str> + ?Sized> From<&'a S> for &'a Name {
154    #[inline]
155    fn from(string: &'a S) -> Self {
156        Name::new(string)
157    }
158}
159
160impl Deref for Name {
161    type Target = str;
162
163    fn deref(&self) -> &Self::Target {
164        &self.0
165    }
166}
167
168impl<I: core::slice::SliceIndex<str, Output = str>> core::ops::Index<I> for Name {
169    type Output = Name;
170
171    #[inline]
172    fn index(&self, index: I) -> &Self::Output {
173        self.0[index].into()
174    }
175}
176
177impl PartialEq for Name {
178    fn eq(&self, other: &Self) -> bool {
179        self.keys().eq(other.keys())
180    }
181}
182
183impl PartialEq<str> for Name {
184    fn eq(&self, other: &str) -> bool {
185        self == Name::new(other)
186    }
187}
188
189impl PartialEq<Name> for str {
190    fn eq(&self, other: &Name) -> bool {
191        Name::new(self) == other
192    }
193}
194
195impl PartialEq<&str> for Name {
196    fn eq(&self, other: &&str) -> bool {
197        self == Name::new(other)
198    }
199}
200
201impl PartialEq<Name> for &str {
202    fn eq(&self, other: &Name) -> bool {
203        Name::new(self) == other
204    }
205}
206
207impl AsRef<Name> for str {
208    fn as_ref(&self) -> &Name {
209        Name::new(self)
210    }
211}
212
213impl AsRef<Name> for RawStr {
214    fn as_ref(&self) -> &Name {
215        Name::new(self)
216    }
217}
218
219impl AsRef<Name> for Name {
220    fn as_ref(&self) -> &Name {
221        self
222    }
223}
224
225impl Eq for Name {}
226
227impl std::hash::Hash for Name {
228    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
229        self.keys().for_each(|k| k.hash(state))
230    }
231}
232
233impl std::fmt::Display for Name {
234    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
235        self.0.fmt(f)
236    }
237}
238
239impl std::fmt::Debug for Name {
240    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
241        self.0.fmt(f)
242    }
243}