Merge pull request #504 from serde-rs/key

Allow map key to be borrowed from &Value
diff --git a/src/value/de.rs b/src/value/de.rs
index b0e0cb8..f70589b 100644
--- a/src/value/de.rs
+++ b/src/value/de.rs
@@ -1253,7 +1253,7 @@
     where
         V: Visitor<'de>,
     {
-        self.key.into_deserializer().deserialize_any(visitor)
+        BorrowedCowStrDeserializer::new(self.key).deserialize_any(visitor)
     }
 
     deserialize_integer_key!(deserialize_i8 => visit_i8);
@@ -1387,3 +1387,102 @@
         }
     }
 }
+
+struct BorrowedCowStrDeserializer<'de> {
+    value: Cow<'de, str>,
+}
+
+impl<'de> BorrowedCowStrDeserializer<'de> {
+    fn new(value: Cow<'de, str>) -> Self {
+        BorrowedCowStrDeserializer { value: value }
+    }
+}
+
+impl<'de> de::Deserializer<'de> for BorrowedCowStrDeserializer<'de> {
+    type Error = Error;
+
+    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+    where
+        V: de::Visitor<'de>,
+    {
+        match self.value {
+            Cow::Borrowed(string) => visitor.visit_borrowed_str(string),
+            Cow::Owned(string) => visitor.visit_string(string),
+        }
+    }
+
+    fn deserialize_enum<V>(
+        self,
+        _name: &str,
+        _variants: &'static [&'static str],
+        visitor: V,
+    ) -> Result<V::Value, Self::Error>
+    where
+        V: de::Visitor<'de>,
+    {
+        visitor.visit_enum(self)
+    }
+
+    forward_to_deserialize_any! {
+        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
+        bytes byte_buf option unit unit_struct newtype_struct seq tuple
+        tuple_struct map struct identifier ignored_any
+    }
+}
+
+impl<'de> de::EnumAccess<'de> for BorrowedCowStrDeserializer<'de> {
+    type Error = Error;
+    type Variant = UnitOnly;
+
+    fn variant_seed<T>(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error>
+    where
+        T: de::DeserializeSeed<'de>,
+    {
+        let value = seed.deserialize(self)?;
+        Ok((value, UnitOnly))
+    }
+}
+
+struct UnitOnly;
+
+impl<'de> de::VariantAccess<'de> for UnitOnly {
+    type Error = Error;
+
+    fn unit_variant(self) -> Result<(), Self::Error> {
+        Ok(())
+    }
+
+    fn newtype_variant_seed<T>(self, _seed: T) -> Result<T::Value, Self::Error>
+    where
+        T: de::DeserializeSeed<'de>,
+    {
+        Err(de::Error::invalid_type(
+            Unexpected::UnitVariant,
+            &"newtype variant",
+        ))
+    }
+
+    fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
+    where
+        V: de::Visitor<'de>,
+    {
+        Err(de::Error::invalid_type(
+            Unexpected::UnitVariant,
+            &"tuple variant",
+        ))
+    }
+
+    fn struct_variant<V>(
+        self,
+        _fields: &'static [&'static str],
+        _visitor: V,
+    ) -> Result<V::Value, Self::Error>
+    where
+        V: de::Visitor<'de>,
+    {
+        Err(de::Error::invalid_type(
+            Unexpected::UnitVariant,
+            &"struct variant",
+        ))
+    }
+}
diff --git a/tests/test.rs b/tests/test.rs
index 88f89c7..97da813 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -2132,3 +2132,28 @@
     let array_to_string = serde_json::to_string(&array_from_str).unwrap();
     assert_eq!(r#"["a",42,{"foo": "bar"},null]"#, array_to_string);
 }
+
+#[test]
+fn test_borrow_in_map_key() {
+    #[derive(Deserialize, Debug)]
+    struct Outer {
+        map: BTreeMap<MyMapKey, ()>,
+    }
+
+    #[derive(Ord, PartialOrd, Eq, PartialEq, Debug)]
+    struct MyMapKey(usize);
+
+    impl<'de> Deserialize<'de> for MyMapKey {
+        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+        where
+            D: de::Deserializer<'de>,
+        {
+            let s = <&str>::deserialize(deserializer)?;
+            let n = s.parse().map_err(de::Error::custom)?;
+            Ok(MyMapKey(n))
+        }
+    }
+
+    let value = json!({ "map": { "1": null } });
+    Outer::deserialize(&value).unwrap();
+}