1 use crate::util::PercentDecodedStr;
2 use http::Extensions;
3 use matchit::Params;
4 use std::sync::Arc;
5 
6 pub(crate) enum UrlParams {
7     Params(Vec<(Arc<str>, PercentDecodedStr)>),
8     InvalidUtf8InPathParam { key: Arc<str> },
9 }
10 
insert_url_params(extensions: &mut Extensions, params: Params)11 pub(super) fn insert_url_params(extensions: &mut Extensions, params: Params) {
12     let current_params = extensions.get_mut();
13 
14     if let Some(UrlParams::InvalidUtf8InPathParam { .. }) = current_params {
15         // nothing to do here since an error was stored earlier
16         return;
17     }
18 
19     let params = params
20         .iter()
21         .filter(|(key, _)| !key.starts_with(super::NEST_TAIL_PARAM))
22         .filter(|(key, _)| !key.starts_with(super::FALLBACK_PARAM))
23         .map(|(k, v)| {
24             if let Some(decoded) = PercentDecodedStr::new(v) {
25                 Ok((Arc::from(k), decoded))
26             } else {
27                 Err(Arc::from(k))
28             }
29         })
30         .collect::<Result<Vec<_>, _>>();
31 
32     match (current_params, params) {
33         (Some(UrlParams::InvalidUtf8InPathParam { .. }), _) => {
34             unreachable!("we check for this state earlier in this method")
35         }
36         (_, Err(invalid_key)) => {
37             extensions.insert(UrlParams::InvalidUtf8InPathParam { key: invalid_key });
38         }
39         (Some(UrlParams::Params(current)), Ok(params)) => {
40             current.extend(params);
41         }
42         (None, Ok(params)) => {
43             extensions.insert(UrlParams::Params(params));
44         }
45     }
46 }
47