1use core::slice;
2
3use xitca_unsafe_collection::small_str::SmallBoxedStr;
4
5#[derive(Debug, PartialEq, Eq, Clone, Hash)]
7struct Param {
8 key: SmallBoxedStr,
9 value: SmallBoxedStr,
10}
11
12impl Param {
13 fn key_str(&self) -> &str {
14 self.key.as_ref()
15 }
16
17 fn value_str(&self) -> &str {
18 self.value.as_ref()
19 }
20}
21
22#[derive(Clone, Debug)]
42pub struct Params {
43 inner: Vec<Param>,
44}
45
46impl Default for Params {
47 fn default() -> Self {
48 Self::new()
49 }
50}
51
52impl Params {
53 #[inline]
55 pub fn len(&self) -> usize {
56 self.inner.len()
57 }
58
59 #[inline]
61 pub fn is_empty(&self) -> bool {
62 self.len() == 0
63 }
64
65 #[inline]
67 pub fn get(&self, key: impl AsRef<str>) -> Option<&str> {
68 self.inner
69 .iter()
70 .find(|param| param.key_str() == key.as_ref())
71 .map(Param::value_str)
72 }
73
74 #[inline]
75 pub fn iter(&self) -> Iter<'_> {
76 Iter {
77 inner: self.inner.iter(),
78 }
79 }
80}
81
82impl Params {
83 pub(super) const fn new() -> Self {
84 Self { inner: Vec::new() }
85 }
86
87 pub(super) fn truncate(&mut self, n: usize) {
88 self.inner.truncate(n)
89 }
90
91 pub(super) fn push(&mut self, key: &str, value: &str) {
92 self.inner.push(Param {
93 key: key.into(),
94 value: value.into(),
95 });
96 }
97
98 pub(crate) fn for_each_key_mut(&mut self, f: impl Fn((usize, &mut SmallBoxedStr))) {
100 self.inner
101 .iter_mut()
102 .map(|param| &mut param.key)
103 .enumerate()
104 .for_each(f);
105 }
106}
107
108impl IntoIterator for Params {
109 type Item = (SmallBoxedStr, SmallBoxedStr);
110 type IntoIter = IntoIter;
111
112 #[inline]
113 fn into_iter(self) -> Self::IntoIter {
114 IntoIter {
115 inner: self.inner.into_iter(),
116 }
117 }
118}
119
120pub struct Iter<'a> {
121 inner: slice::Iter<'a, Param>,
122}
123
124impl<'a> Iterator for Iter<'a> {
125 type Item = (&'a str, &'a str);
126
127 #[inline]
128 fn next(&mut self) -> Option<Self::Item> {
129 self.inner.next().map(|p| (p.key.as_ref(), p.value.as_ref()))
130 }
131
132 #[inline]
133 fn size_hint(&self) -> (usize, Option<usize>) {
134 self.inner.size_hint()
135 }
136}
137
138pub struct IntoIter {
139 inner: std::vec::IntoIter<Param>,
140}
141
142impl Iterator for IntoIter {
143 type Item = (SmallBoxedStr, SmallBoxedStr);
144
145 #[inline]
146 fn next(&mut self) -> Option<Self::Item> {
147 self.inner.next().map(|p| (p.key, p.value))
148 }
149
150 #[inline]
151 fn size_hint(&self) -> (usize, Option<usize>) {
152 self.inner.size_hint()
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159
160 #[test]
161 fn no_alloc() {
162 assert!(Params::new().is_empty());
163 }
164
165 #[test]
166 fn ignore_array_default() {
167 let params = Params::new();
168 assert!(params.get("").is_none());
169 }
170}