rocket_community/form/name/
buf.rs

1use std::borrow::Cow;
2
3use crate::form::name::*;
4
5/// A potentially owned [`Name`].
6///
7/// Constructible from a [`NameView`], [`Name`], `&str`, or `String`, a
8/// `NameBuf` acts much like a [`Name`] but can be converted into an owned
9/// version via [`IntoOwned`](crate::http::ext::IntoOwned).
10///
11/// ```rust
12/// # extern crate rocket_community as rocket;
13/// use rocket::form::name::NameBuf;
14/// use rocket::http::ext::IntoOwned;
15///
16/// let alloc = String::from("a.b.c");
17/// let name = NameBuf::from(alloc.as_str());
18/// let owned: NameBuf<'static> = name.into_owned();
19/// ```
20#[derive(Clone)]
21pub struct NameBuf<'v> {
22    left: &'v Name,
23    right: Cow<'v, str>,
24}
25
26impl<'v> NameBuf<'v> {
27    #[inline]
28    fn split(&self) -> (&Name, &Name) {
29        (self.left, Name::new(&self.right))
30    }
31
32    /// Returns an iterator over the keys of `self`, including empty keys.
33    ///
34    /// See [`Name`] for a description of "keys".
35    ///
36    /// # Example
37    ///
38    /// ```rust
39    /// # extern crate rocket_community as rocket;
40    /// use rocket::form::name::NameBuf;
41    ///
42    /// let name = NameBuf::from("apple.b[foo:bar]zoo.[barb].bat");
43    /// let keys: Vec<_> = name.keys().map(|k| k.as_str()).collect();
44    /// assert_eq!(keys, &["apple", "b", "foo:bar", "zoo", "", "barb", "bat"]);
45    /// ```
46    #[inline]
47    pub fn keys(&self) -> impl Iterator<Item = &Key> {
48        let (left, right) = self.split();
49        left.keys().chain(right.keys())
50    }
51
52    /// Returns `true` if `self` is empty.
53    ///
54    /// # Example
55    ///
56    /// ```rust
57    /// # extern crate rocket_community as rocket;
58    /// use rocket::form::name::NameBuf;
59    ///
60    /// let name = NameBuf::from("apple.b[foo:bar]zoo.[barb].bat");
61    /// assert!(!name.is_empty());
62    ///
63    /// let name = NameBuf::from("");
64    /// assert!(name.is_empty());
65    /// ```
66    #[inline]
67    pub fn is_empty(&self) -> bool {
68        let (left, right) = self.split();
69        left.is_empty() && right.is_empty()
70    }
71}
72
73impl crate::http::ext::IntoOwned for NameBuf<'_> {
74    type Owned = NameBuf<'static>;
75
76    fn into_owned(self) -> Self::Owned {
77        let right = match (self.left, self.right) {
78            (l, Cow::Owned(r)) if l.is_empty() => Cow::Owned(r),
79            (l, r) if l.is_empty() => r.to_string().into(),
80            (l, r) if r.is_empty() => l.to_string().into(),
81            (l, r) => format!("{}.{}", l, r).into(),
82        };
83
84        NameBuf {
85            left: "".into(),
86            right,
87        }
88    }
89}
90
91impl serde::Serialize for NameBuf<'_> {
92    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
93    where
94        S: serde::Serializer,
95    {
96        serializer.serialize_str(&self.to_string())
97    }
98}
99
100impl<'v> From<NameView<'v>> for NameBuf<'v> {
101    fn from(nv: NameView<'v>) -> Self {
102        NameBuf {
103            left: nv.as_name(),
104            right: Cow::Borrowed(""),
105        }
106    }
107}
108
109impl<'v> From<&'v Name> for NameBuf<'v> {
110    fn from(name: &'v Name) -> Self {
111        NameBuf {
112            left: name,
113            right: Cow::Borrowed(""),
114        }
115    }
116}
117
118impl<'v> From<&'v str> for NameBuf<'v> {
119    fn from(name: &'v str) -> Self {
120        NameBuf::from((None, Cow::Borrowed(name)))
121    }
122}
123
124impl<'v> From<String> for NameBuf<'v> {
125    fn from(name: String) -> Self {
126        NameBuf::from((None, Cow::Owned(name)))
127    }
128}
129
130#[doc(hidden)]
131impl<'v> From<(Option<&'v Name>, Cow<'v, str>)> for NameBuf<'v> {
132    fn from((prefix, right): (Option<&'v Name>, Cow<'v, str>)) -> Self {
133        match prefix {
134            Some(left) => NameBuf { left, right },
135            None => NameBuf {
136                left: "".into(),
137                right,
138            },
139        }
140    }
141}
142
143#[doc(hidden)]
144impl<'v> From<(Option<&'v Name>, String)> for NameBuf<'v> {
145    fn from((prefix, right): (Option<&'v Name>, String)) -> Self {
146        match prefix {
147            Some(left) => NameBuf {
148                left,
149                right: right.into(),
150            },
151            None => NameBuf {
152                left: "".into(),
153                right: right.into(),
154            },
155        }
156    }
157}
158
159#[doc(hidden)]
160impl<'v> From<(Option<&'v Name>, &'v str)> for NameBuf<'v> {
161    fn from((prefix, suffix): (Option<&'v Name>, &'v str)) -> Self {
162        NameBuf::from((prefix, Cow::Borrowed(suffix)))
163    }
164}
165
166#[doc(hidden)]
167impl<'v> From<(&'v Name, &'v str)> for NameBuf<'v> {
168    fn from((prefix, suffix): (&'v Name, &'v str)) -> Self {
169        NameBuf::from((Some(prefix), Cow::Borrowed(suffix)))
170    }
171}
172
173impl std::fmt::Debug for NameBuf<'_> {
174    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175        write!(f, "\"")?;
176
177        let (left, right) = self.split();
178        if !left.is_empty() {
179            write!(f, "{}", left.escape_debug())?
180        }
181        if !right.is_empty() {
182            if !left.is_empty() {
183                f.write_str(".")?;
184            }
185            write!(f, "{}", right.escape_debug())?;
186        }
187
188        write!(f, "\"")
189    }
190}
191
192impl std::fmt::Display for NameBuf<'_> {
193    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
194        let (left, right) = self.split();
195        if !left.is_empty() {
196            left.fmt(f)?;
197        }
198        if !right.is_empty() {
199            if !left.is_empty() {
200                f.write_str(".")?;
201            }
202            right.fmt(f)?;
203        }
204
205        Ok(())
206    }
207}
208
209impl PartialEq for NameBuf<'_> {
210    fn eq(&self, other: &Self) -> bool {
211        self.keys().eq(other.keys())
212    }
213}
214
215impl<N: AsRef<Name> + ?Sized> PartialEq<N> for NameBuf<'_> {
216    fn eq(&self, other: &N) -> bool {
217        self.keys().eq(other.as_ref().keys())
218    }
219}
220
221impl PartialEq<NameBuf<'_>> for Name {
222    fn eq(&self, other: &NameBuf<'_>) -> bool {
223        self.keys().eq(other.keys())
224    }
225}
226
227impl PartialEq<NameBuf<'_>> for str {
228    fn eq(&self, other: &NameBuf<'_>) -> bool {
229        Name::new(self) == other
230    }
231}
232
233impl PartialEq<NameBuf<'_>> for &str {
234    fn eq(&self, other: &NameBuf<'_>) -> bool {
235        Name::new(self) == other
236    }
237}
238
239impl Eq for NameBuf<'_> {}
240
241impl std::hash::Hash for NameBuf<'_> {
242    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
243        self.keys().for_each(|k| k.hash(state))
244    }
245}
246
247impl indexmap::Equivalent<Name> for NameBuf<'_> {
248    fn equivalent(&self, key: &Name) -> bool {
249        self.keys().eq(key.keys())
250    }
251}
252
253impl indexmap::Equivalent<NameBuf<'_>> for Name {
254    fn equivalent(&self, key: &NameBuf<'_>) -> bool {
255        self.keys().eq(key.keys())
256    }
257}