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