oxide_auth/endpoint/
query.rs1use std::borrow::{Borrow, Cow};
2use std::collections::HashMap;
3use std::fmt;
4use std::iter::FromIterator;
5use std::hash::{BuildHasher, Hash};
6use std::rc::Rc;
7use std::sync::Arc;
8
9use serde::de;
10use serde::Deserializer;
11
12pub unsafe trait QueryParameter {
25 fn unique_value(&self, key: &str) -> Option<Cow<str>>;
32
33 fn normalize(&self) -> NormalizedParameter;
35}
36
37#[derive(Clone, Debug, Default)]
51pub struct NormalizedParameter {
52 inner: HashMap<Cow<'static, str>, Option<Cow<'static, str>>>,
54}
55
56unsafe impl QueryParameter for NormalizedParameter {
57 fn unique_value(&self, key: &str) -> Option<Cow<str>> {
58 self.inner
59 .get(key)
60 .and_then(|val| val.as_ref().map(Cow::as_ref).map(Cow::Borrowed))
61 }
62
63 fn normalize(&self) -> NormalizedParameter {
64 self.clone()
65 }
66}
67
68impl NormalizedParameter {
69 pub fn new() -> Self {
71 NormalizedParameter::default()
72 }
73
74 pub fn insert_or_poison(&mut self, key: Cow<'static, str>, val: Cow<'static, str>) {
79 let unique_val = Some(val);
80 self.inner
81 .entry(key)
82 .and_modify(|val| *val = None)
83 .or_insert(unique_val);
84 }
85}
86
87impl Borrow<dyn QueryParameter> for NormalizedParameter {
88 fn borrow(&self) -> &(dyn QueryParameter + 'static) {
89 self
90 }
91}
92
93impl Borrow<dyn QueryParameter + Send> for NormalizedParameter {
94 fn borrow(&self) -> &(dyn QueryParameter + Send + 'static) {
95 self
96 }
97}
98
99impl<'de> de::Deserialize<'de> for NormalizedParameter {
100 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
101 where
102 D: Deserializer<'de>,
103 {
104 struct Visitor(NormalizedParameter);
105
106 impl<'a> de::Visitor<'a> for Visitor {
107 type Value = NormalizedParameter;
108
109 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
110 write!(f, "a sequence of key-value-pairs")
111 }
112
113 fn visit_seq<A>(mut self, mut access: A) -> Result<Self::Value, A::Error>
114 where
115 A: de::SeqAccess<'a>,
116 {
117 while let Some((key, value)) = access.next_element::<(String, String)>()? {
118 self.0.insert_or_poison(key.into(), value.into())
119 }
120
121 Ok(self.0)
122 }
123 }
124
125 let visitor = Visitor(NormalizedParameter::default());
126 deserializer.deserialize_seq(visitor)
127 }
128}
129
130impl<K, V> FromIterator<(K, V)> for NormalizedParameter
131where
132 K: Into<Cow<'static, str>>,
133 V: Into<Cow<'static, str>>,
134{
135 fn from_iter<T>(iter: T) -> Self
136 where
137 T: IntoIterator<Item = (K, V)>,
138 {
139 let mut target = NormalizedParameter::default();
140 iter.into_iter()
141 .for_each(|(k, v)| target.insert_or_poison(k.into(), v.into()));
142 target
143 }
144}
145
146impl ToOwned for dyn QueryParameter {
147 type Owned = NormalizedParameter;
148
149 fn to_owned(&self) -> Self::Owned {
150 self.normalize()
151 }
152}
153
154impl ToOwned for dyn QueryParameter + Send {
155 type Owned = NormalizedParameter;
156
157 fn to_owned(&self) -> Self::Owned {
158 self.normalize()
159 }
160}
161
162pub unsafe trait UniqueValue {
170 fn get_unique(&self) -> Option<&str>;
172}
173
174unsafe impl<K, V, S: BuildHasher> QueryParameter for HashMap<K, V, S>
175where
176 K: Borrow<str> + Eq + Hash,
177 V: UniqueValue + Eq + Hash,
178{
179 fn unique_value(&self, key: &str) -> Option<Cow<str>> {
180 self.get(key).and_then(V::get_unique).map(Cow::Borrowed)
181 }
182
183 fn normalize(&self) -> NormalizedParameter {
184 let inner = self
185 .iter()
186 .filter_map(|(key, val)| {
187 val.get_unique().map(|value| {
188 (
189 Cow::Owned(key.borrow().to_string()),
190 Some(Cow::Owned(value.to_string())),
191 )
192 })
193 })
194 .collect();
195
196 NormalizedParameter { inner }
197 }
198}
199
200unsafe impl<K, V> QueryParameter for Vec<(K, V)>
201where
202 K: Borrow<str> + Eq + Hash,
203 V: Borrow<str> + Eq + Hash,
204{
205 fn unique_value(&self, key: &str) -> Option<Cow<str>> {
206 let mut value = None;
207
208 for entry in self.iter() {
209 if entry.0.borrow() == key {
210 if value.is_some() {
211 return None;
212 }
213 value = Some(Cow::Borrowed(entry.1.borrow()));
214 }
215 }
216
217 value
218 }
219
220 fn normalize(&self) -> NormalizedParameter {
221 let mut params = NormalizedParameter::default();
222 self.iter()
223 .map(|&(ref key, ref val)| {
224 (
225 Cow::Owned(key.borrow().to_string()),
226 Cow::Owned(val.borrow().to_string()),
227 )
228 })
229 .for_each(|(key, val)| params.insert_or_poison(key, val));
230 params
231 }
232}
233
234unsafe impl<'a, Q: QueryParameter + 'a + ?Sized> QueryParameter for &'a Q {
235 fn unique_value(&self, key: &str) -> Option<Cow<str>> {
236 (**self).unique_value(key)
237 }
238
239 fn normalize(&self) -> NormalizedParameter {
240 (**self).normalize()
241 }
242}
243
244unsafe impl<'a, Q: QueryParameter + 'a + ?Sized> QueryParameter for &'a mut Q {
245 fn unique_value(&self, key: &str) -> Option<Cow<str>> {
246 (**self).unique_value(key)
247 }
248
249 fn normalize(&self) -> NormalizedParameter {
250 (**self).normalize()
251 }
252}
253
254unsafe impl UniqueValue for str {
255 fn get_unique(&self) -> Option<&str> {
256 Some(self)
257 }
258}
259
260unsafe impl UniqueValue for String {
261 fn get_unique(&self) -> Option<&str> {
262 Some(&self)
263 }
264}
265
266unsafe impl<'a, V> UniqueValue for &'a V
267where
268 V: AsRef<str> + ?Sized,
269{
270 fn get_unique(&self) -> Option<&str> {
271 Some(self.as_ref())
272 }
273}
274
275unsafe impl<'a> UniqueValue for Cow<'a, str> {
276 fn get_unique(&self) -> Option<&str> {
277 Some(self.as_ref())
278 }
279}
280
281unsafe impl<V: UniqueValue> UniqueValue for Option<V> {
282 fn get_unique(&self) -> Option<&str> {
283 self.as_ref().and_then(V::get_unique)
284 }
285}
286
287unsafe impl<V: UniqueValue> UniqueValue for [V] {
288 fn get_unique(&self) -> Option<&str> {
289 if self.len() > 1 {
290 None
291 } else {
292 self.get(0).and_then(V::get_unique)
293 }
294 }
295}
296
297unsafe impl<V: UniqueValue + ?Sized> UniqueValue for Box<V> {
298 fn get_unique(&self) -> Option<&str> {
299 (**self).get_unique()
300 }
301}
302
303unsafe impl<V: UniqueValue + ?Sized> UniqueValue for Rc<V> {
304 fn get_unique(&self) -> Option<&str> {
305 (**self).get_unique()
306 }
307}
308
309unsafe impl<V: UniqueValue + ?Sized> UniqueValue for Arc<V> {
310 fn get_unique(&self) -> Option<&str> {
311 (**self).get_unique()
312 }
313}
314
315unsafe impl<V: UniqueValue> UniqueValue for Vec<V> {
316 fn get_unique(&self) -> Option<&str> {
317 if self.len() > 1 {
318 None
319 } else {
320 self.get(0).and_then(V::get_unique)
321 }
322 }
323}
324
325mod test {
326 use super::*;
327
328 #[allow(unused)]
330 #[allow(dead_code)]
331 fn test_query_parameter_impls() {
332 let _ = (&HashMap::<String, String>::new()) as &dyn QueryParameter;
333 let _ = (&HashMap::<&'static str, &'static str>::new()) as &dyn QueryParameter;
334 let _ = (&HashMap::<Cow<'static, str>, Cow<'static, str>>::new()) as &dyn QueryParameter;
335
336 let _ = (&HashMap::<String, Vec<String>>::new()) as &dyn QueryParameter;
337 let _ = (&HashMap::<String, Box<String>>::new()) as &dyn QueryParameter;
338 let _ = (&HashMap::<String, Box<[Cow<'static, str>]>>::new()) as &dyn QueryParameter;
339 }
340}