508 lines
18 KiB
Rust
Raw Normal View History

2016-09-10 21:53:14 -07:00
use Ctxt;
use syn;
2015-05-01 15:45:58 -04:00
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
// are `attr::Item::from_ast`, `attr::Variant::from_ast`, and
// `attr::Field::from_ast`. Each returns an instance of the corresponding
// struct. Note that none of them return a Result. Unrecognized, malformed, or
// duplicated attributes result in a span_err but otherwise are ignored. The
// user will see errors simultaneously for all bad attributes in the crate
// rather than just the first.
2016-09-10 21:53:14 -07:00
struct Attr<'c, T> {
cx: &'c Ctxt,
2016-06-14 11:22:49 -07:00
name: &'static str,
2016-09-10 21:53:14 -07:00
value: Option<T>,
2016-06-14 11:22:49 -07:00
}
2016-09-10 21:53:14 -07:00
impl<'c, T> Attr<'c, T> {
fn none(cx: &'c Ctxt, name: &'static str) -> Self {
2016-06-14 11:22:49 -07:00
Attr {
cx: cx,
name: name,
value: None,
}
}
2016-09-10 21:53:14 -07:00
fn set(&mut self, value: T) {
if self.value.is_some() {
self.cx.error(format!("duplicate serde attribute `{}`", self.name));
2016-06-14 11:22:49 -07:00
} else {
2016-09-10 21:53:14 -07:00
self.value = Some(value);
2016-06-14 11:22:49 -07:00
}
}
2016-09-10 21:53:14 -07:00
fn set_opt(&mut self, value: Option<T>) {
if let Some(value) = value {
self.set(value);
2016-06-14 11:22:49 -07:00
}
}
2016-09-10 21:53:14 -07:00
fn set_if_none(&mut self, value: T) {
2016-06-14 11:22:49 -07:00
if self.value.is_none() {
2016-09-10 21:53:14 -07:00
self.value = Some(value);
2016-06-14 11:22:49 -07:00
}
}
fn get(self) -> Option<T> {
self.value
}
2016-06-14 11:22:49 -07:00
}
2016-09-10 21:53:14 -07:00
struct BoolAttr<'c>(Attr<'c, ()>);
impl<'c> BoolAttr<'c> {
fn none(cx: &'c Ctxt, name: &'static str) -> Self {
2016-06-14 11:22:49 -07:00
BoolAttr(Attr::none(cx, name))
}
2016-09-10 21:53:14 -07:00
fn set_true(&mut self) {
self.0.set(());
2016-06-14 11:22:49 -07:00
}
fn get(&self) -> bool {
self.0.value.is_some()
}
}
#[derive(Debug)]
pub struct Name {
2016-09-10 21:53:14 -07:00
serialize: String,
deserialize: String,
}
impl Name {
/// Return the container name for the container when serializing.
2016-09-10 21:53:14 -07:00
pub fn serialize_name(&self) -> String {
2016-06-19 20:31:12 -07:00
self.serialize.clone()
}
/// Return the container name for the container when deserializing.
2016-09-10 21:53:14 -07:00
pub fn deserialize_name(&self) -> String {
2016-06-19 20:31:12 -07:00
self.deserialize.clone()
}
}
/// Represents container (e.g. struct) attribute information
#[derive(Debug)]
pub struct Item {
name: Name,
deny_unknown_fields: bool,
2016-09-10 21:53:14 -07:00
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
}
impl Item {
/// Extract out the `#[serde(...)]` attributes from an item.
2016-09-24 09:54:10 -07:00
pub fn from_ast(cx: &Ctxt, item: &syn::MacroInput) -> Self {
2016-06-14 11:22:49 -07:00
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
let mut deny_unknown_fields = BoolAttr::none(cx, "deny_unknown_fields");
let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound");
2016-09-10 21:53:14 -07:00
for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
2016-09-10 21:53:14 -07:00
match meta_item {
// Parse `#[serde(rename="foo")]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
2016-09-24 09:54:10 -07:00
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::List(ref name, ref meta_items) if name == "rename" => {
2016-06-14 23:37:20 -07:00
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
}
}
// Parse `#[serde(deny_unknown_fields)]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::Word(ref name) if name == "deny_unknown_fields" => {
deny_unknown_fields.set_true();
}
// Parse `#[serde(bound="D: Serialize")]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::NameValue(ref name, ref lit) if name == "bound" => {
if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
2016-09-10 21:53:14 -07:00
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
2016-06-14 23:37:20 -07:00
}
}
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::List(ref name, ref meta_items) if name == "bound" => {
2016-06-14 23:37:20 -07:00
if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
ser_bound.set_opt(ser);
de_bound.set_opt(de);
}
}
_ => {
cx.error(format!("unknown serde container attribute `{}`",
meta_item.name()));
}
}
}
}
Item {
2016-06-14 11:22:49 -07:00
name: Name {
2016-09-10 21:53:14 -07:00
serialize: ser_name.get().unwrap_or_else(|| item.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| item.ident.to_string()),
2016-06-14 11:22:49 -07:00
},
deny_unknown_fields: deny_unknown_fields.get(),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
2016-06-14 23:37:20 -07:00
}
}
pub fn name(&self) -> &Name {
&self.name
}
pub fn deny_unknown_fields(&self) -> bool {
self.deny_unknown_fields
}
2016-09-10 21:53:14 -07:00
pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
2016-09-10 21:53:14 -07:00
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
}
2016-02-08 08:03:46 -08:00
/// Represents variant attribute information
#[derive(Debug)]
pub struct Variant {
name: Name,
2016-02-08 08:03:46 -08:00
}
impl Variant {
2016-09-10 21:53:14 -07:00
pub fn from_ast(cx: &Ctxt, variant: &syn::Variant) -> Self {
2016-06-14 11:22:49 -07:00
let mut ser_name = Attr::none(cx, "rename");
let mut de_name = Attr::none(cx, "rename");
2016-02-08 08:03:46 -08:00
2016-09-10 21:53:14 -07:00
for meta_items in variant.attrs.iter().filter_map(get_serde_meta_items) {
2016-02-08 08:03:46 -08:00
for meta_item in meta_items {
2016-09-10 21:53:14 -07:00
match meta_item {
2016-02-08 08:03:46 -08:00
// Parse `#[serde(rename="foo")]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
2016-09-24 09:54:10 -07:00
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::List(ref name, ref meta_items) if name == "rename" => {
2016-06-14 23:37:20 -07:00
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
}
2016-02-08 08:03:46 -08:00
}
_ => {
cx.error(format!("unknown serde variant attribute `{}`",
meta_item.name()));
2016-02-08 08:03:46 -08:00
}
}
}
}
Variant {
2016-06-14 11:22:49 -07:00
name: Name {
2016-09-10 21:53:14 -07:00
serialize: ser_name.get().unwrap_or_else(|| variant.ident.to_string()),
deserialize: de_name.get().unwrap_or_else(|| variant.ident.to_string()),
2016-06-14 11:22:49 -07:00
},
2016-06-14 23:37:20 -07:00
}
2016-02-08 08:03:46 -08:00
}
pub fn name(&self) -> &Name {
&self.name
2016-02-08 08:03:46 -08:00
}
}
2015-05-01 15:45:58 -04:00
/// Represents field attribute information
#[derive(Debug)]
pub struct Field {
name: Name,
2016-06-14 11:22:49 -07:00
skip_serializing: bool,
skip_deserializing: bool,
2016-09-10 21:53:14 -07:00
skip_serializing_if: Option<syn::Path>,
default: FieldDefault,
2016-09-10 21:53:14 -07:00
serialize_with: Option<syn::Path>,
deserialize_with: Option<syn::Path>,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
2015-05-01 15:45:58 -04:00
}
/// Represents the default to use for a field when deserializing.
#[derive(Debug, PartialEq)]
pub enum FieldDefault {
/// Field must always be specified because it does not have a default.
None,
/// The default is given by `std::default::Default::default()`.
Default,
/// The default is given by this function.
2016-09-10 21:53:14 -07:00
Path(syn::Path),
}
impl Field {
/// Extract out the `#[serde(...)]` attributes from a struct field.
2016-09-10 21:53:14 -07:00
pub fn from_ast(cx: &Ctxt,
index: usize,
2016-09-10 21:53:14 -07:00
field: &syn::Field) -> Self {
2016-06-14 11:22:49 -07:00
let mut ser_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_deserializing = BoolAttr::none(cx, "skip_deserializing");
let mut skip_serializing_if = Attr::none(cx, "skip_serializing_if");
let mut default = Attr::none(cx, "default");
let mut serialize_with = Attr::none(cx, "serialize_with");
let mut deserialize_with = Attr::none(cx, "deserialize_with");
let mut ser_bound = Attr::none(cx, "bound");
let mut de_bound = Attr::none(cx, "bound");
2016-06-19 20:31:12 -07:00
let ident = match field.ident {
2016-09-10 21:53:14 -07:00
Some(ref ident) => ident.to_string(),
None => index.to_string(),
};
2016-04-10 19:54:54 -07:00
for meta_items in field.attrs.iter().filter_map(get_serde_meta_items) {
for meta_item in meta_items {
2016-09-10 21:53:14 -07:00
match meta_item {
// Parse `#[serde(rename="foo")]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::NameValue(ref name, ref lit) if name == "rename" => {
if let Ok(s) = get_string_from_lit(cx, name.as_ref(), name.as_ref(), lit) {
2016-09-24 09:54:10 -07:00
ser_name.set(s.clone());
de_name.set(s);
}
}
// Parse `#[serde(rename(serialize="foo", deserialize="bar"))]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::List(ref name, ref meta_items) if name == "rename" => {
2016-06-14 23:37:20 -07:00
if let Ok((ser, de)) = get_renames(cx, meta_items) {
ser_name.set_opt(ser);
de_name.set_opt(de);
}
}
// Parse `#[serde(default)]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::Word(ref name) if name == "default" => {
default.set(FieldDefault::Default);
}
// Parse `#[serde(default="...")]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::NameValue(ref name, ref lit) if name == "default" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
2016-09-10 21:53:14 -07:00
default.set(FieldDefault::Path(path));
2016-06-14 23:37:20 -07:00
}
}
// Parse `#[serde(skip_serializing)]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::Word(ref name) if name == "skip_serializing" => {
skip_serializing.set_true();
}
2016-03-06 23:27:12 -08:00
// Parse `#[serde(skip_deserializing)]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::Word(ref name) if name == "skip_deserializing" => {
skip_deserializing.set_true();
2016-03-06 23:27:12 -08:00
}
// Parse `#[serde(skip_serializing_if="...")]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::NameValue(ref name, ref lit) if name == "skip_serializing_if" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
2016-09-10 21:53:14 -07:00
skip_serializing_if.set(path);
2016-06-14 23:37:20 -07:00
}
}
// Parse `#[serde(serialize_with="...")]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::NameValue(ref name, ref lit) if name == "serialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
2016-09-10 21:53:14 -07:00
serialize_with.set(path);
2016-06-14 23:37:20 -07:00
}
}
// Parse `#[serde(deserialize_with="...")]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::NameValue(ref name, ref lit) if name == "deserialize_with" => {
if let Ok(path) = parse_lit_into_path(cx, name.as_ref(), lit) {
2016-09-10 21:53:14 -07:00
deserialize_with.set(path);
2016-06-14 23:37:20 -07:00
}
}
// Parse `#[serde(bound="D: Serialize")]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::NameValue(ref name, ref lit) if name == "bound" => {
if let Ok(where_predicates) = parse_lit_into_where(cx, name.as_ref(), name.as_ref(), lit) {
2016-09-10 21:53:14 -07:00
ser_bound.set(where_predicates.clone());
de_bound.set(where_predicates);
2016-06-14 23:37:20 -07:00
}
}
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
2016-09-10 21:53:14 -07:00
syn::MetaItem::List(ref name, ref meta_items) if name == "bound" => {
2016-06-14 23:37:20 -07:00
if let Ok((ser, de)) = get_where_predicates(cx, meta_items) {
ser_bound.set_opt(ser);
de_bound.set_opt(de);
}
}
_ => {
cx.error(format!("unknown serde field attribute `{}`",
meta_item.name()));
}
}
}
}
2016-06-14 11:22:49 -07:00
// Is skip_deserializing, initialize the field to Default::default()
// unless a different default is specified by `#[serde(default="...")]`
2016-09-10 21:53:14 -07:00
if skip_deserializing.0.value.is_some() {
default.set_if_none(FieldDefault::Default);
2016-06-14 11:22:49 -07:00
}
Field {
2016-06-14 11:22:49 -07:00
name: Name {
2016-06-19 20:31:12 -07:00
serialize: ser_name.get().unwrap_or(ident.clone()),
deserialize: de_name.get().unwrap_or(ident),
2016-06-14 11:22:49 -07:00
},
skip_serializing: skip_serializing.get(),
skip_deserializing: skip_deserializing.get(),
skip_serializing_if: skip_serializing_if.get(),
default: default.get().unwrap_or(FieldDefault::None),
serialize_with: serialize_with.get(),
deserialize_with: deserialize_with.get(),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
2016-06-14 23:37:20 -07:00
}
}
pub fn name(&self) -> &Name {
&self.name
2015-05-01 15:45:58 -04:00
}
2016-06-14 11:22:49 -07:00
pub fn skip_serializing(&self) -> bool {
self.skip_serializing
}
2016-06-14 11:22:49 -07:00
pub fn skip_deserializing(&self) -> bool {
self.skip_deserializing
2016-03-06 23:27:12 -08:00
}
2016-09-10 21:53:14 -07:00
pub fn skip_serializing_if(&self) -> Option<&syn::Path> {
2016-05-15 15:54:20 -07:00
self.skip_serializing_if.as_ref()
}
pub fn default(&self) -> &FieldDefault {
&self.default
}
2016-09-10 21:53:14 -07:00
pub fn serialize_with(&self) -> Option<&syn::Path> {
self.serialize_with.as_ref()
}
2016-09-10 21:53:14 -07:00
pub fn deserialize_with(&self) -> Option<&syn::Path> {
2016-05-07 12:33:59 -07:00
self.deserialize_with.as_ref()
}
2016-09-10 21:53:14 -07:00
pub fn ser_bound(&self) -> Option<&[syn::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
2016-09-10 21:53:14 -07:00
pub fn de_bound(&self) -> Option<&[syn::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
2015-05-01 15:45:58 -04:00
}
2016-09-10 21:53:14 -07:00
type SerAndDe<T> = (Option<T>, Option<T>);
2016-08-19 11:47:16 -04:00
fn get_ser_and_de<T, F>(
2016-09-10 21:53:14 -07:00
cx: &Ctxt,
attr_name: &'static str,
2016-09-10 21:53:14 -07:00
items: &[syn::MetaItem],
f: F
2016-08-19 11:47:16 -04:00
) -> Result<SerAndDe<T>, ()>
where F: Fn(&Ctxt, &str, &str, &syn::Lit) -> Result<T, ()>,
{
let mut ser_item = Attr::none(cx, attr_name);
let mut de_item = Attr::none(cx, attr_name);
for item in items {
2016-09-10 21:53:14 -07:00
match *item {
syn::MetaItem::NameValue(ref name, ref lit) if name == "serialize" => {
if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) {
2016-09-10 21:53:14 -07:00
ser_item.set(v);
}
}
2016-09-10 21:53:14 -07:00
syn::MetaItem::NameValue(ref name, ref lit) if name == "deserialize" => {
if let Ok(v) = f(cx, attr_name, name.as_ref(), lit) {
2016-09-10 21:53:14 -07:00
de_item.set(v);
}
}
_ => {
cx.error(format!("malformed {0} attribute, expected `{0}(serialize = ..., deserialize = ...)`",
attr_name));
return Err(());
}
}
}
2016-09-10 21:53:14 -07:00
Ok((ser_item.get(), de_item.get()))
}
fn get_renames(
2016-09-10 21:53:14 -07:00
cx: &Ctxt,
items: &[syn::MetaItem],
) -> Result<SerAndDe<String>, ()> {
2016-09-24 09:54:10 -07:00
get_ser_and_de(cx, "rename", items, get_string_from_lit)
}
fn get_where_predicates(
2016-09-10 21:53:14 -07:00
cx: &Ctxt,
items: &[syn::MetaItem],
) -> Result<SerAndDe<Vec<syn::WherePredicate>>, ()> {
get_ser_and_de(cx, "bound", items, parse_lit_into_where)
}
2016-09-10 21:53:14 -07:00
pub fn get_serde_meta_items(attr: &syn::Attribute) -> Option<Vec<syn::MetaItem>> {
match attr.value {
syn::MetaItem::List(ref name, ref items) if name == "serde" => {
Some(items.iter().cloned().collect())
}
_ => None
}
}
fn get_string_from_lit(cx: &Ctxt, attr_name: &str, meta_item_name: &str, lit: &syn::Lit) -> Result<String, ()> {
2016-09-24 09:54:10 -07:00
if let syn::Lit::Str(ref s, _) = *lit {
Ok(s.clone())
} else {
cx.error(format!("expected serde {} attribute to be a string: `{} = \"...\"`",
attr_name, meta_item_name));
2016-09-24 09:54:10 -07:00
Err(())
}
}
fn parse_lit_into_path(cx: &Ctxt, attr_name: &str, lit: &syn::Lit) -> Result<syn::Path, ()> {
let string = try!(get_string_from_lit(cx, attr_name, attr_name, lit));
syn::parse_path(&string).map_err(|err| cx.error(err))
}
fn parse_lit_into_where(cx: &Ctxt, attr_name: &str, meta_item_name: &str, lit: &syn::Lit) -> Result<Vec<syn::WherePredicate>, ()> {
let string = try!(get_string_from_lit(cx, attr_name, meta_item_name, lit));
2016-09-24 09:54:10 -07:00
if string.is_empty() {
return Ok(Vec::new());
}
2016-09-24 09:54:10 -07:00
let where_string = format!("where {}", string);
syn::parse_where_clause(&where_string).map(|wh| wh.predicates).map_err(|err| cx.error(err))
}