Compare commits

...

3 Commits

Author SHA1 Message Date
David Tolnay c68b959696 Release 1.0.4 2017-05-10 20:05:22 -07:00
David Tolnay eab80172e4 Merge pull request #926 from serde-rs/borrow
Support borrowing within internally tagged enum
2017-05-10 20:04:36 -07:00
David Tolnay c1259fbc87 Support borrowing within internally tagged enum 2017-05-10 19:56:05 -07:00
8 changed files with 201 additions and 119 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde" name = "serde"
version = "1.0.3" # remember to update html_root_url version = "1.0.4" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework" description = "A generic serialization/deserialization framework"
+1 -1
View File
@@ -79,7 +79,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here. // Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.3")] #![doc(html_root_url = "https://docs.rs/serde/1.0.4")]
// Support using Serde without the standard library! // Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
+171 -113
View File
@@ -233,7 +233,7 @@ mod content {
/// ///
/// Not public API. Use serde-value instead. /// Not public API. Use serde-value instead.
#[derive(Debug)] #[derive(Debug)]
pub enum Content { pub enum Content<'de> {
Bool(bool), Bool(bool),
U8(u8), U8(u8),
@@ -251,18 +251,20 @@ mod content {
Char(char), Char(char),
String(String), String(String),
Bytes(Vec<u8>), Str(&'de str),
ByteBuf(Vec<u8>),
Bytes(&'de [u8]),
None, None,
Some(Box<Content>), Some(Box<Content<'de>>),
Unit, Unit,
Newtype(Box<Content>), Newtype(Box<Content<'de>>),
Seq(Vec<Content>), Seq(Vec<Content<'de>>),
Map(Vec<(Content, Content)>), Map(Vec<(Content<'de>, Content<'de>)>),
} }
impl Content { impl<'de> Content<'de> {
fn unexpected(&self) -> Unexpected { fn unexpected(&self) -> Unexpected {
match *self { match *self {
Content::Bool(b) => Unexpected::Bool(b), Content::Bool(b) => Unexpected::Bool(b),
@@ -278,7 +280,9 @@ mod content {
Content::F64(f) => Unexpected::Float(f), Content::F64(f) => Unexpected::Float(f),
Content::Char(c) => Unexpected::Char(c), Content::Char(c) => Unexpected::Char(c),
Content::String(ref s) => Unexpected::Str(s), Content::String(ref s) => Unexpected::Str(s),
Content::Bytes(ref b) => Unexpected::Bytes(b), Content::Str(s) => Unexpected::Str(s),
Content::ByteBuf(ref b) => Unexpected::Bytes(b),
Content::Bytes(b) => Unexpected::Bytes(b),
Content::None | Content::Some(_) => Unexpected::Option, Content::None | Content::Some(_) => Unexpected::Option,
Content::Unit => Unexpected::Unit, Content::Unit => Unexpected::Unit,
Content::Newtype(_) => Unexpected::NewtypeStruct, Content::Newtype(_) => Unexpected::NewtypeStruct,
@@ -288,21 +292,30 @@ mod content {
} }
} }
impl<'de> Deserialize<'de> for Content { impl<'de> Deserialize<'de> for Content<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
// Untagged and internally tagged enums are only supported in // Untagged and internally tagged enums are only supported in
// self-describing formats. // self-describing formats.
deserializer.deserialize_any(ContentVisitor) let visitor = ContentVisitor { value: PhantomData };
deserializer.deserialize_any(visitor)
} }
} }
struct ContentVisitor; struct ContentVisitor<'de> {
value: PhantomData<Content<'de>>,
}
impl<'de> Visitor<'de> for ContentVisitor { impl<'de> ContentVisitor<'de> {
type Value = Content; fn new() -> Self {
ContentVisitor { value: PhantomData }
}
}
impl<'de> Visitor<'de> for ContentVisitor<'de> {
type Value = Content<'de>;
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str("any value") fmt.write_str("any value")
@@ -399,6 +412,13 @@ mod content {
Ok(Content::String(value.into())) Ok(Content::String(value.into()))
} }
fn visit_borrowed_str<F>(self, value: &'de str) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::Str(value))
}
fn visit_string<F>(self, value: String) -> Result<Self::Value, F> fn visit_string<F>(self, value: String) -> Result<Self::Value, F>
where where
F: de::Error, F: de::Error,
@@ -410,14 +430,21 @@ mod content {
where where
F: de::Error, F: de::Error,
{ {
Ok(Content::Bytes(value.into())) Ok(Content::ByteBuf(value.into()))
}
fn visit_borrowed_bytes<F>(self, value: &'de [u8]) -> Result<Self::Value, F>
where
F: de::Error,
{
Ok(Content::Bytes(value))
} }
fn visit_byte_buf<F>(self, value: Vec<u8>) -> Result<Self::Value, F> fn visit_byte_buf<F>(self, value: Vec<u8>) -> Result<Self::Value, F>
where where
F: de::Error, F: de::Error,
{ {
Ok(Content::Bytes(value)) Ok(Content::ByteBuf(value))
} }
fn visit_unit<F>(self) -> Result<Self::Value, F> fn visit_unit<F>(self) -> Result<Self::Value, F>
@@ -481,23 +508,24 @@ mod content {
/// This is the type of the map keys in an internally tagged enum. /// This is the type of the map keys in an internally tagged enum.
/// ///
/// Not public API. /// Not public API.
pub enum TagOrContent { pub enum TagOrContent<'de> {
Tag, Tag,
Content(Content), Content(Content<'de>),
} }
struct TagOrContentVisitor { struct TagOrContentVisitor<'de> {
name: &'static str, name: &'static str,
value: PhantomData<TagOrContent<'de>>,
} }
impl TagOrContentVisitor { impl<'de> TagOrContentVisitor<'de> {
fn new(name: &'static str) -> Self { fn new(name: &'static str) -> Self {
TagOrContentVisitor { name: name } TagOrContentVisitor { name: name, value: PhantomData }
} }
} }
impl<'de> DeserializeSeed<'de> for TagOrContentVisitor { impl<'de> DeserializeSeed<'de> for TagOrContentVisitor<'de> {
type Value = TagOrContent; type Value = TagOrContent<'de>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where where
@@ -509,8 +537,8 @@ mod content {
} }
} }
impl<'de> Visitor<'de> for TagOrContentVisitor { impl<'de> Visitor<'de> for TagOrContentVisitor<'de> {
type Value = TagOrContent; type Value = TagOrContent<'de>;
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "a type tag `{}` or any other value", self.name) write!(fmt, "a type tag `{}` or any other value", self.name)
@@ -520,7 +548,7 @@ mod content {
where where
F: de::Error, F: de::Error,
{ {
ContentVisitor ContentVisitor::new()
.visit_bool(value) .visit_bool(value)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -529,14 +557,14 @@ mod content {
where where
F: de::Error, F: de::Error,
{ {
ContentVisitor.visit_i8(value).map(TagOrContent::Content) ContentVisitor::new().visit_i8(value).map(TagOrContent::Content)
} }
fn visit_i16<F>(self, value: i16) -> Result<Self::Value, F> fn visit_i16<F>(self, value: i16) -> Result<Self::Value, F>
where where
F: de::Error, F: de::Error,
{ {
ContentVisitor ContentVisitor::new()
.visit_i16(value) .visit_i16(value)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -545,7 +573,7 @@ mod content {
where where
F: de::Error, F: de::Error,
{ {
ContentVisitor ContentVisitor::new()
.visit_i32(value) .visit_i32(value)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -554,7 +582,7 @@ mod content {
where where
F: de::Error, F: de::Error,
{ {
ContentVisitor ContentVisitor::new()
.visit_i64(value) .visit_i64(value)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -563,14 +591,14 @@ mod content {
where where
F: de::Error, F: de::Error,
{ {
ContentVisitor.visit_u8(value).map(TagOrContent::Content) ContentVisitor::new().visit_u8(value).map(TagOrContent::Content)
} }
fn visit_u16<F>(self, value: u16) -> Result<Self::Value, F> fn visit_u16<F>(self, value: u16) -> Result<Self::Value, F>
where where
F: de::Error, F: de::Error,
{ {
ContentVisitor ContentVisitor::new()
.visit_u16(value) .visit_u16(value)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -579,7 +607,7 @@ mod content {
where where
F: de::Error, F: de::Error,
{ {
ContentVisitor ContentVisitor::new()
.visit_u32(value) .visit_u32(value)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -588,7 +616,7 @@ mod content {
where where
F: de::Error, F: de::Error,
{ {
ContentVisitor ContentVisitor::new()
.visit_u64(value) .visit_u64(value)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -597,7 +625,7 @@ mod content {
where where
F: de::Error, F: de::Error,
{ {
ContentVisitor ContentVisitor::new()
.visit_f32(value) .visit_f32(value)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -606,7 +634,7 @@ mod content {
where where
F: de::Error, F: de::Error,
{ {
ContentVisitor ContentVisitor::new()
.visit_f64(value) .visit_f64(value)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -615,7 +643,7 @@ mod content {
where where
F: de::Error, F: de::Error,
{ {
ContentVisitor ContentVisitor::new()
.visit_char(value) .visit_char(value)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -627,12 +655,25 @@ mod content {
if value == self.name { if value == self.name {
Ok(TagOrContent::Tag) Ok(TagOrContent::Tag)
} else { } else {
ContentVisitor ContentVisitor::new()
.visit_str(value) .visit_str(value)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
} }
fn visit_borrowed_str<F>(self, value: &'de str) -> Result<Self::Value, F>
where
F: de::Error,
{
if value == self.name {
Ok(TagOrContent::Tag)
} else {
ContentVisitor::new()
.visit_borrowed_str(value)
.map(TagOrContent::Content)
}
}
fn visit_string<F>(self, value: String) -> Result<Self::Value, F> fn visit_string<F>(self, value: String) -> Result<Self::Value, F>
where where
F: de::Error, F: de::Error,
@@ -640,7 +681,7 @@ mod content {
if value == self.name { if value == self.name {
Ok(TagOrContent::Tag) Ok(TagOrContent::Tag)
} else { } else {
ContentVisitor ContentVisitor::new()
.visit_string(value) .visit_string(value)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -653,12 +694,25 @@ mod content {
if value == self.name.as_bytes() { if value == self.name.as_bytes() {
Ok(TagOrContent::Tag) Ok(TagOrContent::Tag)
} else { } else {
ContentVisitor ContentVisitor::new()
.visit_bytes(value) .visit_bytes(value)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
} }
fn visit_borrowed_bytes<F>(self, value: &'de [u8]) -> Result<Self::Value, F>
where
F: de::Error,
{
if value == self.name.as_bytes() {
Ok(TagOrContent::Tag)
} else {
ContentVisitor::new()
.visit_borrowed_bytes(value)
.map(TagOrContent::Content)
}
}
fn visit_byte_buf<F>(self, value: Vec<u8>) -> Result<Self::Value, F> fn visit_byte_buf<F>(self, value: Vec<u8>) -> Result<Self::Value, F>
where where
F: de::Error, F: de::Error,
@@ -666,7 +720,7 @@ mod content {
if value == self.name.as_bytes() { if value == self.name.as_bytes() {
Ok(TagOrContent::Tag) Ok(TagOrContent::Tag)
} else { } else {
ContentVisitor ContentVisitor::new()
.visit_byte_buf(value) .visit_byte_buf(value)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -676,21 +730,21 @@ mod content {
where where
F: de::Error, F: de::Error,
{ {
ContentVisitor.visit_unit().map(TagOrContent::Content) ContentVisitor::new().visit_unit().map(TagOrContent::Content)
} }
fn visit_none<F>(self) -> Result<Self::Value, F> fn visit_none<F>(self) -> Result<Self::Value, F>
where where
F: de::Error, F: de::Error,
{ {
ContentVisitor.visit_none().map(TagOrContent::Content) ContentVisitor::new().visit_none().map(TagOrContent::Content)
} }
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error> fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
ContentVisitor ContentVisitor::new()
.visit_some(deserializer) .visit_some(deserializer)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -699,7 +753,7 @@ mod content {
where where
D: Deserializer<'de>, D: Deserializer<'de>,
{ {
ContentVisitor ContentVisitor::new()
.visit_newtype_struct(deserializer) .visit_newtype_struct(deserializer)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -708,7 +762,7 @@ mod content {
where where
V: SeqAccess<'de>, V: SeqAccess<'de>,
{ {
ContentVisitor ContentVisitor::new()
.visit_seq(visitor) .visit_seq(visitor)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -717,7 +771,7 @@ mod content {
where where
V: MapAccess<'de>, V: MapAccess<'de>,
{ {
ContentVisitor ContentVisitor::new()
.visit_map(visitor) .visit_map(visitor)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -726,7 +780,7 @@ mod content {
where where
V: EnumAccess<'de>, V: EnumAccess<'de>,
{ {
ContentVisitor ContentVisitor::new()
.visit_enum(visitor) .visit_enum(visitor)
.map(TagOrContent::Content) .map(TagOrContent::Content)
} }
@@ -735,33 +789,33 @@ mod content {
/// Used by generated code to deserialize an internally tagged enum. /// Used by generated code to deserialize an internally tagged enum.
/// ///
/// Not public API. /// Not public API.
pub struct TaggedContent<T> { pub struct TaggedContent<'de, T> {
pub tag: T, pub tag: T,
pub content: Content, pub content: Content<'de>,
} }
/// Not public API. /// Not public API.
pub struct TaggedContentVisitor<T> { pub struct TaggedContentVisitor<'de, T> {
tag_name: &'static str, tag_name: &'static str,
tag: PhantomData<T>, value: PhantomData<TaggedContent<'de, T>>,
} }
impl<T> TaggedContentVisitor<T> { impl<'de, T> TaggedContentVisitor<'de, T> {
/// Visitor for the content of an internally tagged enum with the given tag /// Visitor for the content of an internally tagged enum with the given tag
/// name. /// name.
pub fn new(name: &'static str) -> Self { pub fn new(name: &'static str) -> Self {
TaggedContentVisitor { TaggedContentVisitor {
tag_name: name, tag_name: name,
tag: PhantomData, value: PhantomData,
} }
} }
} }
impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor<T> impl<'de, T> DeserializeSeed<'de> for TaggedContentVisitor<'de, T>
where where
T: Deserialize<'de>, T: Deserialize<'de>,
{ {
type Value = TaggedContent<T>; type Value = TaggedContent<'de, T>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error> fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where where
@@ -773,11 +827,11 @@ mod content {
} }
} }
impl<'de, T> Visitor<'de> for TaggedContentVisitor<T> impl<'de, T> Visitor<'de> for TaggedContentVisitor<'de, T>
where where
T: Deserialize<'de>, T: Deserialize<'de>,
{ {
type Value = TaggedContent<T>; type Value = TaggedContent<'de, T>;
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str("any value") fmt.write_str("any value")
@@ -913,14 +967,14 @@ mod content {
} }
/// Not public API /// Not public API
pub struct ContentDeserializer<E> { pub struct ContentDeserializer<'de, E> {
content: Content, content: Content<'de>,
err: PhantomData<E>, err: PhantomData<E>,
} }
/// Used when deserializing an internally tagged enum because the content will /// Used when deserializing an internally tagged enum because the content will
/// be used exactly once. /// be used exactly once.
impl<'de, E> Deserializer<'de> for ContentDeserializer<E> impl<'de, E> Deserializer<'de> for ContentDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
{ {
@@ -944,6 +998,9 @@ mod content {
Content::F64(v) => visitor.visit_f64(v), Content::F64(v) => visitor.visit_f64(v),
Content::Char(v) => visitor.visit_char(v), Content::Char(v) => visitor.visit_char(v),
Content::String(v) => visitor.visit_string(v), Content::String(v) => visitor.visit_string(v),
Content::Str(v) => visitor.visit_borrowed_str(v),
Content::ByteBuf(v) => visitor.visit_byte_buf(v),
Content::Bytes(v) => visitor.visit_borrowed_bytes(v),
Content::Unit => visitor.visit_unit(), Content::Unit => visitor.visit_unit(),
Content::None => visitor.visit_none(), Content::None => visitor.visit_none(),
Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)), Content::Some(v) => visitor.visit_some(ContentDeserializer::new(*v)),
@@ -965,7 +1022,6 @@ mod content {
try!(map_visitor.end()); try!(map_visitor.end());
Ok(value) Ok(value)
} }
Content::Bytes(v) => visitor.visit_byte_buf(v),
} }
} }
@@ -1048,9 +1104,9 @@ mod content {
} }
} }
impl<E> ContentDeserializer<E> { impl<'de, E> ContentDeserializer<'de, E> {
/// private API, don't use /// private API, don't use
pub fn new(content: Content) -> Self { pub fn new(content: Content<'de>) -> Self {
ContentDeserializer { ContentDeserializer {
content: content, content: content,
err: PhantomData, err: PhantomData,
@@ -1058,21 +1114,21 @@ mod content {
} }
} }
struct EnumDeserializer<E> struct EnumDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
{ {
variant: Content, variant: Content<'de>,
value: Option<Content>, value: Option<Content<'de>>,
err: PhantomData<E>, err: PhantomData<E>,
} }
impl<'de, E> de::EnumAccess<'de> for EnumDeserializer<E> impl<'de, E> de::EnumAccess<'de> for EnumDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
{ {
type Error = E; type Error = E;
type Variant = VariantDeserializer<Self::Error>; type Variant = VariantDeserializer<'de, Self::Error>;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), E> fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), E>
where where
@@ -1087,15 +1143,15 @@ mod content {
} }
} }
struct VariantDeserializer<E> struct VariantDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
{ {
value: Option<Content>, value: Option<Content<'de>>,
err: PhantomData<E>, err: PhantomData<E>,
} }
impl<'de, E> de::VariantAccess<'de> for VariantDeserializer<E> impl<'de, E> de::VariantAccess<'de> for VariantDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
{ {
@@ -1151,19 +1207,19 @@ mod content {
} }
} }
struct SeqDeserializer<E> struct SeqDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
{ {
iter: <Vec<Content> as IntoIterator>::IntoIter, iter: <Vec<Content<'de>> as IntoIterator>::IntoIter,
err: PhantomData<E>, err: PhantomData<E>,
} }
impl<E> SeqDeserializer<E> impl<'de, E> SeqDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
{ {
fn new(vec: Vec<Content>) -> Self { fn new(vec: Vec<Content<'de>>) -> Self {
SeqDeserializer { SeqDeserializer {
iter: vec.into_iter(), iter: vec.into_iter(),
err: PhantomData, err: PhantomData,
@@ -1171,7 +1227,7 @@ mod content {
} }
} }
impl<'de, E> de::Deserializer<'de> for SeqDeserializer<E> impl<'de, E> de::Deserializer<'de> for SeqDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
{ {
@@ -1203,7 +1259,7 @@ mod content {
} }
} }
impl<'de, E> de::SeqAccess<'de> for SeqDeserializer<E> impl<'de, E> de::SeqAccess<'de> for SeqDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
{ {
@@ -1227,20 +1283,20 @@ mod content {
} }
} }
struct MapDeserializer<E> struct MapDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
{ {
iter: <Vec<(Content, Content)> as IntoIterator>::IntoIter, iter: <Vec<(Content<'de>, Content<'de>)> as IntoIterator>::IntoIter,
value: Option<Content>, value: Option<Content<'de>>,
err: PhantomData<E>, err: PhantomData<E>,
} }
impl<E> MapDeserializer<E> impl<'de, E> MapDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
{ {
fn new(map: Vec<(Content, Content)>) -> Self { fn new(map: Vec<(Content<'de>, Content<'de>)>) -> Self {
MapDeserializer { MapDeserializer {
iter: map.into_iter(), iter: map.into_iter(),
value: None, value: None,
@@ -1249,7 +1305,7 @@ mod content {
} }
} }
impl<'de, E> de::MapAccess<'de> for MapDeserializer<E> impl<'de, E> de::MapAccess<'de> for MapDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
{ {
@@ -1283,7 +1339,7 @@ mod content {
} }
} }
impl<'de, E> de::Deserializer<'de> for MapDeserializer<E> impl<'de, E> de::Deserializer<'de> for MapDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
{ {
@@ -1305,14 +1361,14 @@ mod content {
} }
/// Not public API. /// Not public API.
pub struct ContentRefDeserializer<'a, E> { pub struct ContentRefDeserializer<'a, 'de: 'a, E> {
content: &'a Content, content: &'a Content<'de>,
err: PhantomData<E>, err: PhantomData<E>,
} }
/// Used when deserializing an untagged enum because the content may need to be /// Used when deserializing an untagged enum because the content may need to be
/// used more than once. /// used more than once.
impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, E> impl<'de, 'a, E> Deserializer<'de> for ContentRefDeserializer<'a, 'de, E>
where where
E: de::Error, E: de::Error,
{ {
@@ -1336,6 +1392,9 @@ mod content {
Content::F64(v) => visitor.visit_f64(v), Content::F64(v) => visitor.visit_f64(v),
Content::Char(v) => visitor.visit_char(v), Content::Char(v) => visitor.visit_char(v),
Content::String(ref v) => visitor.visit_str(v), Content::String(ref v) => visitor.visit_str(v),
Content::Str(v) => visitor.visit_borrowed_str(v),
Content::ByteBuf(ref v) => visitor.visit_bytes(v),
Content::Bytes(v) => visitor.visit_borrowed_bytes(v),
Content::Unit => visitor.visit_unit(), Content::Unit => visitor.visit_unit(),
Content::None => visitor.visit_none(), Content::None => visitor.visit_none(),
Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)), Content::Some(ref v) => visitor.visit_some(ContentRefDeserializer::new(v)),
@@ -1361,7 +1420,6 @@ mod content {
try!(map_visitor.end()); try!(map_visitor.end());
Ok(value) Ok(value)
} }
Content::Bytes(ref v) => visitor.visit_bytes(v),
} }
} }
@@ -1440,9 +1498,9 @@ mod content {
} }
} }
impl<'a, E> ContentRefDeserializer<'a, E> { impl<'a, 'de, E> ContentRefDeserializer<'a, 'de, E> {
/// private API, don't use /// private API, don't use
pub fn new(content: &'a Content) -> Self { pub fn new(content: &'a Content<'de>) -> Self {
ContentRefDeserializer { ContentRefDeserializer {
content: content, content: content,
err: PhantomData, err: PhantomData,
@@ -1450,21 +1508,21 @@ mod content {
} }
} }
struct EnumRefDeserializer<'a, E> struct EnumRefDeserializer<'a, 'de: 'a, E>
where where
E: de::Error, E: de::Error,
{ {
variant: &'a Content, variant: &'a Content<'de>,
value: Option<&'a Content>, value: Option<&'a Content<'de>>,
err: PhantomData<E>, err: PhantomData<E>,
} }
impl<'de, 'a, E> de::EnumAccess<'de> for EnumRefDeserializer<'a, E> impl<'de, 'a, E> de::EnumAccess<'de> for EnumRefDeserializer<'a, 'de, E>
where where
E: de::Error, E: de::Error,
{ {
type Error = E; type Error = E;
type Variant = VariantRefDeserializer<'a, Self::Error>; type Variant = VariantRefDeserializer<'a, 'de, Self::Error>;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where where
@@ -1479,15 +1537,15 @@ mod content {
} }
} }
struct VariantRefDeserializer<'a, E> struct VariantRefDeserializer<'a, 'de: 'a, E>
where where
E: de::Error, E: de::Error,
{ {
value: Option<&'a Content>, value: Option<&'a Content<'de>>,
err: PhantomData<E>, err: PhantomData<E>,
} }
impl<'de, 'a, E> de::VariantAccess<'de> for VariantRefDeserializer<'a, E> impl<'de, 'a, E> de::VariantAccess<'de> for VariantRefDeserializer<'a, 'de, E>
where where
E: de::Error, E: de::Error,
{ {
@@ -1543,19 +1601,19 @@ mod content {
} }
} }
struct SeqRefDeserializer<'a, E> struct SeqRefDeserializer<'a, 'de: 'a, E>
where where
E: de::Error, E: de::Error,
{ {
iter: <&'a [Content] as IntoIterator>::IntoIter, iter: <&'a [Content<'de>] as IntoIterator>::IntoIter,
err: PhantomData<E>, err: PhantomData<E>,
} }
impl<'a, E> SeqRefDeserializer<'a, E> impl<'a, 'de, E> SeqRefDeserializer<'a, 'de, E>
where where
E: de::Error, E: de::Error,
{ {
fn new(vec: &'a [Content]) -> Self { fn new(vec: &'a [Content<'de>]) -> Self {
SeqRefDeserializer { SeqRefDeserializer {
iter: vec.into_iter(), iter: vec.into_iter(),
err: PhantomData, err: PhantomData,
@@ -1563,7 +1621,7 @@ mod content {
} }
} }
impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, E> impl<'de, 'a, E> de::Deserializer<'de> for SeqRefDeserializer<'a, 'de, E>
where where
E: de::Error, E: de::Error,
{ {
@@ -1595,7 +1653,7 @@ mod content {
} }
} }
impl<'de, 'a, E> de::SeqAccess<'de> for SeqRefDeserializer<'a, E> impl<'de, 'a, E> de::SeqAccess<'de> for SeqRefDeserializer<'a, 'de, E>
where where
E: de::Error, E: de::Error,
{ {
@@ -1619,20 +1677,20 @@ mod content {
} }
} }
struct MapRefDeserializer<'a, E> struct MapRefDeserializer<'a, 'de: 'a, E>
where where
E: de::Error, E: de::Error,
{ {
iter: <&'a [(Content, Content)] as IntoIterator>::IntoIter, iter: <&'a [(Content<'de>, Content<'de>)] as IntoIterator>::IntoIter,
value: Option<&'a Content>, value: Option<&'a Content<'de>>,
err: PhantomData<E>, err: PhantomData<E>,
} }
impl<'a, E> MapRefDeserializer<'a, E> impl<'a, 'de, E> MapRefDeserializer<'a, 'de, E>
where where
E: de::Error, E: de::Error,
{ {
fn new(map: &'a [(Content, Content)]) -> Self { fn new(map: &'a [(Content<'de>, Content<'de>)]) -> Self {
MapRefDeserializer { MapRefDeserializer {
iter: map.into_iter(), iter: map.into_iter(),
value: None, value: None,
@@ -1641,7 +1699,7 @@ mod content {
} }
} }
impl<'de, 'a, E> de::MapAccess<'de> for MapRefDeserializer<'a, E> impl<'de, 'a, E> de::MapAccess<'de> for MapRefDeserializer<'a, 'de, E>
where where
E: de::Error, E: de::Error,
{ {
@@ -1676,7 +1734,7 @@ mod content {
} }
} }
impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, E> impl<'de, 'a, E> de::Deserializer<'de> for MapRefDeserializer<'a, 'de, E>
where where
E: de::Error, E: de::Error,
{ {
@@ -1697,7 +1755,7 @@ mod content {
} }
} }
impl<'de, E> de::IntoDeserializer<'de, E> for ContentDeserializer<E> impl<'de, E> de::IntoDeserializer<'de, E> for ContentDeserializer<'de, E>
where where
E: de::Error, E: de::Error,
{ {
@@ -1708,7 +1766,7 @@ mod content {
} }
} }
impl<'de, 'a, E> de::IntoDeserializer<'de, E> for ContentRefDeserializer<'a, E> impl<'de, 'a, E> de::IntoDeserializer<'de, E> for ContentRefDeserializer<'a, 'de, E>
where where
E: de::Error, E: de::Error,
{ {
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_derive" name = "serde_derive"
version = "1.0.3" # remember to update html_root_url version = "1.0.4" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
+1 -1
View File
@@ -16,7 +16,7 @@
//! //!
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html //! [https://serde.rs/derive.html]: https://serde.rs/derive.html
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.3")] #![doc(html_root_url = "https://docs.rs/serde_derive/1.0.4")]
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] #![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))] #![cfg_attr(feature = "cargo-clippy", allow(used_underscore_binding))]
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "serde_test" name = "serde_test"
version = "1.0.3" # remember to update html_root_url version = "1.0.4" # remember to update html_root_url
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"] authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations" description = "Token De/Serializer for testing De/Serialize implementations"
+1 -1
View File
@@ -155,7 +155,7 @@
//! # } //! # }
//! ``` //! ```
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.3")] #![doc(html_root_url = "https://docs.rs/serde_test/1.0.4")]
#[macro_use] #[macro_use]
extern crate serde; extern crate serde;
+24
View File
@@ -695,6 +695,30 @@ fn test_internally_tagged_enum() {
); );
} }
#[test]
fn test_internally_tagged_borrow() {
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum Input<'a> {
Package { name: &'a str },
}
assert_tokens(
&Input::Package { name: "borrowed" },
&[
Token::Struct { name: "Input", len: 2 },
Token::BorrowedStr("type"),
Token::BorrowedStr("Package"),
Token::BorrowedStr("name"),
Token::BorrowedStr("borrowed"),
Token::StructEnd,
],
);
}
#[test] #[test]
fn test_adjacently_tagged_enum() { fn test_adjacently_tagged_enum() {
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Debug, PartialEq, Serialize, Deserialize)]