1use std::{fmt, iter, mem, slice};
2
3#[derive(PartialEq, Eq, Ord, PartialOrd, Default, Copy, Clone)]
5struct Param<'k, 'v> {
6 key: &'k [u8],
10 value: &'v [u8],
11}
12
13impl<'k, 'v> Param<'k, 'v> {
14 const EMPTY: Param<'static, 'static> = Param {
15 key: b"",
16 value: b"",
17 };
18
19 fn key_str(&self) -> &'k str {
21 std::str::from_utf8(self.key).unwrap()
22 }
23
24 fn value_str(&self) -> &'v str {
26 std::str::from_utf8(self.value).unwrap()
27 }
28}
29
30#[derive(PartialEq, Eq, Ord, PartialOrd, Clone)]
50pub struct Params<'k, 'v> {
51 kind: ParamsKind<'k, 'v>,
52}
53
54impl Default for Params<'_, '_> {
55 fn default() -> Self {
56 Self::new()
57 }
58}
59
60const SMALL: usize = 3;
63
64#[derive(PartialEq, Eq, Ord, PartialOrd, Clone)]
66enum ParamsKind<'k, 'v> {
67 Small([Param<'k, 'v>; SMALL], usize),
68 Large(Vec<Param<'k, 'v>>),
69}
70
71impl<'k, 'v> Params<'k, 'v> {
72 pub fn new() -> Self {
74 Self {
75 kind: ParamsKind::Small([Param::EMPTY; 3], 0),
76 }
77 }
78
79 pub fn len(&self) -> usize {
81 match self.kind {
82 ParamsKind::Small(_, len) => len,
83 ParamsKind::Large(ref vec) => vec.len(),
84 }
85 }
86
87 pub(crate) fn truncate(&mut self, n: usize) {
89 match &mut self.kind {
90 ParamsKind::Small(_, len) => *len = n,
91 ParamsKind::Large(vec) => vec.truncate(n),
92 }
93 }
94
95 pub fn get(&self, key: impl AsRef<str>) -> Option<&'v str> {
97 let key = key.as_ref().as_bytes();
98
99 match &self.kind {
100 ParamsKind::Small(arr, len) => arr
101 .iter()
102 .take(*len)
103 .find(|param| param.key == key)
104 .map(Param::value_str),
105 ParamsKind::Large(vec) => vec
106 .iter()
107 .find(|param| param.key == key)
108 .map(Param::value_str),
109 }
110 }
111
112 pub fn iter(&self) -> ParamsIter<'_, 'k, 'v> {
114 ParamsIter::new(self)
115 }
116
117 pub fn is_empty(&self) -> bool {
119 match self.kind {
120 ParamsKind::Small(_, len) => len == 0,
121 ParamsKind::Large(ref vec) => vec.is_empty(),
122 }
123 }
124
125 pub(crate) fn push(&mut self, key: &'k [u8], value: &'v [u8]) {
127 #[cold]
128 fn drain_to_vec<T: Default>(len: usize, elem: T, arr: &mut [T; SMALL]) -> Vec<T> {
129 let mut vec = Vec::with_capacity(len + 1);
130 vec.extend(arr.iter_mut().map(mem::take));
131 vec.push(elem);
132 vec
133 }
134
135 let param = Param { key, value };
136 match &mut self.kind {
137 ParamsKind::Small(arr, len) => {
138 if *len == SMALL {
139 self.kind = ParamsKind::Large(drain_to_vec(*len, param, arr));
140 return;
141 }
142
143 arr[*len] = param;
144 *len += 1;
145 }
146 ParamsKind::Large(vec) => vec.push(param),
147 }
148 }
149
150 pub(crate) fn for_each_key_mut(&mut self, f: impl Fn((usize, &mut &'k [u8]))) {
152 match &mut self.kind {
153 ParamsKind::Small(arr, len) => arr
154 .iter_mut()
155 .take(*len)
156 .map(|param| &mut param.key)
157 .enumerate()
158 .for_each(f),
159 ParamsKind::Large(vec) => vec
160 .iter_mut()
161 .map(|param| &mut param.key)
162 .enumerate()
163 .for_each(f),
164 }
165 }
166}
167
168impl fmt::Debug for Params<'_, '_> {
169 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170 f.debug_list().entries(self.iter()).finish()
171 }
172}
173
174pub struct ParamsIter<'ps, 'k, 'v> {
176 kind: ParamsIterKind<'ps, 'k, 'v>,
177}
178
179impl<'ps, 'k, 'v> ParamsIter<'ps, 'k, 'v> {
180 fn new(params: &'ps Params<'k, 'v>) -> Self {
181 let kind = match ¶ms.kind {
182 ParamsKind::Small(arr, len) => ParamsIterKind::Small(arr.iter().take(*len)),
183 ParamsKind::Large(vec) => ParamsIterKind::Large(vec.iter()),
184 };
185 Self { kind }
186 }
187}
188
189enum ParamsIterKind<'ps, 'k, 'v> {
190 Small(iter::Take<slice::Iter<'ps, Param<'k, 'v>>>),
191 Large(slice::Iter<'ps, Param<'k, 'v>>),
192}
193
194impl<'ps, 'k, 'v> Iterator for ParamsIter<'ps, 'k, 'v> {
195 type Item = (&'k str, &'v str);
196
197 fn next(&mut self) -> Option<Self::Item> {
198 match self.kind {
199 ParamsIterKind::Small(ref mut iter) => {
200 iter.next().map(|p| (p.key_str(), p.value_str()))
201 }
202 ParamsIterKind::Large(ref mut iter) => {
203 iter.next().map(|p| (p.key_str(), p.value_str()))
204 }
205 }
206 }
207}
208
209impl ExactSizeIterator for ParamsIter<'_, '_, '_> {
210 fn len(&self) -> usize {
211 match self.kind {
212 ParamsIterKind::Small(ref iter) => iter.len(),
213 ParamsIterKind::Large(ref iter) => iter.len(),
214 }
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 use super::*;
221
222 #[test]
223 fn heap_alloc() {
224 let vec = vec![
225 ("hello", "hello"),
226 ("world", "world"),
227 ("foo", "foo"),
228 ("bar", "bar"),
229 ("baz", "baz"),
230 ];
231
232 let mut params = Params::new();
233 for (key, value) in vec.clone() {
234 params.push(key.as_bytes(), value.as_bytes());
235 assert_eq!(params.get(key), Some(value));
236 }
237
238 match params.kind {
239 ParamsKind::Large(..) => {}
240 _ => panic!(),
241 }
242
243 assert!(params.iter().eq(vec.clone()));
244 }
245
246 #[test]
247 fn stack_alloc() {
248 let vec = vec![("hello", "hello"), ("world", "world"), ("baz", "baz")];
249
250 let mut params = Params::new();
251 for (key, value) in vec.clone() {
252 params.push(key.as_bytes(), value.as_bytes());
253 assert_eq!(params.get(key), Some(value));
254 }
255
256 match params.kind {
257 ParamsKind::Small(..) => {}
258 _ => panic!(),
259 }
260
261 assert!(params.iter().eq(vec.clone()));
262 }
263
264 #[test]
265 fn ignore_array_default() {
266 let params = Params::new();
267 assert!(params.get("").is_none());
268 }
269}