1use core::slice;
2
3use crate::{SmallStr, Vec};
4
5#[derive(Debug, PartialEq, Eq, Clone, Hash)]
7pub struct Param {
8 key: SmallStr,
9 value: SmallStr,
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_val(&mut self, value: &str) {
92 self.inner.push(Param {
93 key: const { SmallStr::new() },
94 value: value.into(),
95 });
96 }
97
98 pub(super) fn push(&mut self, key: &str, value: &str) {
99 self.inner.push(Param {
100 key: key.into(),
101 value: value.into(),
102 });
103 }
104
105 pub(crate) fn apply_keys(&mut self, keys: &[SmallStr]) {
108 self.inner
109 .iter_mut()
110 .zip(keys.iter())
111 .for_each(|(param, key)| param.key = key.clone());
112 }
113}
114
115impl IntoIterator for Params {
116 type Item = (SmallStr, SmallStr);
117 type IntoIter = IntoIter<<Vec<Param> as IntoIterator>::IntoIter>;
118
119 #[inline]
120 fn into_iter(self) -> Self::IntoIter {
121 IntoIter {
122 inner: self.inner.into_iter(),
123 }
124 }
125}
126
127pub struct Iter<'a> {
128 inner: slice::Iter<'a, Param>,
129}
130
131impl<'a> Iterator for Iter<'a> {
132 type Item = (&'a str, &'a str);
133
134 #[inline]
135 fn next(&mut self) -> Option<Self::Item> {
136 self.inner.next().map(|p| (p.key.as_ref(), p.value.as_ref()))
137 }
138
139 #[inline]
140 fn size_hint(&self) -> (usize, Option<usize>) {
141 self.inner.size_hint()
142 }
143}
144
145pub struct IntoIter<I> {
146 inner: I,
147}
148
149impl<I> Iterator for IntoIter<I>
150where
151 I: Iterator<Item = Param>,
152{
153 type Item = (SmallStr, SmallStr);
154
155 #[inline]
156 fn next(&mut self) -> Option<Self::Item> {
157 self.inner.next().map(|p| (p.key, p.value))
158 }
159
160 #[inline]
161 fn size_hint(&self) -> (usize, Option<usize>) {
162 self.inner.size_hint()
163 }
164}
165
166#[cfg(test)]
167mod tests {
168 use super::*;
169
170 #[test]
171 fn no_alloc() {
172 assert!(Params::new().is_empty());
173 }
174
175 #[test]
176 fn ignore_array_default() {
177 let params = Params::new();
178 assert!(params.get("").is_none());
179 }
180}