mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-09 20:11:01 +00:00
Allow borrow attribute on newtype variants
This commit is contained in:
@@ -51,7 +51,7 @@ impl<'a> Container<'a> {
|
|||||||
let mut body = match item.body {
|
let mut body = match item.body {
|
||||||
syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)),
|
syn::Body::Enum(ref variants) => Body::Enum(enum_from_ast(cx, variants)),
|
||||||
syn::Body::Struct(ref variant_data) => {
|
syn::Body::Struct(ref variant_data) => {
|
||||||
let (style, fields) = struct_from_ast(cx, variant_data);
|
let (style, fields) = struct_from_ast(cx, variant_data, None);
|
||||||
Body::Struct(style, fields)
|
Body::Struct(style, fields)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -103,10 +103,11 @@ fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>
|
|||||||
.iter()
|
.iter()
|
||||||
.map(
|
.map(
|
||||||
|variant| {
|
|variant| {
|
||||||
let (style, fields) = struct_from_ast(cx, &variant.data);
|
let attrs = attr::Variant::from_ast(cx, variant);
|
||||||
|
let (style, fields) = struct_from_ast(cx, &variant.data, Some(&attrs));
|
||||||
Variant {
|
Variant {
|
||||||
ident: variant.ident.clone(),
|
ident: variant.ident.clone(),
|
||||||
attrs: attr::Variant::from_ast(cx, variant),
|
attrs: attrs,
|
||||||
style: style,
|
style: style,
|
||||||
fields: fields,
|
fields: fields,
|
||||||
}
|
}
|
||||||
@@ -115,18 +116,18 @@ fn enum_from_ast<'a>(cx: &Ctxt, variants: &'a [syn::Variant]) -> Vec<Variant<'a>
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData) -> (Style, Vec<Field<'a>>) {
|
fn struct_from_ast<'a>(cx: &Ctxt, data: &'a syn::VariantData, attrs: Option<&attr::Variant>) -> (Style, Vec<Field<'a>>) {
|
||||||
match *data {
|
match *data {
|
||||||
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields)),
|
syn::VariantData::Struct(ref fields) => (Style::Struct, fields_from_ast(cx, fields, attrs)),
|
||||||
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
|
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
|
||||||
(Style::Newtype, fields_from_ast(cx, fields))
|
(Style::Newtype, fields_from_ast(cx, fields, attrs))
|
||||||
}
|
}
|
||||||
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields)),
|
syn::VariantData::Tuple(ref fields) => (Style::Tuple, fields_from_ast(cx, fields, attrs)),
|
||||||
syn::VariantData::Unit => (Style::Unit, Vec::new()),
|
syn::VariantData::Unit => (Style::Unit, Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field]) -> Vec<Field<'a>> {
|
fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field], attrs: Option<&attr::Variant>) -> Vec<Field<'a>> {
|
||||||
fields
|
fields
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
@@ -134,7 +135,7 @@ fn fields_from_ast<'a>(cx: &Ctxt, fields: &'a [syn::Field]) -> Vec<Field<'a>> {
|
|||||||
|(i, field)| {
|
|(i, field)| {
|
||||||
Field {
|
Field {
|
||||||
ident: field.ident.clone(),
|
ident: field.ident.clone(),
|
||||||
attrs: attr::Field::from_ast(cx, i, field),
|
attrs: attr::Field::from_ast(cx, i, field, attrs),
|
||||||
ty: &field.ty,
|
ty: &field.ty,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -512,6 +512,7 @@ pub struct Variant {
|
|||||||
other: bool,
|
other: bool,
|
||||||
serialize_with: Option<syn::Path>,
|
serialize_with: Option<syn::Path>,
|
||||||
deserialize_with: Option<syn::Path>,
|
deserialize_with: Option<syn::Path>,
|
||||||
|
borrow: Option<syn::MetaItem>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Variant {
|
impl Variant {
|
||||||
@@ -524,6 +525,7 @@ impl Variant {
|
|||||||
let mut other = BoolAttr::none(cx, "other");
|
let mut other = BoolAttr::none(cx, "other");
|
||||||
let mut serialize_with = Attr::none(cx, "serialize_with");
|
let mut serialize_with = Attr::none(cx, "serialize_with");
|
||||||
let mut deserialize_with = Attr::none(cx, "deserialize_with");
|
let mut deserialize_with = Attr::none(cx, "deserialize_with");
|
||||||
|
let mut borrow = Attr::none(cx, "borrow");
|
||||||
|
|
||||||
for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
|
for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
|
||||||
for meta_item in meta_items {
|
for meta_item in meta_items {
|
||||||
@@ -599,6 +601,18 @@ impl Variant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Defer `#[serde(borrow)]` and `#[serde(borrow = "'a + 'b")]`
|
||||||
|
MetaItem(ref mi) if mi.name() == "borrow" => {
|
||||||
|
match variant.data {
|
||||||
|
syn::VariantData::Tuple(ref fields) if fields.len() == 1 => {
|
||||||
|
borrow.set(mi.clone());
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
cx.error("#[serde(borrow)] may only be used on newtype variants");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MetaItem(ref meta_item) => {
|
MetaItem(ref meta_item) => {
|
||||||
cx.error(format!("unknown serde variant attribute `{}`", meta_item.name()));
|
cx.error(format!("unknown serde variant attribute `{}`", meta_item.name()));
|
||||||
}
|
}
|
||||||
@@ -627,6 +641,7 @@ impl Variant {
|
|||||||
other: other.get(),
|
other: other.get(),
|
||||||
serialize_with: serialize_with.get(),
|
serialize_with: serialize_with.get(),
|
||||||
deserialize_with: deserialize_with.get(),
|
deserialize_with: deserialize_with.get(),
|
||||||
|
borrow: borrow.get(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -699,7 +714,7 @@ pub enum Default {
|
|||||||
|
|
||||||
impl Field {
|
impl Field {
|
||||||
/// Extract out the `#[serde(...)]` attributes from a struct field.
|
/// Extract out the `#[serde(...)]` attributes from a struct field.
|
||||||
pub fn from_ast(cx: &Ctxt, index: usize, field: &syn::Field) -> Self {
|
pub fn from_ast(cx: &Ctxt, index: usize, field: &syn::Field, attrs: Option<&Variant>) -> Self {
|
||||||
let mut ser_name = Attr::none(cx, "rename");
|
let mut ser_name = Attr::none(cx, "rename");
|
||||||
let mut de_name = Attr::none(cx, "rename");
|
let mut de_name = Attr::none(cx, "rename");
|
||||||
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
|
let mut skip_serializing = BoolAttr::none(cx, "skip_serializing");
|
||||||
@@ -718,7 +733,13 @@ impl Field {
|
|||||||
None => index.to_string(),
|
None => index.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
for meta_items in field.attrs.iter().filter_map(get_serde_meta_items) {
|
let variant_borrow = attrs
|
||||||
|
.map(|variant| &variant.borrow)
|
||||||
|
.unwrap_or(&None)
|
||||||
|
.as_ref()
|
||||||
|
.map(|borrow| vec![MetaItem(borrow.clone())]);
|
||||||
|
|
||||||
|
for meta_items in field.attrs.iter().filter_map(get_serde_meta_items).chain(variant_borrow) {
|
||||||
for meta_item in meta_items {
|
for meta_item in meta_items {
|
||||||
match meta_item {
|
match meta_item {
|
||||||
// Parse `#[serde(rename = "foo")]`
|
// Parse `#[serde(rename = "foo")]`
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2017 Serde Developers
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Str<'a>(&'a str);
|
||||||
|
|
||||||
|
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
|
||||||
|
enum Test<'a> {
|
||||||
|
#[serde(borrow)] //~^^ HELP: duplicate serde attribute `borrow`
|
||||||
|
S(#[serde(borrow)] Str<'a>)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2017 Serde Developers
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_derive;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Str<'a>(&'a str);
|
||||||
|
|
||||||
|
#[derive(Deserialize)] //~ ERROR: proc-macro derive panicked
|
||||||
|
enum Test<'a> {
|
||||||
|
#[serde(borrow)] //~^^ HELP: #[serde(borrow)] may only be used on newtype variants
|
||||||
|
S { s: Str<'a> }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
@@ -357,6 +357,12 @@ fn test_gen() {
|
|||||||
s: Str<'a>,
|
s: Str<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
enum BorrowVariant<'a> {
|
||||||
|
#[serde(borrow, with = "StrDef")]
|
||||||
|
S(Str<'a>),
|
||||||
|
}
|
||||||
|
|
||||||
mod vis {
|
mod vis {
|
||||||
pub struct S;
|
pub struct S;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user