diff --git a/samples/build-script/cbindgen.toml b/samples/build-script/cbindgen.toml
index af66efb7d48c142b5a953481ad21f9bfb056ecab..904e4b5146cbf2fc03c117da53da85a03d8ebd07 100644
--- a/samples/build-script/cbindgen.toml
+++ b/samples/build-script/cbindgen.toml
@@ -1,7 +1,17 @@
 include_guard = "build_script_h"
 include_version = true
+braces = "NextLine"
+tab_width = 4
+
+[enum]
+rename_variants = "SnakeCase"
+
+[fn]
+rename_args = "UpperCase"
+args = "Vertical"
 
 [struct]
+rename_fields = "GeckoCase"
 derive_eq = true
 derive_lt = true
 derive_lte = true
diff --git a/samples/build-script/src/lib.rs b/samples/build-script/src/lib.rs
index df7450f32f24e59e2fcaa2788bd9c27ff13fc3a6..22201a09addaecfd9381a60875f396233d2a6b85 100644
--- a/samples/build-script/src/lib.rs
+++ b/samples/build-script/src/lib.rs
@@ -1,6 +1,13 @@
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
+#[repr(u32)]
+pub enum Options {
+    First,
+    Second,
+    LastOne,
+}
+
 pub struct Opaque {
     x: i32,
     y: f32,
@@ -18,7 +25,10 @@ pub struct Comparable {
 }
 
 #[no_mangle]
-pub extern "C" fn root(x: *mut Opaque, y: Normal, z: Comparable)
+pub extern "C" fn root(x: *mut Opaque,
+                       y: Normal,
+                       z: Comparable,
+                       w: Options)
 {
 
 }
diff --git a/src/bindgen/config.rs b/src/bindgen/config.rs
index 4afed2070ee6f113c80f962ddac00ef16dc889f0..73c04276bcb199dcaaed0fa0b0b808f750170dd3 100644
--- a/src/bindgen/config.rs
+++ b/src/bindgen/config.rs
@@ -3,35 +3,84 @@ use std::fs::File;
 use std::io::prelude::*;
 use std::io::{self, BufReader};
 use std::path::PathBuf;
+use std::str::FromStr;
 
 use toml;
 
 pub use bindgen::directive::*;
+pub use bindgen::rename::*;
 
 pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
 
-#[derive(Debug, Clone, Deserialize)]
-#[serde(rename_all = "snake_case")]
+#[derive(Debug, Clone)]
 pub enum Language {
     Cxx,
     C,
 }
-
-#[derive(Debug, Clone, Deserialize)]
-#[serde(rename_all = "snake_case")]
+#[derive(Debug, Clone)]
 pub enum Braces {
     SameLine,
     NextLine,
 }
-
-#[derive(Debug, Clone, PartialEq, Deserialize)]
-#[serde(rename_all = "snake_case")]
+#[derive(Debug, Clone, PartialEq)]
 pub enum Layout {
     Horizontal,
     Vertical,
     Auto,
 }
 
+impl FromStr for Language {
+    type Err = String;
+
+    fn from_str(s: &str) -> Result<Language, Self::Err> {
+        match s {
+            "cxx" => Ok(Language::Cxx),
+            "Cxx" => Ok(Language::Cxx),
+            "CXX" => Ok(Language::Cxx),
+            "cpp" => Ok(Language::Cxx),
+            "Cpp" => Ok(Language::Cxx),
+            "CPP" => Ok(Language::Cxx),
+            "c++" => Ok(Language::Cxx),
+            "C++" => Ok(Language::Cxx),
+            "c" => Ok(Language::C),
+            "C" => Ok(Language::C),
+            _ => Err(format!("unrecognized Language: '{}'", s)),
+        }
+    }
+}
+impl FromStr for Braces {
+    type Err = String;
+
+    fn from_str(s: &str) -> Result<Braces, Self::Err> {
+        match s {
+            "SameLine" => Ok(Braces::SameLine),
+            "same_line" => Ok(Braces::SameLine),
+            "NextLine" => Ok(Braces::NextLine),
+            "next_line" => Ok(Braces::NextLine),
+            _ => Err(format!("unrecognized Braces: '{}'", s)),
+        }
+    }
+}
+impl FromStr for Layout {
+    type Err = String;
+
+    fn from_str(s: &str) -> Result<Layout, Self::Err> {
+        match s {
+            "Horizontal" => Ok(Layout::Horizontal),
+            "horizontal" => Ok(Layout::Horizontal),
+            "Vertical" => Ok(Layout::Vertical),
+            "vertical" => Ok(Layout::Vertical),
+            "Auto" => Ok(Layout::Auto),
+            "auto" => Ok(Layout::Auto),
+            _ => Err(format!("unrecognized Layout: '{}'", s)),
+        }
+    }
+}
+
+deserialize_enum_str!(Language);
+deserialize_enum_str!(Braces);
+deserialize_enum_str!(Layout);
+
 #[derive(Debug, Clone, Deserialize)]
 #[serde(rename_all = "snake_case")]
 #[serde(deny_unknown_fields)]
@@ -96,6 +145,8 @@ pub struct FunctionConfig {
     pub postfix: Option<String>,
     /// The style to layout the args
     pub args: Layout,
+    /// The rename rule to apply to function args
+    pub rename_args: Option<RenameRule>,
 }
 
 impl Default for FunctionConfig {
@@ -104,6 +155,7 @@ impl Default for FunctionConfig {
             prefix: None,
             postfix: None,
             args: Layout::Auto,
+            rename_args: None,
         }
     }
 }
@@ -113,6 +165,8 @@ impl Default for FunctionConfig {
 #[serde(deny_unknown_fields)]
 #[serde(default)]
 pub struct StructConfig {
+    /// The rename rule to apply to the name of struct fields
+    pub rename_fields: Option<RenameRule>,
     /// Whether to generate a piecewise equality operator
     pub derive_eq: bool,
     /// Whether to generate a piecewise inequality operator
@@ -130,6 +184,7 @@ pub struct StructConfig {
 impl Default for StructConfig {
     fn default() -> StructConfig {
         StructConfig {
+            rename_fields: None,
             derive_eq: false,
             derive_neq: false,
             derive_lt: false,
@@ -145,6 +200,8 @@ impl Default for StructConfig {
 #[serde(deny_unknown_fields)]
 #[serde(default)]
 pub struct EnumConfig {
+    /// The rename rule to apply to the name of enum variants
+    pub rename_variants: Option<RenameRule>,
     /// Whether to add a `Sentinel` value at the end of every enum
     /// This is useful in Gecko for IPC serialization
     pub add_sentinel: bool,
@@ -153,6 +210,7 @@ pub struct EnumConfig {
 impl Default for EnumConfig {
     fn default() -> EnumConfig {
         EnumConfig {
+            rename_variants: None,
             add_sentinel: false,
         }
     }
@@ -209,8 +267,10 @@ impl Config {
                 prefix: Some(String::from("WR_INLINE")),
                 postfix: Some(String::from("WR_FUNC")),
                 args: Layout::Vertical,
+                rename_args: Some(RenameRule::GeckoCase),
             },
             structure: StructConfig {
+                rename_fields: Some(RenameRule::GeckoCase),
                 derive_eq: true,
                 derive_neq: false,
                 derive_lt: false,
@@ -219,6 +279,7 @@ impl Config {
                 derive_gte: false,
             },
             enumeration: EnumConfig {
+                rename_variants: None,
                 add_sentinel: true,
             },
         }
diff --git a/src/bindgen/items.rs b/src/bindgen/items.rs
index dc518c8deebe77a18cb01a18f1547acffc65d881..c1db5eefad29c18521ebae43332cb31ef6e8c378 100644
--- a/src/bindgen/items.rs
+++ b/src/bindgen/items.rs
@@ -6,6 +6,7 @@ use syn::*;
 use bindgen::config::{Config, Layout};
 use bindgen::directive::*;
 use bindgen::library::*;
+use bindgen::rename::*;
 use bindgen::syn_helpers::*;
 use bindgen::writer::*;
 
@@ -368,6 +369,16 @@ impl Function {
         })
     }
 
+    pub fn resolve(&mut self, config: &Config) {
+        if let Some(r) = config.function.rename_args {
+            self.args = self.args.iter()
+                                 .map(|x| (r.apply_to_snake_case(&x.0,
+                                                                 RenameContext::FunctionArg),
+                                           x.1.clone()))
+                                  .collect()
+        }
+    }
+
     pub fn add_deps(&self, library: &Library, out: &mut Vec<PathValue>) {
         if let &Some(ref ret) = &self.ret {
             ret.add_deps(library, out);
@@ -512,6 +523,28 @@ impl Struct {
         })
     }
 
+    pub fn resolve(&mut self, config: &Config) {
+        if let Some(o) = self.directives.list("field-names") {
+            let mut overriden_fields = Vec::new();
+
+            for (i, &(ref name, ref ty)) in self.fields.iter().enumerate() {
+                if i >= o.len() {
+                    overriden_fields.push((name.clone(), ty.clone()));
+                } else {
+                    overriden_fields.push((o[i].clone(), ty.clone()));
+                }
+            }
+
+            self.fields = overriden_fields;
+        } else if let Some(r) = config.structure.rename_fields {
+            self.fields = self.fields.iter()
+                                     .map(|x| (r.apply_to_snake_case(&x.0,
+                                                                     RenameContext::StructMember),
+                                               x.1.clone()))
+                                     .collect();
+        }
+    }
+
     pub fn add_deps(&self, library: &Library, out: &mut Vec<PathValue>) {
         for &(_, ref ty) in &self.fields {
             ty.add_deps_with_generics(&self.generic_params, library, out);
@@ -521,29 +554,10 @@ impl Struct {
     pub fn write<F: Write>(&self, config: &Config, out: &mut Writer<F>) {
         assert!(self.generic_params.is_empty());
 
-        // This needs to be done here because `type` specialization may
-        // provide an alternative list of directives to use for renaming
-        let fields = match self.directives.list("field-names") {
-            Some(overrides) => {
-                let mut overriden_fields = Vec::new();
-
-                for (i, &(ref name, ref ty)) in self.fields.iter().enumerate() {
-                    if i >= overrides.len() {
-                        overriden_fields.push((name.clone(), ty.clone()));
-                    } else {
-                        overriden_fields.push((overrides[i].clone(), ty.clone()));
-                    }
-                }
-
-                overriden_fields
-            }
-            _ => self.fields.clone(),
-        };
-
         out.write(&format!("struct {}", self.name));
         out.open_brace();
 
-        for (i, &(ref name, ref ty)) in fields.iter().enumerate() {
+        for (i, &(ref name, ref ty)) in self.fields.iter().enumerate() {
             if i != 0 {
                 out.new_line()
             }
@@ -560,36 +574,36 @@ impl Struct {
                 out.write(&format!("bool operator{}(const {}& aOther) const", op, self.name));
                 out.open_brace();
                 out.write("return ");
-                out.write_aligned_list(fields.iter()
-                                             .map(|x| format!("{} {} aOther.{}", x.0, op, x.0))
-                                             .collect(),
+                out.write_aligned_list(self.fields.iter()
+                                                  .map(|x| format!("{} {} aOther.{}", x.0, op, x.0))
+                                                  .collect(),
                                        format!(" {}", conjuc));
                 out.write(";");
                 out.close_brace(false);
             };
 
             if config.structure.derive_eq(&self.directives) &&
-               !fields.is_empty() && fields.iter().all(|x| x.1.can_cmp_eq()) {
+               !self.fields.is_empty() && self.fields.iter().all(|x| x.1.can_cmp_eq()) {
                 emit_op("==", "&&");
             }
             if config.structure.derive_neq(&self.directives) &&
-               !fields.is_empty() && fields.iter().all(|x| x.1.can_cmp_eq()) {
+               !self.fields.is_empty() && self.fields.iter().all(|x| x.1.can_cmp_eq()) {
                 emit_op("!=", "||");
             }
             if config.structure.derive_lt(&self.directives) &&
-               fields.len() == 1 && fields[0].1.can_cmp_order() {
+               self.fields.len() == 1 && self.fields[0].1.can_cmp_order() {
                 emit_op("<", "&&");
             }
             if config.structure.derive_lte(&self.directives) &&
-               fields.len() == 1 && fields[0].1.can_cmp_order() {
+               self.fields.len() == 1 && self.fields[0].1.can_cmp_order() {
                 emit_op("<=", "&&");
             }
             if config.structure.derive_gt(&self.directives) &&
-               fields.len() == 1 && fields[0].1.can_cmp_order() {
+               self.fields.len() == 1 && self.fields[0].1.can_cmp_order() {
                 emit_op(">", "&&");
             }
             if config.structure.derive_gte(&self.directives) &&
-               fields.len() == 1 && fields[0].1.can_cmp_order() {
+               self.fields.len() == 1 && self.fields[0].1.can_cmp_order() {
                 emit_op(">=", "&&");
             }
         }
@@ -682,6 +696,16 @@ impl Enum {
         })
     }
 
+    pub fn resolve(&mut self, config: &Config) {
+        if let Some(r) = config.enumeration.rename_variants {
+            self.values = self.values.iter()
+                                     .map(|x| (r.apply_to_pascal_case(&x.0,
+                                                                      RenameContext::EnumVariant),
+                                               x.1.clone()))
+                                     .collect();
+        }
+    }
+
     pub fn write<F: Write>(&self, config: &Config, out: &mut Writer<F>) {
         let size = match self.repr {
             Repr::U32 => "uint32_t",
diff --git a/src/bindgen/library.rs b/src/bindgen/library.rs
index 3b60934559557b3d255f569f510540e04501f698..758fbe7927aef54185b70a65e66ac2f8973e0f24 100644
--- a/src/bindgen/library.rs
+++ b/src/bindgen/library.rs
@@ -251,6 +251,16 @@ impl<'a> Library<'a> {
             }
         });
 
+        for (_, ref mut s) in &mut library.structs {
+            s.resolve(config);
+        }
+        for (_, ref mut f) in &mut library.functions {
+            f.resolve(config);
+        }
+        for (_, ref mut e) in &mut library.enums {
+            e.resolve(config);
+        }
+
         library
     }
 
diff --git a/src/bindgen/mod.rs b/src/bindgen/mod.rs
index c944378536eec164e02ede55e3179a9c2e467ddd..572cc66890777f1d249d3993fb72fda4ccc89389 100644
--- a/src/bindgen/mod.rs
+++ b/src/bindgen/mod.rs
@@ -1,7 +1,37 @@
+macro_rules! deserialize_enum_str {
+    ($name:ident) => {
+        impl ::serde::Deserialize for $name {
+            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+                where D: ::serde::Deserializer
+            {
+                struct Visitor;
+                impl ::serde::de::Visitor for Visitor {
+                    type Value = $name;
+
+                    fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+                        formatter.write_str("$name")
+                    }
+
+                    fn visit_str<E>(self, v: &str) -> Result<$name, E>
+                        where E: ::serde::de::Error
+                    {
+                        match v.parse::<$name>() {
+                            Ok(v) => Ok(v),
+                            Err(m) => Err(E::custom(m)),
+                        }
+                    }
+                }
+                deserializer.deserialize_str(Visitor)
+            }
+        }
+    }
+}
+
 mod config;
 mod directive;
 mod items;
 mod library;
+mod rename;
 mod rust_lib;
 mod syn_helpers;
 mod writer;
diff --git a/src/bindgen/rename.rs b/src/bindgen/rename.rs
new file mode 100644
index 0000000000000000000000000000000000000000..7fb11ba7f513ce5c2a372941a376acef36debbb5
--- /dev/null
+++ b/src/bindgen/rename.rs
@@ -0,0 +1,166 @@
+use std::str::FromStr;
+
+#[derive(Debug, Clone, Copy)]
+pub enum RenameContext {
+    StructMember,
+    EnumVariant,
+    FunctionArg,
+}
+impl RenameContext {
+    fn to_str(&self) -> &'static str {
+        match *self {
+            RenameContext::StructMember => "m",
+            RenameContext::EnumVariant => "",
+            RenameContext::FunctionArg => "a",
+        }
+    }
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum RenameRule {
+    GeckoCase,
+    LowerCase,
+    UpperCase,
+    PascalCase,
+    CamelCase,
+    SnakeCase,
+    ScreamingSnakeCase,
+}
+
+impl RenameRule {
+    pub fn apply_to_pascal_case(&self, text: &str, context: RenameContext) -> String {
+        if text.len() == 0 {
+            return String::new();
+        }
+
+        match *self {
+            RenameRule::GeckoCase => context.to_str().to_owned() + text,
+            RenameRule::LowerCase => text.to_lowercase(),
+            RenameRule::UpperCase => text.to_uppercase(),
+            RenameRule::PascalCase => text.to_owned(),
+            RenameRule::CamelCase => {
+                text[..1].to_lowercase() + &text[1..]
+            }
+            RenameRule::SnakeCase => {
+                let mut result = String::new();
+                for (i, c) in text.char_indices() {
+                    if c.is_uppercase() && i != 0 {
+                        result.push_str("_");
+                    }
+                    for x in c.to_lowercase() {
+                        result.push(x);
+                    }
+                }
+                result
+            }
+            RenameRule::ScreamingSnakeCase => {
+                // Same as SnakeCase code above, but uses to_uppercase
+                let mut result = String::new();
+                for (i, c) in text.char_indices() {
+                    if c.is_uppercase() && i != 0 {
+                        result.push_str("_");
+                    }
+                    for x in c.to_uppercase() {
+                        result.push(x);
+                    }
+                }
+                result
+            }
+        }
+    }
+
+    pub fn apply_to_snake_case(&self, text: &str, context: RenameContext) -> String {
+        if text.len() == 0 {
+            return String::new();
+        }
+
+        match *self {
+            RenameRule::GeckoCase => {
+                context.to_str().to_owned() +
+                    &RenameRule::PascalCase.apply_to_snake_case(text, context)
+            }
+            RenameRule::LowerCase => text.to_lowercase(),
+            RenameRule::UpperCase => text.to_uppercase(),
+            RenameRule::PascalCase => {
+                let mut result = String::new();
+                let mut is_uppercase = true;
+                for c in text.chars() {
+                    if c == '_' {
+                        is_uppercase = true;
+                        continue;
+                    }
+
+                    if is_uppercase {
+                        for x in c.to_uppercase() {
+                            result.push(x);
+                        }
+                        is_uppercase = false;
+                    } else {
+                        result.push(c);
+                    }
+                }
+                result
+            }
+            RenameRule::CamelCase => {
+                // Same as PascalCase code above, but is_uppercase = false to start
+                let mut result = String::new();
+                let mut is_uppercase = false;
+                for c in text.chars() {
+                    if c == '_' {
+                        is_uppercase = true;
+                        continue;
+                    }
+
+                    if is_uppercase {
+                        for x in c.to_uppercase() {
+                            result.push(x);
+                        }
+                        is_uppercase = false;
+                    } else {
+                        result.push(c);
+                    }
+                }
+                result
+            }
+            RenameRule::SnakeCase => text.to_owned(),
+            RenameRule::ScreamingSnakeCase => text.to_owned().to_uppercase(),
+        }
+    }
+}
+
+impl FromStr for RenameRule {
+    type Err = String;
+
+    fn from_str(s: &str) -> Result<RenameRule, Self::Err> {
+        match s {
+            "mGeckoCase" => Ok(RenameRule::GeckoCase),
+            "GeckoCase" => Ok(RenameRule::GeckoCase),
+            "gecko_case" => Ok(RenameRule::GeckoCase),
+
+            "lowercase" => Ok(RenameRule::LowerCase),
+            "LowerCase" => Ok(RenameRule::LowerCase),
+            "lower_case" => Ok(RenameRule::LowerCase),
+
+            "UPPERCASE" => Ok(RenameRule::UpperCase),
+            "UpperCase" => Ok(RenameRule::UpperCase),
+            "upper_case" => Ok(RenameRule::UpperCase),
+
+            "PascalCase" => Ok(RenameRule::PascalCase),
+            "pascal_case" => Ok(RenameRule::PascalCase),
+
+            "camelCase" => Ok(RenameRule::CamelCase),
+            "CamelCase" => Ok(RenameRule::CamelCase),
+            "camel_case" => Ok(RenameRule::CamelCase),
+
+            "snake_case" => Ok(RenameRule::SnakeCase),
+            "SnakeCase" => Ok(RenameRule::SnakeCase),
+
+            "SCREAMING_SNAKE_CASE" => Ok(RenameRule::ScreamingSnakeCase),
+            "ScreamingSnakeCase" => Ok(RenameRule::ScreamingSnakeCase),
+            "screaming_snake_case" => Ok(RenameRule::ScreamingSnakeCase),
+
+            _ => Err(format!("unrecognized RenameRule: '{}'", s)),
+        }
+    }
+}
+deserialize_enum_str!(RenameRule);