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
+    }
+}