Allow borrow for field identifiers
This commit is contained in:
parent
9e1f573f88
commit
7a7a182ab6
@ -1,7 +1,7 @@
|
|||||||
use lib::*;
|
use lib::*;
|
||||||
|
|
||||||
use de::{Deserialize, DeserializeSeed, Deserializer, Error, IntoDeserializer, Visitor};
|
use de::{Deserialize, DeserializeSeed, Deserializer, Error, IntoDeserializer, Visitor};
|
||||||
use de::value::BytesDeserializer;
|
use de::value::{BytesDeserializer, BorrowedBytesDeserializer};
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
use de::{MapAccess, Unexpected};
|
use de::{MapAccess, Unexpected};
|
||||||
@ -2527,20 +2527,26 @@ mod content {
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Like `IntoDeserializer` but also implemented for `&[u8]`. This is used for
|
/// Like `IntoDeserializer` but also implemented for `&[u8]`. This is used for
|
||||||
// the newtype fallthrough case of `field_identifier`.
|
/// the newtype fallthrough case of `field_identifier`.
|
||||||
//
|
///
|
||||||
// #[derive(Deserialize)]
|
/// ```ignore
|
||||||
// #[serde(field_identifier)]
|
/// #[derive(Deserialize)]
|
||||||
// enum F {
|
/// #[serde(field_identifier)]
|
||||||
// A,
|
/// enum F {
|
||||||
// B,
|
/// A,
|
||||||
// Other(String), // deserialized using IdentifierDeserializer
|
/// B,
|
||||||
// }
|
/// Other(String), // deserialized using IdentifierDeserializer
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
pub trait IdentifierDeserializer<'de, E: Error> {
|
pub trait IdentifierDeserializer<'de, E: Error> {
|
||||||
|
/// Deserializer, that refers to data owned by deserializer
|
||||||
type Deserializer: Deserializer<'de, Error = E>;
|
type Deserializer: Deserializer<'de, Error = E>;
|
||||||
|
/// Deserializer, that borrows data from the input
|
||||||
|
type BorrowedDeserializer: Deserializer<'de, Error = E>;
|
||||||
|
|
||||||
fn from(self) -> Self::Deserializer;
|
fn from(self) -> Self::Deserializer;
|
||||||
|
fn borrowed(self) -> Self::BorrowedDeserializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, E> IdentifierDeserializer<'de, E> for u32
|
impl<'de, E> IdentifierDeserializer<'de, E> for u32
|
||||||
@ -2548,23 +2554,34 @@ where
|
|||||||
E: Error,
|
E: Error,
|
||||||
{
|
{
|
||||||
type Deserializer = <u32 as IntoDeserializer<'de, E>>::Deserializer;
|
type Deserializer = <u32 as IntoDeserializer<'de, E>>::Deserializer;
|
||||||
|
type BorrowedDeserializer = <u32 as IntoDeserializer<'de, E>>::Deserializer;
|
||||||
|
|
||||||
fn from(self) -> Self::Deserializer {
|
fn from(self) -> Self::Deserializer {
|
||||||
self.into_deserializer()
|
self.into_deserializer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn borrowed(self) -> Self::BorrowedDeserializer {
|
||||||
|
self.into_deserializer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forward_deserializer!(ref StrDeserializer<'a>(&'a str) => visit_str);
|
forward_deserializer!(ref StrDeserializer<'a>(&'a str) => visit_str);
|
||||||
|
forward_deserializer!(borrowed BorrowedStrDeserializer(&'de str) => visit_borrowed_str);
|
||||||
|
|
||||||
impl<'a, E> IdentifierDeserializer<'a, E> for &'a str
|
impl<'a, E> IdentifierDeserializer<'a, E> for &'a str
|
||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
{
|
{
|
||||||
type Deserializer = StrDeserializer<'a, E>;
|
type Deserializer = StrDeserializer<'a, E>;
|
||||||
|
type BorrowedDeserializer = BorrowedStrDeserializer<'a, E>;
|
||||||
|
|
||||||
fn from(self) -> Self::Deserializer {
|
fn from(self) -> Self::Deserializer {
|
||||||
StrDeserializer::new(self)
|
StrDeserializer::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn borrowed(self) -> Self::BorrowedDeserializer {
|
||||||
|
BorrowedStrDeserializer::new(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, E> IdentifierDeserializer<'a, E> for &'a [u8]
|
impl<'a, E> IdentifierDeserializer<'a, E> for &'a [u8]
|
||||||
@ -2572,10 +2589,15 @@ where
|
|||||||
E: Error,
|
E: Error,
|
||||||
{
|
{
|
||||||
type Deserializer = BytesDeserializer<'a, E>;
|
type Deserializer = BytesDeserializer<'a, E>;
|
||||||
|
type BorrowedDeserializer = BorrowedBytesDeserializer<'a, E>;
|
||||||
|
|
||||||
fn from(self) -> Self::Deserializer {
|
fn from(self) -> Self::Deserializer {
|
||||||
BytesDeserializer::new(self)
|
BytesDeserializer::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn borrowed(self) -> Self::BorrowedDeserializer {
|
||||||
|
BorrowedBytesDeserializer::new(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
|
/// A DeserializeSeed helper for implementing deserialize_in_place Visitors.
|
||||||
|
@ -1886,17 +1886,26 @@ fn deserialize_generated_identifier(
|
|||||||
let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() {
|
let (ignore_variant, fallthrough) = if !is_variant && cattrs.has_flatten() {
|
||||||
let ignore_variant = quote!(__other(_serde::private::de::Content<'de>),);
|
let ignore_variant = quote!(__other(_serde::private::de::Content<'de>),);
|
||||||
let fallthrough = quote!(_serde::export::Ok(__Field::__other(__value)));
|
let fallthrough = quote!(_serde::export::Ok(__Field::__other(__value)));
|
||||||
(Some(ignore_variant), Some(fallthrough))
|
(
|
||||||
|
Some(ignore_variant),
|
||||||
|
Some((fallthrough.clone(), fallthrough))
|
||||||
|
)
|
||||||
} else if let Some(other_idx) = other_idx {
|
} else if let Some(other_idx) = other_idx {
|
||||||
let ignore_variant = fields[other_idx].1.clone();
|
let ignore_variant = fields[other_idx].1.clone();
|
||||||
let fallthrough = quote!(_serde::export::Ok(__Field::#ignore_variant));
|
let fallthrough = quote!(_serde::export::Ok(__Field::#ignore_variant));
|
||||||
(None, Some(fallthrough))
|
(
|
||||||
|
None,
|
||||||
|
Some((fallthrough.clone(), fallthrough))
|
||||||
|
)
|
||||||
} else if is_variant || cattrs.deny_unknown_fields() {
|
} else if is_variant || cattrs.deny_unknown_fields() {
|
||||||
(None, None)
|
(None, None)
|
||||||
} else {
|
} else {
|
||||||
let ignore_variant = quote!(__ignore,);
|
let ignore_variant = quote!(__ignore,);
|
||||||
let fallthrough = quote!(_serde::export::Ok(__Field::__ignore));
|
let fallthrough = quote!(_serde::export::Ok(__Field::__ignore));
|
||||||
(Some(ignore_variant), Some(fallthrough))
|
(
|
||||||
|
Some(ignore_variant),
|
||||||
|
Some((fallthrough.clone(), fallthrough))
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let visitor_impl = Stmts(deserialize_identifier(
|
let visitor_impl = Stmts(deserialize_identifier(
|
||||||
@ -1959,16 +1968,27 @@ fn deserialize_custom_identifier(
|
|||||||
if last.attrs.other() {
|
if last.attrs.other() {
|
||||||
let ordinary = &variants[..variants.len() - 1];
|
let ordinary = &variants[..variants.len() - 1];
|
||||||
let fallthrough = quote!(_serde::export::Ok(#this::#last_ident));
|
let fallthrough = quote!(_serde::export::Ok(#this::#last_ident));
|
||||||
(ordinary, Some(fallthrough))
|
(
|
||||||
|
ordinary,
|
||||||
|
Some((fallthrough.clone(), fallthrough))
|
||||||
|
)
|
||||||
} else if let Style::Newtype = last.style {
|
} else if let Style::Newtype = last.style {
|
||||||
let ordinary = &variants[..variants.len() - 1];
|
let ordinary = &variants[..variants.len() - 1];
|
||||||
let deserializer = quote!(_serde::private::de::IdentifierDeserializer::from(__value));
|
|
||||||
let fallthrough = quote! {
|
let fallthrough = |method| quote! {
|
||||||
_serde::export::Result::map(
|
_serde::export::Result::map(
|
||||||
_serde::Deserialize::deserialize(#deserializer),
|
_serde::Deserialize::deserialize(
|
||||||
|
_serde::private::de::IdentifierDeserializer::#method(__value)
|
||||||
|
),
|
||||||
#this::#last_ident)
|
#this::#last_ident)
|
||||||
};
|
};
|
||||||
(ordinary, Some(fallthrough))
|
(
|
||||||
|
ordinary,
|
||||||
|
Some((
|
||||||
|
fallthrough(quote!(from)),
|
||||||
|
fallthrough(quote!(borrowed)),
|
||||||
|
))
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
(variants, None)
|
(variants, None)
|
||||||
}
|
}
|
||||||
@ -2040,7 +2060,8 @@ fn deserialize_identifier(
|
|||||||
this: &TokenStream,
|
this: &TokenStream,
|
||||||
fields: &[(String, Ident, Vec<String>)],
|
fields: &[(String, Ident, Vec<String>)],
|
||||||
is_variant: bool,
|
is_variant: bool,
|
||||||
fallthrough: Option<TokenStream>,
|
// .0 for referenced data, .1 -- for borrowed
|
||||||
|
fallthrough: Option<(TokenStream, TokenStream)>,
|
||||||
collect_other_fields: bool,
|
collect_other_fields: bool,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
let mut flat_fields = Vec::new();
|
let mut flat_fields = Vec::new();
|
||||||
@ -2048,14 +2069,11 @@ fn deserialize_identifier(
|
|||||||
flat_fields.extend(aliases.iter().map(|alias| (alias, ident)))
|
flat_fields.extend(aliases.iter().map(|alias| (alias, ident)))
|
||||||
}
|
}
|
||||||
|
|
||||||
let field_strs = flat_fields.iter().map(|(name, _)| name);
|
let field_strs: &Vec<_> = &flat_fields.iter().map(|(name, _)| name).collect();
|
||||||
let field_borrowed_strs = flat_fields.iter().map(|(name, _)| name);
|
let field_bytes: &Vec<_> = &flat_fields
|
||||||
let field_bytes = flat_fields
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, _)| Literal::byte_string(name.as_bytes()));
|
.map(|(name, _)| Literal::byte_string(name.as_bytes()))
|
||||||
let field_borrowed_bytes = flat_fields
|
.collect();
|
||||||
.iter()
|
|
||||||
.map(|(name, _)| Literal::byte_string(name.as_bytes()));
|
|
||||||
|
|
||||||
let constructors: &Vec<_> = &flat_fields
|
let constructors: &Vec<_> = &flat_fields
|
||||||
.iter()
|
.iter()
|
||||||
@ -2106,16 +2124,21 @@ fn deserialize_identifier(
|
|||||||
(None, None, None, None)
|
(None, None, None, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
let fallthrough_arm = if let Some(fallthrough) = fallthrough {
|
let (
|
||||||
|
fallthrough_arm,
|
||||||
|
fallthrough_borrowed_arm,
|
||||||
|
) = if let Some(fallthrough) = fallthrough.clone() {
|
||||||
fallthrough
|
fallthrough
|
||||||
} else if is_variant {
|
} else if is_variant {
|
||||||
quote! {
|
let fallthrough = quote! {
|
||||||
_serde::export::Err(_serde::de::Error::unknown_variant(__value, VARIANTS))
|
_serde::export::Err(_serde::de::Error::unknown_variant(__value, VARIANTS))
|
||||||
}
|
};
|
||||||
|
(fallthrough.clone(), fallthrough)
|
||||||
} else {
|
} else {
|
||||||
quote! {
|
let fallthrough = quote! {
|
||||||
_serde::export::Err(_serde::de::Error::unknown_field(__value, FIELDS))
|
_serde::export::Err(_serde::de::Error::unknown_field(__value, FIELDS))
|
||||||
}
|
};
|
||||||
|
(fallthrough.clone(), fallthrough)
|
||||||
};
|
};
|
||||||
|
|
||||||
let variant_indices = 0_u64..;
|
let variant_indices = 0_u64..;
|
||||||
@ -2212,37 +2235,6 @@ fn deserialize_identifier(
|
|||||||
{
|
{
|
||||||
_serde::export::Ok(__Field::__other(_serde::private::de::Content::Unit))
|
_serde::export::Ok(__Field::__other(_serde::private::de::Content::Unit))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::export::Result<Self::Value, __E>
|
|
||||||
where
|
|
||||||
__E: _serde::de::Error,
|
|
||||||
{
|
|
||||||
match __value {
|
|
||||||
#(
|
|
||||||
#field_borrowed_strs => _serde::export::Ok(#constructors),
|
|
||||||
)*
|
|
||||||
_ => {
|
|
||||||
#value_as_borrowed_str_content
|
|
||||||
#fallthrough_arm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_borrowed_bytes<__E>(self, __value: &'de [u8]) -> _serde::export::Result<Self::Value, __E>
|
|
||||||
where
|
|
||||||
__E: _serde::de::Error,
|
|
||||||
{
|
|
||||||
match __value {
|
|
||||||
#(
|
|
||||||
#field_borrowed_bytes => _serde::export::Ok(#constructors),
|
|
||||||
)*
|
|
||||||
_ => {
|
|
||||||
#bytes_to_str
|
|
||||||
#value_as_borrowed_bytes_content
|
|
||||||
#fallthrough_arm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
@ -2285,6 +2277,21 @@ fn deserialize_identifier(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::export::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
match __value {
|
||||||
|
#(
|
||||||
|
#field_strs => _serde::export::Ok(#constructors),
|
||||||
|
)*
|
||||||
|
_ => {
|
||||||
|
#value_as_borrowed_str_content
|
||||||
|
#fallthrough_borrowed_arm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::export::Result<Self::Value, __E>
|
fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::export::Result<Self::Value, __E>
|
||||||
where
|
where
|
||||||
__E: _serde::de::Error,
|
__E: _serde::de::Error,
|
||||||
@ -2300,6 +2307,22 @@ fn deserialize_identifier(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_bytes<__E>(self, __value: &'de [u8]) -> _serde::export::Result<Self::Value, __E>
|
||||||
|
where
|
||||||
|
__E: _serde::de::Error,
|
||||||
|
{
|
||||||
|
match __value {
|
||||||
|
#(
|
||||||
|
#field_bytes => _serde::export::Ok(#constructors),
|
||||||
|
)*
|
||||||
|
_ => {
|
||||||
|
#bytes_to_str
|
||||||
|
#value_as_borrowed_bytes_content
|
||||||
|
#fallthrough_borrowed_arm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +90,37 @@ fn test_struct() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_field_identifier() {
|
||||||
|
#[derive(Deserialize, Debug, PartialEq)]
|
||||||
|
#[serde(field_identifier)]
|
||||||
|
enum FieldStr<'a> {
|
||||||
|
#[serde(borrow)]
|
||||||
|
Str(&'a str),
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&FieldStr::Str("value"),
|
||||||
|
&[
|
||||||
|
Token::BorrowedStr("value"),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, PartialEq)]
|
||||||
|
#[serde(field_identifier)]
|
||||||
|
enum FieldBytes<'a> {
|
||||||
|
#[serde(borrow)]
|
||||||
|
Bytes(&'a [u8]),
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens(
|
||||||
|
&FieldBytes::Bytes(b"value"),
|
||||||
|
&[
|
||||||
|
Token::BorrowedBytes(b"value"),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cow() {
|
fn test_cow() {
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user