rocket_community/form/name/
key.rs

1use std::ops::Deref;
2
3use ref_cast::RefCast;
4
5use crate::http::RawStr;
6
7/// A field name key composed of indices.
8///
9/// A form field name key is composed of _indices_, delimited by `:`. The
10/// graphic below illustrates this composition for a single field in
11/// `$name=$value` format:
12///
13/// ```text
14///       food.bart[bar:foo:baz]=some-value
15/// name  |--------------------|
16/// key   |--| |--| |---------|
17/// index |--| |--| |-| |-| |-|
18/// ```
19///
20/// A `Key` is a wrapper around a given key string with methods to easily access
21/// its indices.
22///
23/// # Serialization
24///
25/// A value of this type is serialized exactly as an `&str` consisting of the
26/// entire key.
27#[repr(transparent)]
28#[derive(RefCast, Debug, PartialEq, Eq, Hash)]
29pub struct Key(str);
30
31impl Key {
32    /// Wraps a string as a `Key`. This is cost-free.
33    ///
34    /// # Example
35    ///
36    /// ```rust
37    /// # extern crate rocket_community as rocket;
38    /// use rocket::form::name::Key;
39    ///
40    /// let key = Key::new("a:b:c");
41    /// assert_eq!(key.as_str(), "a:b:c");
42    /// ```
43    pub fn new<S: AsRef<str> + ?Sized>(string: &S) -> &Key {
44        Key::ref_cast(string.as_ref())
45    }
46
47    /// Returns an iterator over the indices of `self`, including empty indices.
48    ///
49    /// See the [top-level docs](Self) for a description of "indices".
50    ///
51    /// # Example
52    ///
53    /// ```rust
54    /// # extern crate rocket_community as rocket;
55    /// use rocket::form::name::Key;
56    ///
57    /// let key = Key::new("foo:bar::baz:a.b.c");
58    /// let indices: Vec<_> = key.indices().collect();
59    /// assert_eq!(indices, &["foo", "bar", "", "baz", "a.b.c"]);
60    /// ```
61    pub fn indices(&self) -> impl Iterator<Item = &str> {
62        self.split(':')
63    }
64
65    /// Borrows the underlying string.
66    ///
67    /// # Example
68    ///
69    /// ```rust
70    /// # extern crate rocket_community as rocket;
71    /// use rocket::form::name::Key;
72    ///
73    /// let key = Key::new("a:b:c");
74    /// assert_eq!(key.as_str(), "a:b:c");
75    /// ```
76    pub fn as_str(&self) -> &str {
77        self
78    }
79}
80
81impl Deref for Key {
82    type Target = str;
83
84    fn deref(&self) -> &Self::Target {
85        &self.0
86    }
87}
88
89impl serde::Serialize for Key {
90    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
91    where
92        S: serde::Serializer,
93    {
94        self.0.serialize(ser)
95    }
96}
97
98impl<'de: 'a, 'a> serde::Deserialize<'de> for &'a Key {
99    fn deserialize<D>(de: D) -> Result<Self, D::Error>
100    where
101        D: serde::Deserializer<'de>,
102    {
103        <&'a str as serde::Deserialize<'de>>::deserialize(de).map(Key::new)
104    }
105}
106
107impl<I: core::slice::SliceIndex<str, Output = str>> core::ops::Index<I> for Key {
108    type Output = Key;
109
110    #[inline]
111    fn index(&self, index: I) -> &Self::Output {
112        self.0[index].into()
113    }
114}
115
116impl PartialEq<str> for Key {
117    fn eq(&self, other: &str) -> bool {
118        self == Key::new(other)
119    }
120}
121
122impl PartialEq<Key> for str {
123    fn eq(&self, other: &Key) -> bool {
124        Key::new(self) == other
125    }
126}
127
128impl<'a, S: AsRef<str> + ?Sized> From<&'a S> for &'a Key {
129    #[inline]
130    fn from(string: &'a S) -> Self {
131        Key::new(string)
132    }
133}
134
135impl AsRef<Key> for str {
136    fn as_ref(&self) -> &Key {
137        Key::new(self)
138    }
139}
140
141impl AsRef<Key> for RawStr {
142    fn as_ref(&self) -> &Key {
143        Key::new(self)
144    }
145}
146
147impl std::fmt::Display for Key {
148    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149        self.0.fmt(f)
150    }
151}