Skip to content

Commit 5ff62b7

Browse files
Merge pull request #488 from ijackson/deser-unify-2
Unify deser impl (redux)
2 parents 1887369 + 10033cc commit 5ff62b7

File tree

2 files changed

+69
-113
lines changed

2 files changed

+69
-113
lines changed

src/de.rs

+47-113
Original file line numberDiff line numberDiff line change
@@ -363,122 +363,56 @@ impl<'de> de::VariantAccess<'de> for EnumAccess {
363363
}
364364
}
365365

366-
impl<'de> de::Deserializer<'de> for Config {
367-
type Error = ConfigError;
368-
366+
/// Define `$method`s, `deserialize_foo`, by forwarding to `Value`
367+
///
368+
/// `($arg: $argtype, ...)`, if supplied, are the formal arguments
369+
macro_rules! config_deserialize_via_value { { $(
370+
$method:ident $( ( $( $arg:ident: $argtype:ty ),* ) )? ;
371+
)* } => { $(
369372
#[inline]
370-
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
371-
where
372-
V: de::Visitor<'de>,
373-
{
374-
// Delegate deserialization to Value
375-
de::Deserializer::deserialize_any(self.cache, visitor)
373+
fn $method<V: de::Visitor<'de>>(
374+
self,
375+
$( $( $arg: $argtype, )* )?
376+
visitor: V,
377+
) -> Result<V::Value> {
378+
self.cache.$method( $( $( $arg, )* )? visitor)
376379
}
380+
)* } }
377381

378-
#[inline]
379-
fn deserialize_bool<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
380-
visitor.visit_bool(self.cache.into_bool()?)
381-
}
382-
383-
#[inline]
384-
fn deserialize_i8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
385-
let num = try_convert_number!(signed, self.cache, "8");
386-
visitor.visit_i8(num)
387-
}
388-
389-
#[inline]
390-
fn deserialize_i16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
391-
let num = try_convert_number!(signed, self.cache, "16");
392-
visitor.visit_i16(num)
393-
}
394-
395-
#[inline]
396-
fn deserialize_i32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
397-
let num = try_convert_number!(signed, self.cache, "32");
398-
visitor.visit_i32(num)
399-
}
400-
401-
#[inline]
402-
fn deserialize_i64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
403-
let num = try_convert_number!(signed, self.cache, "64");
404-
visitor.visit_i64(num)
405-
}
406-
407-
#[inline]
408-
fn deserialize_u8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
409-
let num = try_convert_number!(unsigned, self.cache, "8");
410-
visitor.visit_u8(num)
411-
}
412-
413-
#[inline]
414-
fn deserialize_u16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
415-
let num = try_convert_number!(unsigned, self.cache, "16");
416-
visitor.visit_u16(num)
417-
}
418-
419-
#[inline]
420-
fn deserialize_u32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
421-
let num = try_convert_number!(unsigned, self.cache, "32");
422-
visitor.visit_u32(num)
423-
}
424-
425-
#[inline]
426-
fn deserialize_u64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
427-
let num = try_convert_number!(unsigned, self.cache, "64");
428-
visitor.visit_u64(num)
429-
}
430-
431-
#[inline]
432-
fn deserialize_f32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
433-
visitor.visit_f32(self.cache.into_float()? as f32)
434-
}
435-
436-
#[inline]
437-
fn deserialize_f64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
438-
visitor.visit_f64(self.cache.into_float()?)
439-
}
440-
441-
#[inline]
442-
fn deserialize_str<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
443-
visitor.visit_string(self.cache.into_string()?)
444-
}
445-
446-
#[inline]
447-
fn deserialize_string<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
448-
visitor.visit_string(self.cache.into_string()?)
449-
}
450-
451-
#[inline]
452-
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
453-
where
454-
V: de::Visitor<'de>,
455-
{
456-
// Match an explicit nil as None and everything else as Some
457-
match self.cache.kind {
458-
ValueKind::Nil => visitor.visit_none(),
459-
_ => visitor.visit_some(self),
460-
}
461-
}
462-
463-
fn deserialize_enum<V>(
464-
self,
465-
name: &'static str,
466-
variants: &'static [&'static str],
467-
visitor: V,
468-
) -> Result<V::Value>
469-
where
470-
V: de::Visitor<'de>,
471-
{
472-
visitor.visit_enum(EnumAccess {
473-
value: self.cache,
474-
name,
475-
variants,
476-
})
477-
}
382+
impl<'de> de::Deserializer<'de> for Config {
383+
type Error = ConfigError;
478384

479-
serde::forward_to_deserialize_any! {
480-
char seq
481-
bytes byte_buf map struct unit newtype_struct
482-
identifier ignored_any unit_struct tuple_struct tuple
385+
config_deserialize_via_value! {
386+
deserialize_any;
387+
deserialize_bool;
388+
deserialize_i8;
389+
deserialize_i16;
390+
deserialize_i32;
391+
deserialize_i64;
392+
deserialize_u8;
393+
deserialize_u16;
394+
deserialize_u32;
395+
deserialize_u64;
396+
deserialize_f32;
397+
deserialize_f64;
398+
deserialize_str;
399+
deserialize_string;
400+
deserialize_option;
401+
402+
deserialize_char;
403+
deserialize_seq;
404+
deserialize_bytes;
405+
deserialize_byte_buf;
406+
deserialize_map;
407+
deserialize_unit;
408+
deserialize_identifier;
409+
deserialize_ignored_any;
410+
411+
deserialize_enum(name: &'static str, variants: &'static [&'static str]);
412+
deserialize_unit_struct(name: &'static str);
413+
deserialize_newtype_struct(name: &'static str);
414+
deserialize_tuple(n: usize);
415+
deserialize_tuple_struct(name: &'static str, n: usize);
416+
deserialize_struct(name: &'static str, fields: &'static [&'static str]);
483417
}
484418
}

tests/errors.rs

+22
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,28 @@ fn test_error_type() {
4444
);
4545
}
4646

47+
#[test]
48+
fn test_error_deser_whole() {
49+
#[derive(Deserialize, Debug)]
50+
struct Place {
51+
#[allow(dead_code)]
52+
name: usize, // is actually s string
53+
}
54+
55+
#[derive(Deserialize, Debug)]
56+
struct Output {
57+
#[allow(dead_code)]
58+
place: Place,
59+
}
60+
61+
let c = make();
62+
let err = c.try_deserialize::<Output>().unwrap_err().to_string();
63+
assert_eq!(
64+
err,
65+
"invalid type: string \"Torre di Pisa\", expected an integer for key `place.name` in tests/Settings.toml",
66+
);
67+
}
68+
4769
#[test]
4870
fn test_error_type_detached() {
4971
let c = make();

0 commit comments

Comments
 (0)