Allow to define custom expectation message for type with #[serde(expecting = "...")]
Closes #1883
This commit is contained in:
parent
23c14e5f33
commit
104ad9a7dd
@ -824,15 +824,17 @@ mod content {
|
|||||||
/// Not public API.
|
/// Not public API.
|
||||||
pub struct TaggedContentVisitor<'de, T> {
|
pub struct TaggedContentVisitor<'de, T> {
|
||||||
tag_name: &'static str,
|
tag_name: &'static str,
|
||||||
|
expecting: &'static str,
|
||||||
value: PhantomData<TaggedContent<'de, T>>,
|
value: PhantomData<TaggedContent<'de, T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, T> TaggedContentVisitor<'de, T> {
|
impl<'de, T> TaggedContentVisitor<'de, T> {
|
||||||
/// Visitor for the content of an internally tagged enum with the given
|
/// Visitor for the content of an internally tagged enum with the given
|
||||||
/// tag name.
|
/// tag name.
|
||||||
pub fn new(name: &'static str) -> Self {
|
pub fn new(name: &'static str, expecting: &'static str) -> Self {
|
||||||
TaggedContentVisitor {
|
TaggedContentVisitor {
|
||||||
tag_name: name,
|
tag_name: name,
|
||||||
|
expecting: expecting,
|
||||||
value: PhantomData,
|
value: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -861,7 +863,7 @@ mod content {
|
|||||||
type Value = TaggedContent<'de, 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("internally tagged enum")
|
fmt.write_str(self.expecting)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
|
fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
|
||||||
|
@ -399,6 +399,7 @@ fn deserialize_unit_struct(params: &Parameters, cattrs: &attr::Container) -> Fra
|
|||||||
let type_name = cattrs.name().deserialize_name();
|
let type_name = cattrs.name().deserialize_name();
|
||||||
|
|
||||||
let expecting = format!("unit struct {}", params.type_name());
|
let expecting = format!("unit struct {}", params.type_name());
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
quote_block! {
|
quote_block! {
|
||||||
struct __Visitor;
|
struct __Visitor;
|
||||||
@ -456,6 +457,7 @@ fn deserialize_tuple(
|
|||||||
Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident),
|
Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident),
|
||||||
None => format!("tuple struct {}", params.type_name()),
|
None => format!("tuple struct {}", params.type_name()),
|
||||||
};
|
};
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
let nfields = fields.len();
|
let nfields = fields.len();
|
||||||
|
|
||||||
@ -542,6 +544,7 @@ fn deserialize_tuple_in_place(
|
|||||||
Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident),
|
Some(variant_ident) => format!("tuple variant {}::{}", params.type_name(), variant_ident),
|
||||||
None => format!("tuple struct {}", params.type_name()),
|
None => format!("tuple struct {}", params.type_name()),
|
||||||
};
|
};
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
let nfields = fields.len();
|
let nfields = fields.len();
|
||||||
|
|
||||||
@ -630,6 +633,7 @@ fn deserialize_seq(
|
|||||||
} else {
|
} else {
|
||||||
format!("{} with {} elements", expecting, deserialized_count)
|
format!("{} with {} elements", expecting, deserialized_count)
|
||||||
};
|
};
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
let mut index_in_seq = 0_usize;
|
let mut index_in_seq = 0_usize;
|
||||||
let let_values = vars.clone().zip(fields).map(|(var, field)| {
|
let let_values = vars.clone().zip(fields).map(|(var, field)| {
|
||||||
@ -732,6 +736,7 @@ fn deserialize_seq_in_place(
|
|||||||
} else {
|
} else {
|
||||||
format!("{} with {} elements", expecting, deserialized_count)
|
format!("{} with {} elements", expecting, deserialized_count)
|
||||||
};
|
};
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
let mut index_in_seq = 0usize;
|
let mut index_in_seq = 0usize;
|
||||||
let write_values = fields.iter().map(|field| {
|
let write_values = fields.iter().map(|field| {
|
||||||
@ -907,6 +912,7 @@ fn deserialize_struct(
|
|||||||
Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident),
|
Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident),
|
||||||
None => format!("struct {}", params.type_name()),
|
None => format!("struct {}", params.type_name()),
|
||||||
};
|
};
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
let visit_seq = Stmts(deserialize_seq(
|
let visit_seq = Stmts(deserialize_seq(
|
||||||
&type_path, params, fields, true, cattrs, &expecting,
|
&type_path, params, fields, true, cattrs, &expecting,
|
||||||
@ -1048,6 +1054,7 @@ fn deserialize_struct_in_place(
|
|||||||
Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident),
|
Some(variant_ident) => format!("struct variant {}::{}", params.type_name(), variant_ident),
|
||||||
None => format!("struct {}", params.type_name()),
|
None => format!("struct {}", params.type_name()),
|
||||||
};
|
};
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, &expecting));
|
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, &expecting));
|
||||||
|
|
||||||
@ -1200,6 +1207,7 @@ fn deserialize_externally_tagged_enum(
|
|||||||
|
|
||||||
let type_name = cattrs.name().deserialize_name();
|
let type_name = cattrs.name().deserialize_name();
|
||||||
let expecting = format!("enum {}", params.type_name());
|
let expecting = format!("enum {}", params.type_name());
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs);
|
let (variants_stmt, variant_visitor) = prepare_enum_variant_enum(variants, cattrs);
|
||||||
|
|
||||||
@ -1309,6 +1317,9 @@ fn deserialize_internally_tagged_enum(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let expecting = format!("internally tagged enum {}", params.type_name());
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
|
|
||||||
quote_block! {
|
quote_block! {
|
||||||
#variant_visitor
|
#variant_visitor
|
||||||
|
|
||||||
@ -1316,7 +1327,7 @@ fn deserialize_internally_tagged_enum(
|
|||||||
|
|
||||||
let __tagged = try!(_serde::Deserializer::deserialize_any(
|
let __tagged = try!(_serde::Deserializer::deserialize_any(
|
||||||
__deserializer,
|
__deserializer,
|
||||||
_serde::private::de::TaggedContentVisitor::<__Field>::new(#tag)));
|
_serde::private::de::TaggedContentVisitor::<__Field>::new(#tag, #expecting)));
|
||||||
|
|
||||||
match __tagged.tag {
|
match __tagged.tag {
|
||||||
#(#variant_arms)*
|
#(#variant_arms)*
|
||||||
@ -1359,6 +1370,7 @@ fn deserialize_adjacently_tagged_enum(
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let expecting = format!("adjacently tagged enum {}", params.type_name());
|
let expecting = format!("adjacently tagged enum {}", params.type_name());
|
||||||
|
let expecting = cattrs.expecting().unwrap_or(&expecting);
|
||||||
let type_name = cattrs.name().deserialize_name();
|
let type_name = cattrs.name().deserialize_name();
|
||||||
let deny_unknown_fields = cattrs.deny_unknown_fields();
|
let deny_unknown_fields = cattrs.deny_unknown_fields();
|
||||||
|
|
||||||
@ -1648,6 +1660,7 @@ fn deserialize_untagged_enum(
|
|||||||
"data did not match any variant of untagged enum {}",
|
"data did not match any variant of untagged enum {}",
|
||||||
params.type_name()
|
params.type_name()
|
||||||
);
|
);
|
||||||
|
let fallthrough_msg = cattrs.expecting().unwrap_or(&fallthrough_msg);
|
||||||
|
|
||||||
quote_block! {
|
quote_block! {
|
||||||
let __content = try!(<_serde::private::de::Content as _serde::Deserialize>::deserialize(__deserializer));
|
let __content = try!(<_serde::private::de::Content as _serde::Deserialize>::deserialize(__deserializer));
|
||||||
@ -1905,6 +1918,7 @@ fn deserialize_generated_identifier(
|
|||||||
is_variant,
|
is_variant,
|
||||||
fallthrough,
|
fallthrough,
|
||||||
!is_variant && cattrs.has_flatten(),
|
!is_variant && cattrs.has_flatten(),
|
||||||
|
None,
|
||||||
));
|
));
|
||||||
|
|
||||||
let lifetime = if !is_variant && cattrs.has_flatten() {
|
let lifetime = if !is_variant && cattrs.has_flatten() {
|
||||||
@ -2012,6 +2026,7 @@ fn deserialize_custom_identifier(
|
|||||||
is_variant,
|
is_variant,
|
||||||
fallthrough,
|
fallthrough,
|
||||||
false,
|
false,
|
||||||
|
cattrs.expecting(),
|
||||||
));
|
));
|
||||||
|
|
||||||
quote_block! {
|
quote_block! {
|
||||||
@ -2042,6 +2057,7 @@ fn deserialize_identifier(
|
|||||||
is_variant: bool,
|
is_variant: bool,
|
||||||
fallthrough: Option<TokenStream>,
|
fallthrough: Option<TokenStream>,
|
||||||
collect_other_fields: bool,
|
collect_other_fields: bool,
|
||||||
|
expecting: Option<&str>,
|
||||||
) -> Fragment {
|
) -> Fragment {
|
||||||
let mut flat_fields = Vec::new();
|
let mut flat_fields = Vec::new();
|
||||||
for (_, ident, aliases) in fields {
|
for (_, ident, aliases) in fields {
|
||||||
@ -2066,11 +2082,11 @@ fn deserialize_identifier(
|
|||||||
.map(|(_, ident, _)| quote!(#this::#ident))
|
.map(|(_, ident, _)| quote!(#this::#ident))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let expecting = if is_variant {
|
let expecting = expecting.unwrap_or(if is_variant {
|
||||||
"variant identifier"
|
"variant identifier"
|
||||||
} else {
|
} else {
|
||||||
"field identifier"
|
"field identifier"
|
||||||
};
|
});
|
||||||
|
|
||||||
let index_expecting = if is_variant { "variant" } else { "field" };
|
let index_expecting = if is_variant { "variant" } else { "field" };
|
||||||
|
|
||||||
|
@ -223,6 +223,8 @@ pub struct Container {
|
|||||||
has_flatten: bool,
|
has_flatten: bool,
|
||||||
serde_path: Option<syn::Path>,
|
serde_path: Option<syn::Path>,
|
||||||
is_packed: bool,
|
is_packed: bool,
|
||||||
|
/// Error message generated when type can't be deserialized
|
||||||
|
expecting: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Styles of representing an enum.
|
/// Styles of representing an enum.
|
||||||
@ -305,6 +307,7 @@ impl Container {
|
|||||||
let mut field_identifier = BoolAttr::none(cx, FIELD_IDENTIFIER);
|
let mut field_identifier = BoolAttr::none(cx, FIELD_IDENTIFIER);
|
||||||
let mut variant_identifier = BoolAttr::none(cx, VARIANT_IDENTIFIER);
|
let mut variant_identifier = BoolAttr::none(cx, VARIANT_IDENTIFIER);
|
||||||
let mut serde_path = Attr::none(cx, CRATE);
|
let mut serde_path = Attr::none(cx, CRATE);
|
||||||
|
let mut expecting = Attr::none(cx, EXPECTING);
|
||||||
|
|
||||||
for meta_item in item
|
for meta_item in item
|
||||||
.attrs
|
.attrs
|
||||||
@ -575,6 +578,13 @@ impl Container {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse `#[serde(expecting = "a message")]`
|
||||||
|
Meta(NameValue(m)) if m.path == EXPECTING => {
|
||||||
|
if let Ok(s) = get_lit_str(cx, EXPECTING, &m.lit) {
|
||||||
|
expecting.set(&m.path, s.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Meta(meta_item) => {
|
Meta(meta_item) => {
|
||||||
let path = meta_item
|
let path = meta_item
|
||||||
.path()
|
.path()
|
||||||
@ -627,6 +637,7 @@ impl Container {
|
|||||||
has_flatten: false,
|
has_flatten: false,
|
||||||
serde_path: serde_path.get(),
|
serde_path: serde_path.get(),
|
||||||
is_packed,
|
is_packed,
|
||||||
|
expecting: expecting.get(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,6 +713,12 @@ impl Container {
|
|||||||
self.custom_serde_path()
|
self.custom_serde_path()
|
||||||
.map_or_else(|| Cow::Owned(parse_quote!(_serde)), Cow::Borrowed)
|
.map_or_else(|| Cow::Owned(parse_quote!(_serde)), Cow::Borrowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Error message generated when type can't be deserialized.
|
||||||
|
/// If `None`, default message will be used
|
||||||
|
pub fn expecting(&self) -> Option<&str> {
|
||||||
|
self.expecting.as_ref().map(String::as_ref)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decide_tag(
|
fn decide_tag(
|
||||||
|
@ -35,6 +35,7 @@ pub const TRY_FROM: Symbol = Symbol("try_from");
|
|||||||
pub const UNTAGGED: Symbol = Symbol("untagged");
|
pub const UNTAGGED: Symbol = Symbol("untagged");
|
||||||
pub const VARIANT_IDENTIFIER: Symbol = Symbol("variant_identifier");
|
pub const VARIANT_IDENTIFIER: Symbol = Symbol("variant_identifier");
|
||||||
pub const WITH: Symbol = Symbol("with");
|
pub const WITH: Symbol = Symbol("with");
|
||||||
|
pub const EXPECTING: Symbol = Symbol("expecting");
|
||||||
|
|
||||||
impl PartialEq<Symbol> for Ident {
|
impl PartialEq<Symbol> for Ident {
|
||||||
fn eq(&self, word: &Symbol) -> bool {
|
fn eq(&self, word: &Symbol) -> bool {
|
||||||
|
@ -2633,3 +2633,200 @@ fn test_flatten_any_after_flatten_struct() {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://github.com/serde-rs/serde/issues/1883
|
||||||
|
#[test]
|
||||||
|
fn test_expecting_message() {
|
||||||
|
#[derive(Deserialize, PartialEq, Debug)]
|
||||||
|
#[serde(expecting = "something strange...")]
|
||||||
|
struct Unit;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(expecting = "something strange...")]
|
||||||
|
struct Newtype(bool);
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(expecting = "something strange...")]
|
||||||
|
struct Tuple(u32, bool);
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(expecting = "something strange...")]
|
||||||
|
struct Struct {
|
||||||
|
question: String,
|
||||||
|
answer: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens_error::<Unit>(
|
||||||
|
&[Token::Str("Unit")],
|
||||||
|
r#"invalid type: string "Unit", expected something strange..."#
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens_error::<Newtype>(
|
||||||
|
&[Token::Str("Newtype")],
|
||||||
|
r#"invalid type: string "Newtype", expected something strange..."#
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens_error::<Tuple>(
|
||||||
|
&[Token::Str("Tuple")],
|
||||||
|
r#"invalid type: string "Tuple", expected something strange..."#
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens_error::<Struct>(
|
||||||
|
&[Token::Str("Struct")],
|
||||||
|
r#"invalid type: string "Struct", expected something strange..."#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_expecting_message_externally_tagged_enum() {
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(expecting = "something strange...")]
|
||||||
|
enum Enum {
|
||||||
|
ExternallyTagged,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens_error::<Enum>(
|
||||||
|
&[
|
||||||
|
Token::Str("ExternallyTagged"),
|
||||||
|
],
|
||||||
|
r#"invalid type: string "ExternallyTagged", expected something strange..."#
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
|
||||||
|
assert_de_tokens_error::<Enum>(
|
||||||
|
&[
|
||||||
|
Token::Enum { name: "Enum" },
|
||||||
|
Token::Unit,
|
||||||
|
],
|
||||||
|
r#"invalid type: unit value, expected variant identifier"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_expecting_message_internally_tagged_enum() {
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(tag = "tag")]
|
||||||
|
#[serde(expecting = "something strange...")]
|
||||||
|
enum Enum {
|
||||||
|
InternallyTagged,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens_error::<Enum>(
|
||||||
|
&[
|
||||||
|
Token::Str("InternallyTagged"),
|
||||||
|
],
|
||||||
|
r#"invalid type: string "InternallyTagged", expected something strange..."#
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
|
||||||
|
assert_de_tokens_error::<Enum>(
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Str("tag"),
|
||||||
|
Token::Unit,
|
||||||
|
],
|
||||||
|
r#"invalid type: unit value, expected variant identifier"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_expecting_message_adjacently_tagged_enum() {
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(tag = "tag", content = "content")]
|
||||||
|
#[serde(expecting = "something strange...")]
|
||||||
|
enum Enum {
|
||||||
|
AdjacentlyTagged,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens_error::<Enum>(
|
||||||
|
&[
|
||||||
|
Token::Str("AdjacentlyTagged"),
|
||||||
|
],
|
||||||
|
r#"invalid type: string "AdjacentlyTagged", expected something strange..."#
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens_error::<Enum>(
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Unit,
|
||||||
|
],
|
||||||
|
r#"invalid type: unit value, expected "tag", "content", or other ignored fields"#
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check that #[serde(expecting = "...")] doesn't affect variant identifier error message
|
||||||
|
assert_de_tokens_error::<Enum>(
|
||||||
|
&[
|
||||||
|
Token::Map { len: None },
|
||||||
|
Token::Str("tag"),
|
||||||
|
Token::Unit,
|
||||||
|
],
|
||||||
|
r#"invalid type: unit value, expected variant identifier"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_expecting_message_untagged_tagged_enum() {
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
#[serde(expecting = "something strange...")]
|
||||||
|
enum Enum {
|
||||||
|
Untagged,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens_error::<Enum>(
|
||||||
|
&[
|
||||||
|
Token::Str("Untagged"),
|
||||||
|
],
|
||||||
|
r#"something strange..."#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_expecting_message_identifier_enum() {
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(field_identifier)]
|
||||||
|
#[serde(expecting = "something strange...")]
|
||||||
|
enum FieldEnum {
|
||||||
|
Field,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(variant_identifier)]
|
||||||
|
#[serde(expecting = "something strange...")]
|
||||||
|
enum VariantEnum {
|
||||||
|
Variant,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_de_tokens_error::<FieldEnum>(
|
||||||
|
&[
|
||||||
|
Token::Unit,
|
||||||
|
],
|
||||||
|
r#"invalid type: unit value, expected something strange..."#
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens_error::<FieldEnum>(
|
||||||
|
&[
|
||||||
|
Token::Enum { name: "FieldEnum" },
|
||||||
|
Token::Str("Unknown"),
|
||||||
|
Token::None,
|
||||||
|
],
|
||||||
|
r#"invalid type: map, expected something strange..."#
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
assert_de_tokens_error::<VariantEnum>(
|
||||||
|
&[
|
||||||
|
Token::Unit,
|
||||||
|
],
|
||||||
|
r#"invalid type: unit value, expected something strange..."#
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_de_tokens_error::<VariantEnum>(
|
||||||
|
&[
|
||||||
|
Token::Enum { name: "VariantEnum" },
|
||||||
|
Token::Str("Unknown"),
|
||||||
|
Token::None,
|
||||||
|
],
|
||||||
|
r#"invalid type: map, expected something strange..."#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -723,6 +723,55 @@ fn test_gen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deriving!(&'a str);
|
deriving!(&'a str);
|
||||||
|
|
||||||
|
// https://github.com/serde-rs/serde/issues/1883
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(expecting = "a message")]
|
||||||
|
struct CustomMessageUnit;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(expecting = "a message")]
|
||||||
|
struct CustomMessageNewtype(bool);
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(expecting = "a message")]
|
||||||
|
struct CustomMessageTuple(u32, bool);
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(expecting = "a message")]
|
||||||
|
struct CustomMessageStruct {
|
||||||
|
question: String,
|
||||||
|
answer: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(expecting = "a message")]
|
||||||
|
enum CustomMessageExternallyTaggedEnum {}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(tag = "tag")]
|
||||||
|
#[serde(expecting = "a message")]
|
||||||
|
enum CustomMessageInternallyTaggedEnum {}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(tag = "tag", content = "content")]
|
||||||
|
#[serde(expecting = "a message")]
|
||||||
|
enum CustomMessageAdjacentlyTaggedEnum {}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
#[serde(expecting = "a message")]
|
||||||
|
enum CustomMessageUntaggedEnum {}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(field_identifier)]
|
||||||
|
#[serde(expecting = "a message")]
|
||||||
|
enum CustomMessageFieldIdentifierEnum {}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(variant_identifier)]
|
||||||
|
#[serde(expecting = "a message")]
|
||||||
|
enum CustomMessageVariantIdentifierEnum {}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
x
Reference in New Issue
Block a user