Macros 1.1

This commit is contained in:
David Tolnay 2016-08-28 22:19:17 -07:00
parent 7014c105b4
commit d914fdf67b
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
6 changed files with 148 additions and 37 deletions

View File

@ -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<ast::Attribute> {
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<String, syntex::Error> {
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<S, D>(src: S, dst: D) -> Result<(), syntex::Error>
where S: AsRef<Path>,
@ -44,43 +96,7 @@ pub fn expand<S, D>(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<ast::Attribute> {
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)

18
serde_derive/Cargo.toml Normal file
View File

@ -0,0 +1,18 @@
[package]
name = "serde_derive"
version = "0.8.4"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
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.4", path = "../serde_codegen" }

20
serde_derive/src/lib.rs Normal file
View File

@ -0,0 +1,20 @@
#![feature(rustc_macro)]
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()
}

9
tmp_test/Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "tmp-test"
version = "0.1.0"
authors = ["David Tolnay <dtolnay@gmail.com>"]
[dependencies]
serde = "0.8"
serde_derive = { path = "../serde_derive" }
serde_json = "0.8"

32
tmp_test/build.sh Executable file
View File

@ -0,0 +1,32 @@
#!/bin/bash
set -xeuo pipefail
DIR=$(cd "$(dirname "$0")" && pwd)
export RUSTC=${RUSTC:-$HOME/.local/bin/rustc}
cargo build || true
"$RUSTC" \
"$DIR"/../serde_derive/src/lib.rs \
--crate-name serde_derive \
--crate-type rustc-macro \
-C prefer-dynamic \
-g \
--out-dir "$DIR"/target/debug/deps \
--emit=dep-info,link \
-L dependency="$DIR"/target/debug/deps \
--extern serde_codegen="$DIR"/target/debug/deps/libserde_codegen.rlib
"$RUSTC" \
src/main.rs \
--crate-name tmp_test \
--crate-type bin \
-g \
--out-dir "$DIR"/target/debug \
--emit=dep-info,link \
-L dependency="$DIR"/target/debug/deps \
--extern serde_json=$(echo "$DIR"/target/debug/deps/libserde_json-*.rlib) \
--extern serde=$(echo "$DIR"/target/debug/deps/libserde-*.rlib) \
--extern serde_derive="$DIR"/target/debug/deps/libserde_derive.so

16
tmp_test/src/main.rs Normal file
View File

@ -0,0 +1,16 @@
#![feature(rustc_macro)]
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[derive(Serialize)]
enum Macros {
#[serde(rename = "macros 1.1")]
OnePointOne,
}
fn main() {
let s = Macros::OnePointOne;
println!("{}", serde_json::to_string(&s).unwrap());
}