1use super::{ErrorKind, PathDeserializationError};
2use crate::util::PercentDecodedStr;
3use serde::{
4 de::{self, DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor},
5 forward_to_deserialize_any, Deserializer,
6};
7use std::{any::type_name, sync::Arc};
8
9macro_rules! unsupported_type {
10 ($trait_fn:ident) => {
11 fn $trait_fn<V>(self, _: V) -> Result<V::Value, Self::Error>
12 where
13 V: Visitor<'de>,
14 {
15 Err(PathDeserializationError::unsupported_type(type_name::<
16 V::Value,
17 >()))
18 }
19 };
20}
21
22macro_rules! parse_single_value {
23 ($trait_fn:ident, $visit_fn:ident, $ty:literal) => {
24 fn $trait_fn<V>(self, visitor: V) -> Result<V::Value, Self::Error>
25 where
26 V: Visitor<'de>,
27 {
28 if self.url_params.len() != 1 {
29 return Err(PathDeserializationError::wrong_number_of_parameters()
30 .got(self.url_params.len())
31 .expected(1));
32 }
33
34 let value = self.url_params[0].1.parse().map_err(|_| {
35 PathDeserializationError::new(ErrorKind::ParseError {
36 value: self.url_params[0].1.as_str().to_owned(),
37 expected_type: $ty,
38 })
39 })?;
40 visitor.$visit_fn(value)
41 }
42 };
43}
44
45pub(crate) struct PathDeserializer<'de> {
46 url_params: &'de [(Arc<str>, PercentDecodedStr)],
47}
48
49impl<'de> PathDeserializer<'de> {
50 #[inline]
51 pub(crate) fn new(url_params: &'de [(Arc<str>, PercentDecodedStr)]) -> Self {
52 PathDeserializer { url_params }
53 }
54}
55
56impl<'de> Deserializer<'de> for PathDeserializer<'de> {
57 type Error = PathDeserializationError;
58
59 unsupported_type!(deserialize_bytes);
60 unsupported_type!(deserialize_option);
61 unsupported_type!(deserialize_identifier);
62 unsupported_type!(deserialize_ignored_any);
63
64 parse_single_value!(deserialize_bool, visit_bool, "bool");
65 parse_single_value!(deserialize_i8, visit_i8, "i8");
66 parse_single_value!(deserialize_i16, visit_i16, "i16");
67 parse_single_value!(deserialize_i32, visit_i32, "i32");
68 parse_single_value!(deserialize_i64, visit_i64, "i64");
69 parse_single_value!(deserialize_i128, visit_i128, "i128");
70 parse_single_value!(deserialize_u8, visit_u8, "u8");
71 parse_single_value!(deserialize_u16, visit_u16, "u16");
72 parse_single_value!(deserialize_u32, visit_u32, "u32");
73 parse_single_value!(deserialize_u64, visit_u64, "u64");
74 parse_single_value!(deserialize_u128, visit_u128, "u128");
75 parse_single_value!(deserialize_f32, visit_f32, "f32");
76 parse_single_value!(deserialize_f64, visit_f64, "f64");
77 parse_single_value!(deserialize_string, visit_string, "String");
78 parse_single_value!(deserialize_byte_buf, visit_string, "String");
79 parse_single_value!(deserialize_char, visit_char, "char");
80
81 fn deserialize_any<V>(self, v: V) -> Result<V::Value, Self::Error>
82 where
83 V: Visitor<'de>,
84 {
85 self.deserialize_str(v)
86 }
87
88 fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
89 where
90 V: Visitor<'de>,
91 {
92 if self.url_params.len() != 1 {
93 return Err(PathDeserializationError::wrong_number_of_parameters()
94 .got(self.url_params.len())
95 .expected(1));
96 }
97 let key = &self.url_params[0].0;
98 let value = &self.url_params[0].1;
99 visitor
100 .visit_borrowed_str(value)
101 .map_err(|e: PathDeserializationError| {
102 if let ErrorKind::Message(message) = &e.kind {
103 PathDeserializationError::new(ErrorKind::DeserializeError {
104 key: key.to_string(),
105 value: value.as_str().to_owned(),
106 message: message.to_owned(),
107 })
108 } else {
109 e
110 }
111 })
112 }
113
114 fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
115 where
116 V: Visitor<'de>,
117 {
118 visitor.visit_unit()
119 }
120
121 fn deserialize_unit_struct<V>(
122 self,
123 _name: &'static str,
124 visitor: V,
125 ) -> Result<V::Value, Self::Error>
126 where
127 V: Visitor<'de>,
128 {
129 visitor.visit_unit()
130 }
131
132 fn deserialize_newtype_struct<V>(
133 self,
134 _name: &'static str,
135 visitor: V,
136 ) -> Result<V::Value, Self::Error>
137 where
138 V: Visitor<'de>,
139 {
140 visitor.visit_newtype_struct(self)
141 }
142
143 fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
144 where
145 V: Visitor<'de>,
146 {
147 visitor.visit_seq(SeqDeserializer {
148 params: self.url_params,
149 idx: 0,
150 })
151 }
152
153 fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
154 where
155 V: Visitor<'de>,
156 {
157 if self.url_params.len() != len {
158 return Err(PathDeserializationError::wrong_number_of_parameters()
159 .got(self.url_params.len())
160 .expected(len));
161 }
162 visitor.visit_seq(SeqDeserializer {
163 params: self.url_params,
164 idx: 0,
165 })
166 }
167
168 fn deserialize_tuple_struct<V>(
169 self,
170 _name: &'static str,
171 len: usize,
172 visitor: V,
173 ) -> Result<V::Value, Self::Error>
174 where
175 V: Visitor<'de>,
176 {
177 if self.url_params.len() != len {
178 return Err(PathDeserializationError::wrong_number_of_parameters()
179 .got(self.url_params.len())
180 .expected(len));
181 }
182 visitor.visit_seq(SeqDeserializer {
183 params: self.url_params,
184 idx: 0,
185 })
186 }
187
188 fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
189 where
190 V: Visitor<'de>,
191 {
192 visitor.visit_map(MapDeserializer {
193 params: self.url_params,
194 value: None,
195 key: None,
196 })
197 }
198
199 fn deserialize_struct<V>(
200 self,
201 _name: &'static str,
202 _fields: &'static [&'static str],
203 visitor: V,
204 ) -> Result<V::Value, Self::Error>
205 where
206 V: Visitor<'de>,
207 {
208 self.deserialize_map(visitor)
209 }
210
211 fn deserialize_enum<V>(
212 self,
213 _name: &'static str,
214 _variants: &'static [&'static str],
215 visitor: V,
216 ) -> Result<V::Value, Self::Error>
217 where
218 V: Visitor<'de>,
219 {
220 if self.url_params.len() != 1 {
221 return Err(PathDeserializationError::wrong_number_of_parameters()
222 .got(self.url_params.len())
223 .expected(1));
224 }
225
226 visitor.visit_enum(EnumDeserializer {
227 value: &self.url_params[0].1,
228 })
229 }
230}
231
232struct MapDeserializer<'de> {
233 params: &'de [(Arc<str>, PercentDecodedStr)],
234 key: Option<KeyOrIdx<'de>>,
235 value: Option<&'de PercentDecodedStr>,
236}
237
238impl<'de> MapAccess<'de> for MapDeserializer<'de> {
239 type Error = PathDeserializationError;
240
241 fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
242 where
243 K: DeserializeSeed<'de>,
244 {
245 match self.params.split_first() {
246 Some(((key, value), tail)) => {
247 self.value = Some(value);
248 self.params = tail;
249 self.key = Some(KeyOrIdx::Key(key));
250 seed.deserialize(KeyDeserializer { key }).map(Some)
251 }
252 None => Ok(None),
253 }
254 }
255
256 fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
257 where
258 V: DeserializeSeed<'de>,
259 {
260 match self.value.take() {
261 Some(value) => seed.deserialize(ValueDeserializer {
262 key: self.key.take(),
263 value,
264 }),
265 None => Err(PathDeserializationError::custom("value is missing")),
266 }
267 }
268}
269
270struct KeyDeserializer<'de> {
271 key: &'de str,
272}
273
274macro_rules! parse_key {
275 ($trait_fn:ident) => {
276 fn $trait_fn<V>(self, visitor: V) -> Result<V::Value, Self::Error>
277 where
278 V: Visitor<'de>,
279 {
280 visitor.visit_str(&self.key)
281 }
282 };
283}
284
285impl<'de> Deserializer<'de> for KeyDeserializer<'de> {
286 type Error = PathDeserializationError;
287
288 parse_key!(deserialize_identifier);
289 parse_key!(deserialize_str);
290 parse_key!(deserialize_string);
291
292 fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
293 where
294 V: Visitor<'de>,
295 {
296 Err(PathDeserializationError::custom("Unexpected key type"))
297 }
298
299 forward_to_deserialize_any! {
300 bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char bytes
301 byte_buf option unit unit_struct seq tuple
302 tuple_struct map newtype_struct struct enum ignored_any
303 }
304}
305
306macro_rules! parse_value {
307 ($trait_fn:ident, $visit_fn:ident, $ty:literal) => {
308 fn $trait_fn<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
309 where
310 V: Visitor<'de>,
311 {
312 let v = self.value.parse().map_err(|_| {
313 if let Some(key) = self.key.take() {
314 let kind = match key {
315 KeyOrIdx::Key(key) => ErrorKind::ParseErrorAtKey {
316 key: key.to_owned(),
317 value: self.value.as_str().to_owned(),
318 expected_type: $ty,
319 },
320 KeyOrIdx::Idx { idx: index, key: _ } => ErrorKind::ParseErrorAtIndex {
321 index,
322 value: self.value.as_str().to_owned(),
323 expected_type: $ty,
324 },
325 };
326 PathDeserializationError::new(kind)
327 } else {
328 PathDeserializationError::new(ErrorKind::ParseError {
329 value: self.value.as_str().to_owned(),
330 expected_type: $ty,
331 })
332 }
333 })?;
334 visitor.$visit_fn(v)
335 }
336 };
337}
338
339#[derive(Debug)]
340struct ValueDeserializer<'de> {
341 key: Option<KeyOrIdx<'de>>,
342 value: &'de PercentDecodedStr,
343}
344
345impl<'de> Deserializer<'de> for ValueDeserializer<'de> {
346 type Error = PathDeserializationError;
347
348 unsupported_type!(deserialize_map);
349 unsupported_type!(deserialize_identifier);
350
351 parse_value!(deserialize_bool, visit_bool, "bool");
352 parse_value!(deserialize_i8, visit_i8, "i8");
353 parse_value!(deserialize_i16, visit_i16, "i16");
354 parse_value!(deserialize_i32, visit_i32, "i32");
355 parse_value!(deserialize_i64, visit_i64, "i64");
356 parse_value!(deserialize_i128, visit_i128, "i128");
357 parse_value!(deserialize_u8, visit_u8, "u8");
358 parse_value!(deserialize_u16, visit_u16, "u16");
359 parse_value!(deserialize_u32, visit_u32, "u32");
360 parse_value!(deserialize_u64, visit_u64, "u64");
361 parse_value!(deserialize_u128, visit_u128, "u128");
362 parse_value!(deserialize_f32, visit_f32, "f32");
363 parse_value!(deserialize_f64, visit_f64, "f64");
364 parse_value!(deserialize_string, visit_string, "String");
365 parse_value!(deserialize_byte_buf, visit_string, "String");
366 parse_value!(deserialize_char, visit_char, "char");
367
368 fn deserialize_any<V>(self, v: V) -> Result<V::Value, Self::Error>
369 where
370 V: Visitor<'de>,
371 {
372 self.deserialize_str(v)
373 }
374
375 fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
376 where
377 V: Visitor<'de>,
378 {
379 visitor
380 .visit_borrowed_str(self.value)
381 .map_err(|e: PathDeserializationError| {
382 if let (ErrorKind::Message(message), Some(key)) = (&e.kind, self.key.as_ref()) {
383 PathDeserializationError::new(ErrorKind::DeserializeError {
384 key: key.key().to_owned(),
385 value: self.value.as_str().to_owned(),
386 message: message.to_owned(),
387 })
388 } else {
389 e
390 }
391 })
392 }
393
394 fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
395 where
396 V: Visitor<'de>,
397 {
398 visitor.visit_borrowed_bytes(self.value.as_bytes())
399 }
400
401 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
402 where
403 V: Visitor<'de>,
404 {
405 visitor.visit_some(self)
406 }
407
408 fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
409 where
410 V: Visitor<'de>,
411 {
412 visitor.visit_unit()
413 }
414
415 fn deserialize_unit_struct<V>(
416 self,
417 _name: &'static str,
418 visitor: V,
419 ) -> Result<V::Value, Self::Error>
420 where
421 V: Visitor<'de>,
422 {
423 visitor.visit_unit()
424 }
425
426 fn deserialize_newtype_struct<V>(
427 self,
428 _name: &'static str,
429 visitor: V,
430 ) -> Result<V::Value, Self::Error>
431 where
432 V: Visitor<'de>,
433 {
434 visitor.visit_newtype_struct(self)
435 }
436
437 fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
438 where
439 V: Visitor<'de>,
440 {
441 struct PairDeserializer<'de> {
442 key: Option<KeyOrIdx<'de>>,
443 value: Option<&'de PercentDecodedStr>,
444 }
445
446 impl<'de> SeqAccess<'de> for PairDeserializer<'de> {
447 type Error = PathDeserializationError;
448
449 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
450 where
451 T: DeserializeSeed<'de>,
452 {
453 match self.key.take() {
454 Some(KeyOrIdx::Idx { idx: _, key }) => {
455 return seed.deserialize(KeyDeserializer { key }).map(Some);
456 }
457 Some(KeyOrIdx::Key(_)) => {
458 return Err(PathDeserializationError::custom(
459 "array types are not supported",
460 ));
461 }
462 None => {}
463 };
464
465 self.value
466 .take()
467 .map(|value| seed.deserialize(ValueDeserializer { key: None, value }))
468 .transpose()
469 }
470 }
471
472 if len == 2 {
473 match self.key {
474 Some(key) => visitor.visit_seq(PairDeserializer {
475 key: Some(key),
476 value: Some(self.value),
477 }),
478 None => unreachable!(),
481 }
482 } else {
483 Err(PathDeserializationError::unsupported_type(type_name::<
484 V::Value,
485 >()))
486 }
487 }
488
489 fn deserialize_seq<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
490 where
491 V: Visitor<'de>,
492 {
493 Err(PathDeserializationError::unsupported_type(type_name::<
494 V::Value,
495 >()))
496 }
497
498 fn deserialize_tuple_struct<V>(
499 self,
500 _name: &'static str,
501 _len: usize,
502 _visitor: V,
503 ) -> Result<V::Value, Self::Error>
504 where
505 V: Visitor<'de>,
506 {
507 Err(PathDeserializationError::unsupported_type(type_name::<
508 V::Value,
509 >()))
510 }
511
512 fn deserialize_struct<V>(
513 self,
514 _name: &'static str,
515 _fields: &'static [&'static str],
516 _visitor: V,
517 ) -> Result<V::Value, Self::Error>
518 where
519 V: Visitor<'de>,
520 {
521 Err(PathDeserializationError::unsupported_type(type_name::<
522 V::Value,
523 >()))
524 }
525
526 fn deserialize_enum<V>(
527 self,
528 _name: &'static str,
529 _variants: &'static [&'static str],
530 visitor: V,
531 ) -> Result<V::Value, Self::Error>
532 where
533 V: Visitor<'de>,
534 {
535 visitor.visit_enum(EnumDeserializer { value: self.value })
536 }
537
538 fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
539 where
540 V: Visitor<'de>,
541 {
542 visitor.visit_unit()
543 }
544}
545
546struct EnumDeserializer<'de> {
547 value: &'de str,
548}
549
550impl<'de> EnumAccess<'de> for EnumDeserializer<'de> {
551 type Error = PathDeserializationError;
552 type Variant = UnitVariant;
553
554 fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
555 where
556 V: de::DeserializeSeed<'de>,
557 {
558 Ok((
559 seed.deserialize(KeyDeserializer { key: self.value })?,
560 UnitVariant,
561 ))
562 }
563}
564
565struct UnitVariant;
566
567impl<'de> VariantAccess<'de> for UnitVariant {
568 type Error = PathDeserializationError;
569
570 fn unit_variant(self) -> Result<(), Self::Error> {
571 Ok(())
572 }
573
574 fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
575 where
576 T: DeserializeSeed<'de>,
577 {
578 Err(PathDeserializationError::unsupported_type(
579 "newtype enum variant",
580 ))
581 }
582
583 fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
584 where
585 V: Visitor<'de>,
586 {
587 Err(PathDeserializationError::unsupported_type(
588 "tuple enum variant",
589 ))
590 }
591
592 fn struct_variant<V>(
593 self,
594 _fields: &'static [&'static str],
595 _visitor: V,
596 ) -> Result<V::Value, Self::Error>
597 where
598 V: Visitor<'de>,
599 {
600 Err(PathDeserializationError::unsupported_type(
601 "struct enum variant",
602 ))
603 }
604}
605
606struct SeqDeserializer<'de> {
607 params: &'de [(Arc<str>, PercentDecodedStr)],
608 idx: usize,
609}
610
611impl<'de> SeqAccess<'de> for SeqDeserializer<'de> {
612 type Error = PathDeserializationError;
613
614 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
615 where
616 T: DeserializeSeed<'de>,
617 {
618 match self.params.split_first() {
619 Some(((key, value), tail)) => {
620 self.params = tail;
621 let idx = self.idx;
622 self.idx += 1;
623 Ok(Some(seed.deserialize(ValueDeserializer {
624 key: Some(KeyOrIdx::Idx { idx, key }),
625 value,
626 })?))
627 }
628 None => Ok(None),
629 }
630 }
631}
632
633#[derive(Debug, Clone)]
634enum KeyOrIdx<'de> {
635 Key(&'de str),
636 Idx { idx: usize, key: &'de str },
637}
638
639impl<'de> KeyOrIdx<'de> {
640 fn key(&self) -> &'de str {
641 match &self {
642 Self::Key(key) => key,
643 Self::Idx { key, .. } => key,
644 }
645 }
646}
647
648#[cfg(test)]
649mod tests {
650 use super::*;
651 use serde::Deserialize;
652 use std::collections::HashMap;
653
654 #[derive(Debug, Deserialize, Eq, PartialEq)]
655 enum MyEnum {
656 A,
657 B,
658 #[serde(rename = "c")]
659 C,
660 }
661
662 #[derive(Debug, Deserialize, Eq, PartialEq)]
663 struct Struct {
664 c: String,
665 b: bool,
666 a: i32,
667 }
668
669 fn create_url_params<I, K, V>(values: I) -> Vec<(Arc<str>, PercentDecodedStr)>
670 where
671 I: IntoIterator<Item = (K, V)>,
672 K: AsRef<str>,
673 V: AsRef<str>,
674 {
675 values
676 .into_iter()
677 .map(|(k, v)| (Arc::from(k.as_ref()), PercentDecodedStr::new(v).unwrap()))
678 .collect()
679 }
680
681 macro_rules! check_single_value {
682 ($ty:ty, $value_str:literal, $value:expr) => {
683 #[allow(clippy::bool_assert_comparison)]
684 {
685 let url_params = create_url_params(vec![("value", $value_str)]);
686 let deserializer = PathDeserializer::new(&url_params);
687 assert_eq!(<$ty>::deserialize(deserializer).unwrap(), $value);
688 }
689 };
690 }
691
692 #[test]
693 fn test_parse_single_value() {
694 check_single_value!(bool, "true", true);
695 check_single_value!(bool, "false", false);
696 check_single_value!(i8, "-123", -123);
697 check_single_value!(i16, "-123", -123);
698 check_single_value!(i32, "-123", -123);
699 check_single_value!(i64, "-123", -123);
700 check_single_value!(i128, "123", 123);
701 check_single_value!(u8, "123", 123);
702 check_single_value!(u16, "123", 123);
703 check_single_value!(u32, "123", 123);
704 check_single_value!(u64, "123", 123);
705 check_single_value!(u128, "123", 123);
706 check_single_value!(f32, "123", 123.0);
707 check_single_value!(f64, "123", 123.0);
708 check_single_value!(String, "abc", "abc");
709 check_single_value!(String, "one%20two", "one two");
710 check_single_value!(&str, "abc", "abc");
711 check_single_value!(&str, "one%20two", "one two");
712 check_single_value!(char, "a", 'a');
713
714 let url_params = create_url_params(vec![("a", "B")]);
715 assert_eq!(
716 MyEnum::deserialize(PathDeserializer::new(&url_params)).unwrap(),
717 MyEnum::B
718 );
719
720 let url_params = create_url_params(vec![("a", "1"), ("b", "2")]);
721 let error_kind = i32::deserialize(PathDeserializer::new(&url_params))
722 .unwrap_err()
723 .kind;
724 assert!(matches!(
725 error_kind,
726 ErrorKind::WrongNumberOfParameters {
727 expected: 1,
728 got: 2
729 }
730 ));
731 }
732
733 #[test]
734 fn test_parse_seq() {
735 let url_params = create_url_params(vec![("a", "1"), ("b", "true"), ("c", "abc")]);
736 assert_eq!(
737 <(i32, bool, String)>::deserialize(PathDeserializer::new(&url_params)).unwrap(),
738 (1, true, "abc".to_owned())
739 );
740
741 #[derive(Debug, Deserialize, Eq, PartialEq)]
742 struct TupleStruct(i32, bool, String);
743 assert_eq!(
744 TupleStruct::deserialize(PathDeserializer::new(&url_params)).unwrap(),
745 TupleStruct(1, true, "abc".to_owned())
746 );
747
748 let url_params = create_url_params(vec![("a", "1"), ("b", "2"), ("c", "3")]);
749 assert_eq!(
750 <Vec<i32>>::deserialize(PathDeserializer::new(&url_params)).unwrap(),
751 vec![1, 2, 3]
752 );
753
754 let url_params = create_url_params(vec![("a", "c"), ("a", "B")]);
755 assert_eq!(
756 <Vec<MyEnum>>::deserialize(PathDeserializer::new(&url_params)).unwrap(),
757 vec![MyEnum::C, MyEnum::B]
758 );
759 }
760
761 #[test]
762 fn test_parse_seq_tuple_string_string() {
763 let url_params = create_url_params(vec![("a", "foo"), ("b", "bar")]);
764 assert_eq!(
765 <Vec<(String, String)>>::deserialize(PathDeserializer::new(&url_params)).unwrap(),
766 vec![
767 ("a".to_owned(), "foo".to_owned()),
768 ("b".to_owned(), "bar".to_owned())
769 ]
770 );
771 }
772
773 #[test]
774 fn test_parse_seq_tuple_string_parse() {
775 let url_params = create_url_params(vec![("a", "1"), ("b", "2")]);
776 assert_eq!(
777 <Vec<(String, u32)>>::deserialize(PathDeserializer::new(&url_params)).unwrap(),
778 vec![("a".to_owned(), 1), ("b".to_owned(), 2)]
779 );
780 }
781
782 #[test]
783 fn test_parse_struct() {
784 let url_params = create_url_params(vec![("a", "1"), ("b", "true"), ("c", "abc")]);
785 assert_eq!(
786 Struct::deserialize(PathDeserializer::new(&url_params)).unwrap(),
787 Struct {
788 c: "abc".to_owned(),
789 b: true,
790 a: 1,
791 }
792 );
793 }
794
795 #[test]
796 fn test_parse_struct_ignoring_additional_fields() {
797 let url_params = create_url_params(vec![
798 ("a", "1"),
799 ("b", "true"),
800 ("c", "abc"),
801 ("d", "false"),
802 ]);
803 assert_eq!(
804 Struct::deserialize(PathDeserializer::new(&url_params)).unwrap(),
805 Struct {
806 c: "abc".to_owned(),
807 b: true,
808 a: 1,
809 }
810 );
811 }
812
813 #[test]
814 fn test_parse_map() {
815 let url_params = create_url_params(vec![("a", "1"), ("b", "true"), ("c", "abc")]);
816 assert_eq!(
817 <HashMap<String, String>>::deserialize(PathDeserializer::new(&url_params)).unwrap(),
818 [("a", "1"), ("b", "true"), ("c", "abc")]
819 .iter()
820 .map(|(key, value)| ((*key).to_owned(), (*value).to_owned()))
821 .collect()
822 );
823 }
824
825 macro_rules! test_parse_error {
826 (
827 $params:expr,
828 $ty:ty,
829 $expected_error_kind:expr $(,)?
830 ) => {
831 let url_params = create_url_params($params);
832 let actual_error_kind = <$ty>::deserialize(PathDeserializer::new(&url_params))
833 .unwrap_err()
834 .kind;
835 assert_eq!(actual_error_kind, $expected_error_kind);
836 };
837 }
838
839 #[test]
840 fn test_parse_tuple_too_many_fields() {
841 test_parse_error!(
842 vec![("a", "abc"), ("b", "true"), ("c", "1"), ("d", "false"),],
843 (&str, bool, u32),
844 ErrorKind::WrongNumberOfParameters {
845 got: 4,
846 expected: 3,
847 }
848 );
849 }
850
851 #[test]
852 fn test_wrong_number_of_parameters_error() {
853 test_parse_error!(
854 vec![("a", "1")],
855 (u32, u32),
856 ErrorKind::WrongNumberOfParameters {
857 got: 1,
858 expected: 2,
859 }
860 );
861 }
862
863 #[test]
864 fn test_parse_error_at_key_error() {
865 #[derive(Debug, Deserialize)]
866 #[allow(dead_code)]
867 struct Params {
868 a: u32,
869 }
870 test_parse_error!(
871 vec![("a", "false")],
872 Params,
873 ErrorKind::ParseErrorAtKey {
874 key: "a".to_owned(),
875 value: "false".to_owned(),
876 expected_type: "u32",
877 }
878 );
879 }
880
881 #[test]
882 fn test_parse_error_at_key_error_multiple() {
883 #[derive(Debug, Deserialize)]
884 #[allow(dead_code)]
885 struct Params {
886 a: u32,
887 b: u32,
888 }
889 test_parse_error!(
890 vec![("a", "false")],
891 Params,
892 ErrorKind::ParseErrorAtKey {
893 key: "a".to_owned(),
894 value: "false".to_owned(),
895 expected_type: "u32",
896 }
897 );
898 }
899
900 #[test]
901 fn test_parse_error_at_index_error() {
902 test_parse_error!(
903 vec![("a", "false"), ("b", "true")],
904 (bool, u32),
905 ErrorKind::ParseErrorAtIndex {
906 index: 1,
907 value: "true".to_owned(),
908 expected_type: "u32",
909 }
910 );
911 }
912
913 #[test]
914 fn test_parse_error_error() {
915 test_parse_error!(
916 vec![("a", "false")],
917 u32,
918 ErrorKind::ParseError {
919 value: "false".to_owned(),
920 expected_type: "u32",
921 }
922 );
923 }
924
925 #[test]
926 fn test_unsupported_type_error_nested_data_structure() {
927 test_parse_error!(
928 vec![("a", "false")],
929 Vec<Vec<u32>>,
930 ErrorKind::UnsupportedType {
931 name: "alloc::vec::Vec<u32>",
932 }
933 );
934 }
935
936 #[test]
937 fn test_parse_seq_tuple_unsupported_key_type() {
938 test_parse_error!(
939 vec![("a", "false")],
940 Vec<(u32, String)>,
941 ErrorKind::Message("Unexpected key type".to_owned())
942 );
943 }
944
945 #[test]
946 fn test_parse_seq_wrong_tuple_length() {
947 test_parse_error!(
948 vec![("a", "false")],
949 Vec<(String, String, String)>,
950 ErrorKind::UnsupportedType {
951 name: "(alloc::string::String, alloc::string::String, alloc::string::String)",
952 }
953 );
954 }
955
956 #[test]
957 fn test_parse_seq_seq() {
958 test_parse_error!(
959 vec![("a", "false")],
960 Vec<Vec<String>>,
961 ErrorKind::UnsupportedType {
962 name: "alloc::vec::Vec<alloc::string::String>",
963 }
964 );
965 }
966
967 #[test]
968 fn test_deserialize_key_value() {
969 test_parse_error!(
970 vec![("id", "123123-123-123123")],
971 uuid::Uuid,
972 ErrorKind::DeserializeError {
973 key: "id".to_owned(),
974 value: "123123-123-123123".to_owned(),
975 message: "UUID parsing failed: invalid group count: expected 5, found 3".to_owned(),
976 }
977 );
978 }
979}