summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2023-10-23 20:19:33 +0200
committerGitHub <noreply@github.com>2023-10-23 20:19:33 +0200
commit5ff62b7eae05a2206836fd102ac09c8aff45434e (patch)
tree9e051e94b9c028a82b2ac2ac5b5ec0bb12389a4f
parent18873691500efb1f04f97b48d1018a003b2e7f75 (diff)
parent10033cca54a651d8da3d408090fcfd279d762230 (diff)
Merge pull request #488 from ijackson/deser-unify-2
Unify deser impl (redux)
-rw-r--r--src/de.rs160
-rw-r--r--tests/errors.rs22
2 files changed, 69 insertions, 113 deletions
diff --git a/src/de.rs b/src/de.rs
index 0325ce6..0e2b8de 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -363,122 +363,56 @@ impl<'de> de::VariantAccess<'de> for EnumAccess {
}
}
-impl<'de> de::Deserializer<'de> for Config {
- type Error = ConfigError;
-
+/// Define `$method`s, `deserialize_foo`, by forwarding to `Value`
+///
+/// `($arg: $argtype, ...)`, if supplied, are the formal arguments
+macro_rules! config_deserialize_via_value { { $(
+ $method:ident $( ( $( $arg:ident: $argtype:ty ),* ) )? ;
+)* } => { $(
#[inline]
- fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
- where
- V: de::Visitor<'de>,
- {
- // Delegate deserialization to Value
- de::Deserializer::deserialize_any(self.cache, visitor)
+ fn $method<V: de::Visitor<'de>>(
+ self,
+ $( $( $arg: $argtype, )* )?
+ visitor: V,
+ ) -> Result<V::Value> {
+ self.cache.$method( $( $( $arg, )* )? visitor)
}
+)* } }
- #[inline]
- fn deserialize_bool<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- visitor.visit_bool(self.cache.into_bool()?)
- }
-
- #[inline]
- fn deserialize_i8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- let num = try_convert_number!(signed, self.cache, "8");
- visitor.visit_i8(num)
- }
-
- #[inline]
- fn deserialize_i16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- let num = try_convert_number!(signed, self.cache, "16");
- visitor.visit_i16(num)
- }
-
- #[inline]
- fn deserialize_i32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- let num = try_convert_number!(signed, self.cache, "32");
- visitor.visit_i32(num)
- }
-
- #[inline]
- fn deserialize_i64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- let num = try_convert_number!(signed, self.cache, "64");
- visitor.visit_i64(num)
- }
-
- #[inline]
- fn deserialize_u8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- let num = try_convert_number!(unsigned, self.cache, "8");
- visitor.visit_u8(num)
- }
-
- #[inline]
- fn deserialize_u16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- let num = try_convert_number!(unsigned, self.cache, "16");
- visitor.visit_u16(num)
- }
-
- #[inline]
- fn deserialize_u32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- let num = try_convert_number!(unsigned, self.cache, "32");
- visitor.visit_u32(num)
- }
-
- #[inline]
- fn deserialize_u64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- let num = try_convert_number!(unsigned, self.cache, "64");
- visitor.visit_u64(num)
- }
-
- #[inline]
- fn deserialize_f32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- visitor.visit_f32(self.cache.into_float()? as f32)
- }
-
- #[inline]
- fn deserialize_f64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- visitor.visit_f64(self.cache.into_float()?)
- }
-
- #[inline]
- fn deserialize_str<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- visitor.visit_string(self.cache.into_string()?)
- }
-
- #[inline]
- fn deserialize_string<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
- visitor.visit_string(self.cache.into_string()?)
- }
-
- #[inline]
- fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
- where
- V: de::Visitor<'de>,
- {
- // Match an explicit nil as None and everything else as Some
- match self.cache.kind {
- ValueKind::Nil => visitor.visit_none(),
- _ => visitor.visit_some(self),
- }
- }
-
- fn deserialize_enum<V>(
- self,
- name: &'static str,
- variants: &'static [&'static str],
- visitor: V,
- ) -> Result<V::Value>
- where
- V: de::Visitor<'de>,
- {
- visitor.visit_enum(EnumAccess {
- value: self.cache,
- name,
- variants,
- })
- }
+impl<'de> de::Deserializer<'de> for Config {
+ type Error = ConfigError;
- serde::forward_to_deserialize_any! {
- char seq
- bytes byte_buf map struct unit newtype_struct
- identifier ignored_any unit_struct tuple_struct tuple
+ config_deserialize_via_value! {
+ deserialize_any;
+ deserialize_bool;
+ deserialize_i8;
+ deserialize_i16;
+ deserialize_i32;
+ deserialize_i64;
+ deserialize_u8;
+ deserialize_u16;
+ deserialize_u32;
+ deserialize_u64;
+ deserialize_f32;
+ deserialize_f64;
+ deserialize_str;
+ deserialize_string;
+ deserialize_option;
+
+ deserialize_char;
+ deserialize_seq;
+ deserialize_bytes;
+ deserialize_byte_buf;
+ deserialize_map;
+ deserialize_unit;
+ deserialize_identifier;
+ deserialize_ignored_any;
+
+ deserialize_enum(name: &'static str, variants: &'static [&'static str]);
+ deserialize_unit_struct(name: &'static str);
+ deserialize_newtype_struct(name: &'static str);
+ deserialize_tuple(n: usize);
+ deserialize_tuple_struct(name: &'static str, n: usize);
+ deserialize_struct(name: &'static str, fields: &'static [&'static str]);
}
}
diff --git a/tests/errors.rs b/tests/errors.rs
index 54cb93a..1c3204c 100644
--- a/tests/errors.rs
+++ b/tests/errors.rs
@@ -45,6 +45,28 @@ fn test_error_type() {
}
#[test]
+fn test_error_deser_whole() {
+ #[derive(Deserialize, Debug)]
+ struct Place {
+ #[allow(dead_code)]
+ name: usize, // is actually s string
+ }
+
+ #[derive(Deserialize, Debug)]
+ struct Output {
+ #[allow(dead_code)]
+ place: Place,
+ }
+
+ let c = make();
+ let err = c.try_deserialize::<Output>().unwrap_err().to_string();
+ assert_eq!(
+ err,
+ "invalid type: string \"Torre di Pisa\", expected an integer for key `place.name` in tests/Settings.toml",
+ );
+}
+
+#[test]
fn test_error_type_detached() {
let c = make();