From fe5176113b6389fbf960014300478cb67c4333d5 Mon Sep 17 00:00:00 2001 From: Hugo Duncan <hugo@hugoduncan.org> Date: Fri, 1 May 2015 15:45:58 -0400 Subject: [PATCH] Add missing attr.rs file --- serde_macros/src/attr.rs | 108 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 serde_macros/src/attr.rs diff --git a/serde_macros/src/attr.rs b/serde_macros/src/attr.rs new file mode 100644 index 00000000..94402814 --- /dev/null +++ b/serde_macros/src/attr.rs @@ -0,0 +1,108 @@ +use std::collections::HashMap; +use std::collections::HashSet; + +use syntax::ast; +use syntax::ext::base::ExtCtxt; +use syntax::ptr::P; + +/// Represents field name information +pub enum FieldNames { + Global(P<ast::Expr>), + Format{ + formats: HashMap<P<ast::Expr>, P<ast::Expr>>, + default: P<ast::Expr>, + } +} + +/// Represents field attribute information +pub struct FieldAttrs { + names: FieldNames, + use_default: bool, +} + +impl FieldAttrs { + + /// Create a FieldAttr with a single default field name + pub fn new(default_value: bool, name: P<ast::Expr>) -> FieldAttrs { + FieldAttrs { + names: FieldNames::Global(name), + use_default: default_value, + } + } + + /// Create a FieldAttr with format specific field names + pub fn new_with_formats( + default_value: bool, + default_name: P<ast::Expr>, + formats: HashMap<P<ast::Expr>, P<ast::Expr>>, + ) -> FieldAttrs { + FieldAttrs { + names: FieldNames::Format { + formats: formats, + default: default_name, + }, + use_default: default_value, + } + } + + /// Return a set of formats that the field has attributes for. + pub fn formats(&self) -> HashSet<P<ast::Expr>> { + match self.names { + FieldNames::Format{ref formats, default: _} => { + let mut set = HashSet::new(); + for (fmt, _) in formats.iter() { + set.insert(fmt.clone()); + }; + set + }, + _ => HashSet::new() + } + } + + /// Return an expression for the field key name for serialisation. + /// + /// The resulting expression assumes that `S` refers to a type + /// that implements `Serializer`. + pub fn serializer_key_expr(self, cx: &ExtCtxt) -> P<ast::Expr> { + match self.names { + FieldNames::Global(x) => x, + FieldNames::Format{formats, default} => { + let arms = formats.iter() + .map(|(fmt, lit)| { + quote_arm!(cx, $fmt => { $lit }) + }) + .collect::<Vec<_>>(); + quote_expr!(cx, + { + match S::format() { + $arms, + _ => $default + } + }) + }, + } + } + + /// Return the default field name for the field. + pub fn default_key_expr(&self) -> &P<ast::Expr> { + match self.names { + FieldNames::Global(ref expr) => expr, + FieldNames::Format{formats: _, ref default} => default + } + } + + /// Return the field name for the field in the specified format. + pub fn key_expr(&self, format: &P<ast::Expr>) -> &P<ast::Expr> { + match self.names { + FieldNames::Global(ref expr) => + expr, + FieldNames::Format{ref formats, ref default} => + formats.get(format).unwrap_or(default) + } + } + + /// Predicate for using a field's default value + pub fn use_default(&self) -> bool { + self.use_default + } +}