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