Skip to content

Commit

Permalink
Merge pull request #6 from dtolnay/nonstring
Browse files Browse the repository at this point in the history
Support more key types
  • Loading branch information
dtolnay authored Aug 18, 2019
2 parents 1d7a62c + d7f9411 commit 57f9101
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 3 deletions.
30 changes: 27 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -996,7 +996,7 @@ where
}
}

/// Forwarding impl except `visit_str` and `visit_string` which save the string.
/// Forwarding impl that also saves the value of integers and strings.
impl<'a, 'de, X> Visitor<'de> for CaptureKey<'a, X>
where
X: Visitor<'de>,
Expand All @@ -1011,62 +1011,71 @@ where
where
E: de::Error,
{
*self.key = Some(v.to_string());
self.delegate.visit_bool(v)
}

fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
where
E: de::Error,
{
*self.key = Some(v.to_string());
self.delegate.visit_i8(v)
}

fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
where
E: de::Error,
{
*self.key = Some(v.to_string());
self.delegate.visit_i16(v)
}

fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
where
E: de::Error,
{
*self.key = Some(v.to_string());
self.delegate.visit_i32(v)
}

fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: de::Error,
{
*self.key = Some(v.to_string());
self.delegate.visit_i64(v)
}

fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
where
E: de::Error,
{
*self.key = Some(v.to_string());
self.delegate.visit_u8(v)
}

fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
where
E: de::Error,
{
*self.key = Some(v.to_string());
self.delegate.visit_u16(v)
}

fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
where
E: de::Error,
{
*self.key = Some(v.to_string());
self.delegate.visit_u32(v)
}

fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
*self.key = Some(v.to_string());
self.delegate.visit_u64(v)
}

Expand Down Expand Up @@ -1140,7 +1149,7 @@ where
where
D: de::Deserializer<'de>,
{
self.delegate.visit_newtype_struct(deserializer)
self.delegate.visit_newtype_struct(CaptureKey::new(deserializer, self.key))
}

fn visit_seq<V>(self, visitor: V) -> Result<Self::Value, V::Error>
Expand All @@ -1161,7 +1170,7 @@ where
where
V: de::EnumAccess<'de>,
{
self.delegate.visit_enum(visitor)
self.delegate.visit_enum(CaptureKey::new(visitor, self.key))
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
Expand All @@ -1186,6 +1195,21 @@ where
}
}

impl<'a, 'de, X> de::EnumAccess<'de> for CaptureKey<'a, X>
where
X: de::EnumAccess<'de>,
{
type Error = X::Error;
type Variant = X::Variant;

fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), X::Error>
where
V: DeserializeSeed<'de>,
{
self.delegate.variant_seed(CaptureKey::new(seed, self.key))
}
}

/// Seed used for map values, sequence elements and newtype variants to track
/// their path.
struct TrackedSeed<'a, X, F: 'a> {
Expand Down
64 changes: 64 additions & 0 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ where
value
}

#[derive(Debug, Deserialize)]
struct V {
used: (),
}

#[test]
fn test_readme() {
#[derive(Debug, PartialEq, Deserialize)]
Expand Down Expand Up @@ -67,3 +72,62 @@ fn test_readme() {
};
assert_eq!(p, expected);
}

#[test]
fn test_int_key() {
#[derive(Debug, Deserialize)]
struct Test {
a: Map<usize, V>,
}

let json = r#"{
"a": {
"2": {
"used": null,
"unused": null
}
}
}"#;

let ignored = &["a.2.unused"];
assert_ignored::<Test>(json, ignored);
}

#[test]
fn test_newtype_key() {
type Test = Map<Key, V>;

#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Deserialize)]
struct Key(&'static str);

let json = r#"{
"k": {
"used": null,
"unused": null
}
}"#;

let ignored = &["k.unused"];
assert_ignored::<Test>(json, ignored);
}

#[test]
fn test_unit_variant_key() {
type Test = Map<Key, V>;

#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Deserialize)]
enum Key {
First,
Second,
}

let json = r#"{
"First": {
"used": null,
"unused": null
}
}"#;

let ignored = &["First.unused"];
assert_ignored::<Test>(json, ignored);
}

0 comments on commit 57f9101

Please sign in to comment.