diff --git a/serde_codegen/src/lib.rs b/serde_codegen/src/lib.rs index fcdc6f4e..55318af6 100644 --- a/serde_codegen/src/lib.rs +++ b/serde_codegen/src/lib.rs @@ -35,6 +35,58 @@ include!(concat!(env!("OUT_DIR"), "/lib.rs")); #[cfg(not(feature = "with-syntex"))] include!("lib.rs.in"); +#[cfg(feature = "with-syntex")] +fn syntex_registry() -> syntex::Registry { + use syntax::{ast, fold}; + + /// Strip the serde attributes from the crate. + #[cfg(feature = "with-syntex")] + fn strip_attributes(krate: ast::Crate) -> ast::Crate { + /// Helper folder that strips the serde attributes after the extensions have been expanded. + struct StripAttributeFolder; + + impl fold::Folder for StripAttributeFolder { + fn fold_attribute(&mut self, attr: ast::Attribute) -> Option { + match attr.node.value.node { + ast::MetaItemKind::List(ref n, _) if n == &"serde" => { return None; } + _ => {} + } + + Some(attr) + } + + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) + } + } + + fold::Folder::fold_crate(&mut StripAttributeFolder, krate) + } + + let mut reg = syntex::Registry::new(); + + reg.add_attr("feature(custom_derive)"); + reg.add_attr("feature(custom_attribute)"); + + reg.add_decorator("derive_Serialize", ser::expand_derive_serialize); + reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize); + + reg.add_post_expansion_pass(strip_attributes); + + reg +} + +#[cfg(feature = "with-syntex")] +pub fn expand_str(src: &str) -> Result { + let src = src.to_owned(); + + let expand_thread = move || { + syntex_registry().expand_str("", "", &src) + }; + + syntex::with_extra_stack(expand_thread) +} + #[cfg(feature = "with-syntex")] pub fn expand(src: S, dst: D) -> Result<(), syntex::Error> where S: AsRef, @@ -44,43 +96,7 @@ pub fn expand(src: S, dst: D) -> Result<(), syntex::Error> let dst = dst.as_ref().to_owned(); let expand_thread = move || { - use syntax::{ast, fold}; - - /// Strip the serde attributes from the crate. - #[cfg(feature = "with-syntex")] - fn strip_attributes(krate: ast::Crate) -> ast::Crate { - /// Helper folder that strips the serde attributes after the extensions have been expanded. - struct StripAttributeFolder; - - impl fold::Folder for StripAttributeFolder { - fn fold_attribute(&mut self, attr: ast::Attribute) -> Option { - match attr.node.value.node { - ast::MetaItemKind::List(ref n, _) if n == &"serde" => { return None; } - _ => {} - } - - Some(attr) - } - - fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(mac, self) - } - } - - fold::Folder::fold_crate(&mut StripAttributeFolder, krate) - } - - let mut reg = syntex::Registry::new(); - - reg.add_attr("feature(custom_derive)"); - reg.add_attr("feature(custom_attribute)"); - - reg.add_decorator("derive_Serialize", ser::expand_derive_serialize); - reg.add_decorator("derive_Deserialize", de::expand_derive_deserialize); - - reg.add_post_expansion_pass(strip_attributes); - - reg.expand("", src, dst) + syntex_registry().expand("", src, dst) }; syntex::with_extra_stack(expand_thread) diff --git a/serde_derive/Cargo.toml b/serde_derive/Cargo.toml new file mode 100644 index 00000000..314080d1 --- /dev/null +++ b/serde_derive/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "serde_derive" +version = "0.8.5" +authors = ["Erick Tryzelaar "] +license = "MIT/Apache-2.0" +description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]" +homepage = "https://serde.rs" +repository = "https://github.com/serde-rs/serde" +documentation = "https://serde.rs/codegen.html" +keywords = ["serde", "serialization"] +include = ["Cargo.toml", "src/**/*.rs"] + +[lib] +name = "serde_derive" +rustc-macro = true + +[dependencies] +serde_codegen = { version = "=0.8.5", path = "../serde_codegen" } + +[dev-dependencies] +fnv = "1.0" +serde = { version = "0.8.5", path = "../serde" } +serde_test = { version = "0.8.5", path = "../serde_test" } diff --git a/serde_derive/src/lib.rs b/serde_derive/src/lib.rs new file mode 100644 index 00000000..aa7bba60 --- /dev/null +++ b/serde_derive/src/lib.rs @@ -0,0 +1,21 @@ +#![feature(rustc_macro, rustc_macro_lib)] +#![cfg(not(test))] + +extern crate rustc_macro; +extern crate serde_codegen; + +use rustc_macro::TokenStream; + +#[rustc_macro_derive(Serialize)] +pub fn derive_serialize(input: TokenStream) -> TokenStream { + let item = format!("#[derive(Serialize)]\n{}", input); + let expanded = serde_codegen::expand_str(&item).unwrap(); + expanded.parse().unwrap() +} + +#[rustc_macro_derive(Deserialize)] +pub fn derive_deserialize(input: TokenStream) -> TokenStream { + let item = format!("#[derive(Deserialize)]\n{}", input); + let expanded = serde_codegen::expand_str(&item).unwrap(); + expanded.parse().unwrap() +} diff --git a/serde_derive/tests/test.rs b/serde_derive/tests/test.rs new file mode 100644 index 00000000..ff8ac572 --- /dev/null +++ b/serde_derive/tests/test.rs @@ -0,0 +1,8 @@ +#![feature(test, rustc_macro, rustc_attrs)] + +#[macro_use] +extern crate serde_derive; + +extern crate test; + +include!("../../testing/tests/test.rs.in");