scrappy_router/
de.rs

1use serde::de::{self, Deserializer, Error as DeError, Visitor};
2use serde::forward_to_deserialize_any;
3
4use crate::path::{Path, PathIter};
5use crate::ResourcePath;
6
7macro_rules! unsupported_type {
8    ($trait_fn:ident, $name:expr) => {
9        fn $trait_fn<V>(self, _: V) -> Result<V::Value, Self::Error>
10            where V: Visitor<'de>
11        {
12            Err(de::value::Error::custom(concat!("unsupported type: ", $name)))
13        }
14    };
15}
16
17macro_rules! parse_single_value {
18    ($trait_fn:ident, $visit_fn:ident, $tp:tt) => {
19        fn $trait_fn<V>(self, visitor: V) -> Result<V::Value, Self::Error>
20            where V: Visitor<'de>
21        {
22            if self.path.len() != 1 {
23                Err(de::value::Error::custom(
24                    format!("wrong number of parameters: {} expected 1",
25                            self.path.len()).as_str()))
26            } else {
27                let v = self.path[0].parse().map_err(
28                    |_| de::value::Error::custom(
29                        format!("can not parse {:?} to a {}", &self.path[0], $tp)))?;
30                visitor.$visit_fn(v)
31            }
32        }
33    }
34}
35
36pub struct PathDeserializer<'de, T: ResourcePath + 'de> {
37    path: &'de Path<T>,
38}
39
40impl<'de, T: ResourcePath + 'de> PathDeserializer<'de, T> {
41    pub fn new(path: &'de Path<T>) -> Self {
42        PathDeserializer { path }
43    }
44}
45
46impl<'de, T: ResourcePath + 'de> Deserializer<'de> for PathDeserializer<'de, T> {
47    type Error = de::value::Error;
48
49    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
50    where
51        V: Visitor<'de>,
52    {
53        visitor.visit_map(ParamsDeserializer {
54            params: self.path.iter(),
55            current: None,
56        })
57    }
58
59    fn deserialize_struct<V>(
60        self,
61        _: &'static str,
62        _: &'static [&'static str],
63        visitor: V,
64    ) -> Result<V::Value, Self::Error>
65    where
66        V: Visitor<'de>,
67    {
68        self.deserialize_map(visitor)
69    }
70
71    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
72    where
73        V: Visitor<'de>,
74    {
75        visitor.visit_unit()
76    }
77
78    fn deserialize_unit_struct<V>(
79        self,
80        _: &'static str,
81        visitor: V,
82    ) -> Result<V::Value, Self::Error>
83    where
84        V: Visitor<'de>,
85    {
86        self.deserialize_unit(visitor)
87    }
88
89    fn deserialize_newtype_struct<V>(
90        self,
91        _: &'static str,
92        visitor: V,
93    ) -> Result<V::Value, Self::Error>
94    where
95        V: Visitor<'de>,
96    {
97        visitor.visit_newtype_struct(self)
98    }
99
100    fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
101    where
102        V: Visitor<'de>,
103    {
104        if self.path.len() < len {
105            Err(de::value::Error::custom(
106                format!(
107                    "wrong number of parameters: {} expected {}",
108                    self.path.len(),
109                    len
110                )
111                .as_str(),
112            ))
113        } else {
114            visitor.visit_seq(ParamsSeq {
115                params: self.path.iter(),
116            })
117        }
118    }
119
120    fn deserialize_tuple_struct<V>(
121        self,
122        _: &'static str,
123        len: usize,
124        visitor: V,
125    ) -> Result<V::Value, Self::Error>
126    where
127        V: Visitor<'de>,
128    {
129        if self.path.len() < len {
130            Err(de::value::Error::custom(
131                format!(
132                    "wrong number of parameters: {} expected {}",
133                    self.path.len(),
134                    len
135                )
136                .as_str(),
137            ))
138        } else {
139            visitor.visit_seq(ParamsSeq {
140                params: self.path.iter(),
141            })
142        }
143    }
144
145    fn deserialize_enum<V>(
146        self,
147        _: &'static str,
148        _: &'static [&'static str],
149        visitor: V,
150    ) -> Result<V::Value, Self::Error>
151    where
152        V: Visitor<'de>,
153    {
154        if self.path.is_empty() {
155            Err(de::value::Error::custom(
156                "expeceted at least one parameters",
157            ))
158        } else {
159            visitor.visit_enum(ValueEnum {
160                value: &self.path[0],
161            })
162        }
163    }
164
165    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
166    where
167        V: Visitor<'de>,
168    {
169        if self.path.len() != 1 {
170            Err(de::value::Error::custom(
171                format!("wrong number of parameters: {} expected 1", self.path.len()).as_str(),
172            ))
173        } else {
174            visitor.visit_str(&self.path[0])
175        }
176    }
177
178    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
179    where
180        V: Visitor<'de>,
181    {
182        visitor.visit_seq(ParamsSeq {
183            params: self.path.iter(),
184        })
185    }
186
187    unsupported_type!(deserialize_any, "'any'");
188    unsupported_type!(deserialize_bytes, "bytes");
189    unsupported_type!(deserialize_option, "Option<T>");
190    unsupported_type!(deserialize_identifier, "identifier");
191    unsupported_type!(deserialize_ignored_any, "ignored_any");
192
193    parse_single_value!(deserialize_bool, visit_bool, "bool");
194    parse_single_value!(deserialize_i8, visit_i8, "i8");
195    parse_single_value!(deserialize_i16, visit_i16, "i16");
196    parse_single_value!(deserialize_i32, visit_i32, "i32");
197    parse_single_value!(deserialize_i64, visit_i64, "i64");
198    parse_single_value!(deserialize_u8, visit_u8, "u8");
199    parse_single_value!(deserialize_u16, visit_u16, "u16");
200    parse_single_value!(deserialize_u32, visit_u32, "u32");
201    parse_single_value!(deserialize_u64, visit_u64, "u64");
202    parse_single_value!(deserialize_f32, visit_f32, "f32");
203    parse_single_value!(deserialize_f64, visit_f64, "f64");
204    parse_single_value!(deserialize_string, visit_string, "String");
205    parse_single_value!(deserialize_byte_buf, visit_string, "String");
206    parse_single_value!(deserialize_char, visit_char, "char");
207}
208
209struct ParamsDeserializer<'de, T: ResourcePath> {
210    params: PathIter<'de, T>,
211    current: Option<(&'de str, &'de str)>,
212}
213
214impl<'de, T: ResourcePath> de::MapAccess<'de> for ParamsDeserializer<'de, T> {
215    type Error = de::value::Error;
216
217    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
218    where
219        K: de::DeserializeSeed<'de>,
220    {
221        self.current = self.params.next().map(|ref item| (item.0, item.1));
222        match self.current {
223            Some((key, _)) => Ok(Some(seed.deserialize(Key { key })?)),
224            None => Ok(None),
225        }
226    }
227
228    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
229    where
230        V: de::DeserializeSeed<'de>,
231    {
232        if let Some((_, value)) = self.current.take() {
233            seed.deserialize(Value { value })
234        } else {
235            Err(de::value::Error::custom("unexpected item"))
236        }
237    }
238}
239
240struct Key<'de> {
241    key: &'de str,
242}
243
244impl<'de> Deserializer<'de> for Key<'de> {
245    type Error = de::value::Error;
246
247    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
248    where
249        V: Visitor<'de>,
250    {
251        visitor.visit_str(self.key)
252    }
253
254    fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
255    where
256        V: Visitor<'de>,
257    {
258        Err(de::value::Error::custom("Unexpected"))
259    }
260
261    forward_to_deserialize_any! {
262        bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
263            byte_buf option unit unit_struct newtype_struct seq tuple
264            tuple_struct map struct enum ignored_any
265    }
266}
267
268macro_rules! parse_value {
269    ($trait_fn:ident, $visit_fn:ident, $tp:tt) => {
270        fn $trait_fn<V>(self, visitor: V) -> Result<V::Value, Self::Error>
271            where V: Visitor<'de>
272        {
273            let v = self.value.parse().map_err(
274                |_| de::value::Error::custom(
275                    format!("can not parse {:?} to a {}", self.value, $tp)))?;
276            visitor.$visit_fn(v)
277        }
278    }
279}
280
281struct Value<'de> {
282    value: &'de str,
283}
284
285impl<'de> Deserializer<'de> for Value<'de> {
286    type Error = de::value::Error;
287
288    parse_value!(deserialize_bool, visit_bool, "bool");
289    parse_value!(deserialize_i8, visit_i8, "i8");
290    parse_value!(deserialize_i16, visit_i16, "i16");
291    parse_value!(deserialize_i32, visit_i32, "i16");
292    parse_value!(deserialize_i64, visit_i64, "i64");
293    parse_value!(deserialize_u8, visit_u8, "u8");
294    parse_value!(deserialize_u16, visit_u16, "u16");
295    parse_value!(deserialize_u32, visit_u32, "u32");
296    parse_value!(deserialize_u64, visit_u64, "u64");
297    parse_value!(deserialize_f32, visit_f32, "f32");
298    parse_value!(deserialize_f64, visit_f64, "f64");
299    parse_value!(deserialize_string, visit_string, "String");
300    parse_value!(deserialize_byte_buf, visit_string, "String");
301    parse_value!(deserialize_char, visit_char, "char");
302
303    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
304    where
305        V: Visitor<'de>,
306    {
307        visitor.visit_unit()
308    }
309
310    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
311    where
312        V: Visitor<'de>,
313    {
314        visitor.visit_unit()
315    }
316
317    fn deserialize_unit_struct<V>(
318        self,
319        _: &'static str,
320        visitor: V,
321    ) -> Result<V::Value, Self::Error>
322    where
323        V: Visitor<'de>,
324    {
325        visitor.visit_unit()
326    }
327
328    fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
329    where
330        V: Visitor<'de>,
331    {
332        visitor.visit_borrowed_bytes(self.value.as_bytes())
333    }
334
335    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
336    where
337        V: Visitor<'de>,
338    {
339        visitor.visit_borrowed_str(self.value)
340    }
341
342    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
343    where
344        V: Visitor<'de>,
345    {
346        visitor.visit_some(self)
347    }
348
349    fn deserialize_enum<V>(
350        self,
351        _: &'static str,
352        _: &'static [&'static str],
353        visitor: V,
354    ) -> Result<V::Value, Self::Error>
355    where
356        V: Visitor<'de>,
357    {
358        visitor.visit_enum(ValueEnum { value: self.value })
359    }
360
361    fn deserialize_newtype_struct<V>(
362        self,
363        _: &'static str,
364        visitor: V,
365    ) -> Result<V::Value, Self::Error>
366    where
367        V: Visitor<'de>,
368    {
369        visitor.visit_newtype_struct(self)
370    }
371
372    fn deserialize_tuple<V>(self, _: usize, _: V) -> Result<V::Value, Self::Error>
373    where
374        V: Visitor<'de>,
375    {
376        Err(de::value::Error::custom("unsupported type: tuple"))
377    }
378
379    fn deserialize_struct<V>(
380        self,
381        _: &'static str,
382        _: &'static [&'static str],
383        _: V,
384    ) -> Result<V::Value, Self::Error>
385    where
386        V: Visitor<'de>,
387    {
388        Err(de::value::Error::custom("unsupported type: struct"))
389    }
390
391    fn deserialize_tuple_struct<V>(
392        self,
393        _: &'static str,
394        _: usize,
395        _: V,
396    ) -> Result<V::Value, Self::Error>
397    where
398        V: Visitor<'de>,
399    {
400        Err(de::value::Error::custom("unsupported type: tuple struct"))
401    }
402
403    unsupported_type!(deserialize_any, "any");
404    unsupported_type!(deserialize_seq, "seq");
405    unsupported_type!(deserialize_map, "map");
406    unsupported_type!(deserialize_identifier, "identifier");
407}
408
409struct ParamsSeq<'de, T: ResourcePath> {
410    params: PathIter<'de, T>,
411}
412
413impl<'de, T: ResourcePath> de::SeqAccess<'de> for ParamsSeq<'de, T> {
414    type Error = de::value::Error;
415
416    fn next_element_seed<U>(&mut self, seed: U) -> Result<Option<U::Value>, Self::Error>
417    where
418        U: de::DeserializeSeed<'de>,
419    {
420        match self.params.next() {
421            Some(item) => Ok(Some(seed.deserialize(Value { value: item.1 })?)),
422            None => Ok(None),
423        }
424    }
425}
426
427struct ValueEnum<'de> {
428    value: &'de str,
429}
430
431impl<'de> de::EnumAccess<'de> for ValueEnum<'de> {
432    type Error = de::value::Error;
433    type Variant = UnitVariant;
434
435    fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
436    where
437        V: de::DeserializeSeed<'de>,
438    {
439        Ok((seed.deserialize(Key { key: self.value })?, UnitVariant))
440    }
441}
442
443struct UnitVariant;
444
445impl<'de> de::VariantAccess<'de> for UnitVariant {
446    type Error = de::value::Error;
447
448    fn unit_variant(self) -> Result<(), Self::Error> {
449        Ok(())
450    }
451
452    fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
453    where
454        T: de::DeserializeSeed<'de>,
455    {
456        Err(de::value::Error::custom("not supported"))
457    }
458
459    fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
460    where
461        V: Visitor<'de>,
462    {
463        Err(de::value::Error::custom("not supported"))
464    }
465
466    fn struct_variant<V>(
467        self,
468        _: &'static [&'static str],
469        _: V,
470    ) -> Result<V::Value, Self::Error>
471    where
472        V: Visitor<'de>,
473    {
474        Err(de::value::Error::custom("not supported"))
475    }
476}
477
478#[cfg(test)]
479mod tests {
480    use serde::de;
481    use serde_derive::Deserialize;
482
483    use super::*;
484    use crate::path::Path;
485    use crate::router::Router;
486
487    #[derive(Deserialize)]
488    struct MyStruct {
489        key: String,
490        value: String,
491    }
492
493    #[derive(Deserialize)]
494    struct Id {
495        _id: String,
496    }
497
498    #[derive(Debug, Deserialize)]
499    struct Test1(String, u32);
500
501    #[derive(Debug, Deserialize)]
502    struct Test2 {
503        key: String,
504        value: u32,
505    }
506
507    #[derive(Debug, Deserialize, PartialEq)]
508    #[serde(rename_all = "lowercase")]
509    enum TestEnum {
510        Val1,
511        Val2,
512    }
513
514    #[derive(Debug, Deserialize)]
515    struct Test3 {
516        val: TestEnum,
517    }
518
519    #[test]
520    fn test_request_extract() {
521        let mut router = Router::<()>::build();
522        router.path("/{key}/{value}/", ());
523        let router = router.finish();
524
525        let mut path = Path::new("/name/user1/");
526        assert!(router.recognize(&mut path).is_some());
527
528        let s: MyStruct = de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap();
529        assert_eq!(s.key, "name");
530        assert_eq!(s.value, "user1");
531
532        let s: (String, String) =
533            de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap();
534        assert_eq!(s.0, "name");
535        assert_eq!(s.1, "user1");
536
537        let mut router = Router::<()>::build();
538        router.path("/{key}/{value}/", ());
539        let router = router.finish();
540
541        let mut path = Path::new("/name/32/");
542        assert!(router.recognize(&mut path).is_some());
543
544        let s: Test1 = de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap();
545        assert_eq!(s.0, "name");
546        assert_eq!(s.1, 32);
547
548        let s: Test2 = de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap();
549        assert_eq!(s.key, "name");
550        assert_eq!(s.value, 32);
551
552        let s: (String, u8) =
553            de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap();
554        assert_eq!(s.0, "name");
555        assert_eq!(s.1, 32);
556
557        let res: Vec<String> =
558            de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap();
559        assert_eq!(res[0], "name".to_owned());
560        assert_eq!(res[1], "32".to_owned());
561    }
562
563    #[test]
564    fn test_extract_path_single() {
565        let mut router = Router::<()>::build();
566        router.path("/{value}/", ());
567        let router = router.finish();
568
569        let mut path = Path::new("/32/");
570        assert!(router.recognize(&mut path).is_some());
571        let i: i8 = de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap();
572        assert_eq!(i, 32);
573    }
574
575    #[test]
576    fn test_extract_enum() {
577        let mut router = Router::<()>::build();
578        router.path("/{val}/", ());
579        let router = router.finish();
580
581        let mut path = Path::new("/val1/");
582        assert!(router.recognize(&mut path).is_some());
583        let i: TestEnum = de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap();
584        assert_eq!(i, TestEnum::Val1);
585
586        let mut router = Router::<()>::build();
587        router.path("/{val1}/{val2}/", ());
588        let router = router.finish();
589
590        let mut path = Path::new("/val1/val2/");
591        assert!(router.recognize(&mut path).is_some());
592        let i: (TestEnum, TestEnum) =
593            de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap();
594        assert_eq!(i, (TestEnum::Val1, TestEnum::Val2));
595    }
596
597    #[test]
598    fn test_extract_enum_value() {
599        let mut router = Router::<()>::build();
600        router.path("/{val}/", ());
601        let router = router.finish();
602
603        let mut path = Path::new("/val1/");
604        assert!(router.recognize(&mut path).is_some());
605        let i: Test3 = de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap();
606        assert_eq!(i.val, TestEnum::Val1);
607
608        let mut path = Path::new("/val3/");
609        assert!(router.recognize(&mut path).is_some());
610        let i: Result<Test3, de::value::Error> =
611            de::Deserialize::deserialize(PathDeserializer::new(&path));
612        assert!(i.is_err());
613        assert!(format!("{:?}", i).contains("unknown variant"));
614    }
615
616    #[test]
617    fn test_extract_errors() {
618        let mut router = Router::<()>::build();
619        router.path("/{value}/", ());
620        let router = router.finish();
621
622        let mut path = Path::new("/name/");
623        assert!(router.recognize(&mut path).is_some());
624
625        let s: Result<Test1, de::value::Error> =
626            de::Deserialize::deserialize(PathDeserializer::new(&path));
627        assert!(s.is_err());
628        assert!(format!("{:?}", s).contains("wrong number of parameters"));
629
630        let s: Result<Test2, de::value::Error> =
631            de::Deserialize::deserialize(PathDeserializer::new(&path));
632        assert!(s.is_err());
633        assert!(format!("{:?}", s).contains("can not parse"));
634
635        let s: Result<(String, String), de::value::Error> =
636            de::Deserialize::deserialize(PathDeserializer::new(&path));
637        assert!(s.is_err());
638        assert!(format!("{:?}", s).contains("wrong number of parameters"));
639
640        let s: Result<u32, de::value::Error> =
641            de::Deserialize::deserialize(PathDeserializer::new(&path));
642        assert!(s.is_err());
643        assert!(format!("{:?}", s).contains("can not parse"));
644    }
645
646    // #[test]
647    // fn test_extract_path_decode() {
648    //     let mut router = Router::<()>::default();
649    //     router.register_resource(Resource::new(ResourceDef::new("/{value}/")));
650
651    //     macro_rules! test_single_value {
652    //         ($value:expr, $expected:expr) => {{
653    //             let req = TestRequest::with_uri($value).finish();
654    //             let info = router.recognize(&req, &(), 0);
655    //             let req = req.with_route_info(info);
656    //             assert_eq!(
657    //                 *Path::<String>::from_request(&req, &PathConfig::default()).unwrap(),
658    //                 $expected
659    //             );
660    //         }};
661    //     }
662
663    //     test_single_value!("/%25/", "%");
664    //     test_single_value!("/%40%C2%A3%24%25%5E%26%2B%3D/", "@£$%^&+=");
665    //     test_single_value!("/%2B/", "+");
666    //     test_single_value!("/%252B/", "%2B");
667    //     test_single_value!("/%2F/", "/");
668    //     test_single_value!("/%252F/", "%2F");
669    //     test_single_value!(
670    //         "/http%3A%2F%2Flocalhost%3A80%2Ffoo/",
671    //         "http://localhost:80/foo"
672    //     );
673    //     test_single_value!("/%2Fvar%2Flog%2Fsyslog/", "/var/log/syslog");
674    //     test_single_value!(
675    //         "/http%3A%2F%2Flocalhost%3A80%2Ffile%2F%252Fvar%252Flog%252Fsyslog/",
676    //         "http://localhost:80/file/%2Fvar%2Flog%2Fsyslog"
677    //     );
678
679    //     let req = TestRequest::with_uri("/%25/7/?id=test").finish();
680
681    //     let mut router = Router::<()>::default();
682    //     router.register_resource(Resource::new(ResourceDef::new("/{key}/{value}/")));
683    //     let info = router.recognize(&req, &(), 0);
684    //     let req = req.with_route_info(info);
685
686    //     let s = Path::<Test2>::from_request(&req, &PathConfig::default()).unwrap();
687    //     assert_eq!(s.key, "%");
688    //     assert_eq!(s.value, 7);
689
690    //     let s = Path::<(String, String)>::from_request(&req, &PathConfig::default()).unwrap();
691    //     assert_eq!(s.0, "%");
692    //     assert_eq!(s.1, "7");
693    // }
694
695    // #[test]
696    // fn test_extract_path_no_decode() {
697    //     let mut router = Router::<()>::default();
698    //     router.register_resource(Resource::new(ResourceDef::new("/{value}/")));
699
700    //     let req = TestRequest::with_uri("/%25/").finish();
701    //     let info = router.recognize(&req, &(), 0);
702    //     let req = req.with_route_info(info);
703    //     assert_eq!(
704    //         *Path::<String>::from_request(&req, &&PathConfig::default().disable_decoding())
705    //             .unwrap(),
706    //         "%25"
707    //     );
708    // }
709}