add a #[deriving_serializable]
macro
This commit is contained in:
parent
91d68e256c
commit
eaa1fc26d1
67
bench_log.rs
67
bench_log.rs
@ -11,6 +11,7 @@ use ser::Serializable;
|
||||
use ser;
|
||||
|
||||
#[deriving(Encodable, Decodable)]
|
||||
#[deriving_serializable]
|
||||
struct Http {
|
||||
protocol: HttpProtocol,
|
||||
status: u32,
|
||||
@ -23,28 +24,6 @@ struct Http {
|
||||
request_uri: String,
|
||||
}
|
||||
|
||||
impl ser::Serializable for Http {
|
||||
#[inline]
|
||||
fn serialize<
|
||||
S: ser::Serializer<E>,
|
||||
E
|
||||
>(&self, s: &mut S) -> Result<(), E> {
|
||||
try!(s.serialize_struct_start("Http", 9));
|
||||
|
||||
try!(s.serialize_struct_sep("protocol", &self.protocol));
|
||||
try!(s.serialize_struct_sep("status", &self.status));
|
||||
try!(s.serialize_struct_sep("host_status", &self.host_status));
|
||||
try!(s.serialize_struct_sep("up_status", &self.up_status));
|
||||
try!(s.serialize_struct_sep("method", &self.method));
|
||||
try!(s.serialize_struct_sep("content_type", &self.content_type));
|
||||
try!(s.serialize_struct_sep("user_agent", &self.user_agent));
|
||||
try!(s.serialize_struct_sep("referer", &self.referer));
|
||||
try!(s.serialize_struct_sep("request_uri", &self.request_uri));
|
||||
|
||||
s.serialize_struct_end()
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Encodable, Decodable)]
|
||||
enum HttpProtocol {
|
||||
HTTP_PROTOCOL_UNKNOWN,
|
||||
@ -106,6 +85,7 @@ impl ser::Serializable for CacheStatus {
|
||||
}
|
||||
|
||||
#[deriving(Encodable, Decodable)]
|
||||
#[deriving_serializable]
|
||||
struct Origin {
|
||||
ip: String,
|
||||
port: u32,
|
||||
@ -113,23 +93,6 @@ struct Origin {
|
||||
protocol: OriginProtocol,
|
||||
}
|
||||
|
||||
impl ser::Serializable for Origin {
|
||||
#[inline]
|
||||
fn serialize<
|
||||
S: ser::Serializer<E>,
|
||||
E
|
||||
>(&self, s: &mut S) -> Result<(), E> {
|
||||
try!(s.serialize_struct_start("Http", 4));
|
||||
|
||||
try!(s.serialize_struct_sep("ip", &self.ip));
|
||||
try!(s.serialize_struct_sep("port", &self.port));
|
||||
try!(s.serialize_struct_sep("hostname", &self.hostname));
|
||||
try!(s.serialize_struct_sep("protocol", &self.protocol));
|
||||
|
||||
s.serialize_struct_end()
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Encodable, Decodable)]
|
||||
enum OriginProtocol {
|
||||
ORIGIN_PROTOCOL_UNKNOWN,
|
||||
@ -437,6 +400,7 @@ impl ser::Serializable for Country {
|
||||
}
|
||||
|
||||
#[deriving(Encodable, Decodable)]
|
||||
#[deriving_serializable]
|
||||
struct Log {
|
||||
timestamp: i64,
|
||||
zone_id: u32,
|
||||
@ -452,31 +416,6 @@ struct Log {
|
||||
ray_id: String,
|
||||
}
|
||||
|
||||
impl ser::Serializable for Log {
|
||||
#[inline]
|
||||
fn serialize<
|
||||
S: ser::Serializer<E>,
|
||||
E
|
||||
>(&self, s: &mut S) -> Result<(), E> {
|
||||
try!(s.serialize_struct_start("Log", 12));
|
||||
|
||||
try!(s.serialize_struct_sep("timestamp", &self.timestamp));
|
||||
try!(s.serialize_struct_sep("zone_id", &self.zone_id));
|
||||
try!(s.serialize_struct_sep("zone_plan", &self.zone_plan));
|
||||
try!(s.serialize_struct_sep("http", &self.http));
|
||||
try!(s.serialize_struct_sep("origin", &self.origin));
|
||||
try!(s.serialize_struct_sep("country", &self.country));
|
||||
try!(s.serialize_struct_sep("cache_status", &self.cache_status));
|
||||
try!(s.serialize_struct_sep("server_ip", &self.server_ip));
|
||||
try!(s.serialize_struct_sep("server_name", &self.server_name));
|
||||
try!(s.serialize_struct_sep("remote_ip", &self.remote_ip));
|
||||
try!(s.serialize_struct_sep("bytes_dlv", &self.bytes_dlv));
|
||||
try!(s.serialize_struct_sep("ray_id", &self.ray_id));
|
||||
|
||||
s.serialize_struct_end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Log {
|
||||
fn new() -> Log {
|
||||
Log {
|
||||
|
54
ser.rs
54
ser.rs
@ -272,78 +272,30 @@ mod tests {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[deriving(Clone, PartialEq, Show, Decodable)]
|
||||
#[deriving_serializable]
|
||||
struct Inner {
|
||||
a: (),
|
||||
b: uint,
|
||||
c: HashMap<String, Option<char>>,
|
||||
}
|
||||
|
||||
impl Serializable for Inner {
|
||||
#[inline]
|
||||
fn serialize<
|
||||
S: Serializer<E>,
|
||||
E
|
||||
>(&self, s: &mut S) -> Result<(), E> {
|
||||
try!(s.serialize_struct_start("Inner", 3));
|
||||
|
||||
try!(s.serialize_struct_sep("a", &self.a));
|
||||
try!(s.serialize_struct_sep("b", &self.b));
|
||||
try!(s.serialize_struct_sep("c", &self.c));
|
||||
|
||||
s.serialize_struct_end()
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[deriving(Clone, PartialEq, Show, Decodable)]
|
||||
#[deriving_serializable]
|
||||
struct Outer {
|
||||
inner: Vec<Inner>,
|
||||
}
|
||||
|
||||
impl Serializable for Outer {
|
||||
#[inline]
|
||||
fn serialize<
|
||||
S: Serializer<E>,
|
||||
E
|
||||
>(&self, s: &mut S) -> Result<(), E> {
|
||||
try!(s.serialize_struct_start("Outer", 1));
|
||||
|
||||
try!(s.serialize_struct_sep("inner", &self.inner));
|
||||
|
||||
s.serialize_struct_end()
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[deriving(Clone, PartialEq, Show, Decodable)]
|
||||
#[deriving_serializable]
|
||||
enum Animal {
|
||||
Dog,
|
||||
Frog(String, int)
|
||||
}
|
||||
|
||||
impl Serializable for Animal {
|
||||
#[inline]
|
||||
fn serialize<
|
||||
S: Serializer<E>,
|
||||
E
|
||||
>(&self, s: &mut S) -> Result<(), E> {
|
||||
match *self {
|
||||
Dog => {
|
||||
try!(s.serialize_enum_start("Animal", "Dog", 0));
|
||||
}
|
||||
Frog(ref x0, ref x1) => {
|
||||
try!(s.serialize_enum_start("Animal", "Frog", 2));
|
||||
|
||||
try!(s.serialize_enum_sep(x0));
|
||||
try!(s.serialize_enum_sep(x1));
|
||||
}
|
||||
}
|
||||
s.serialize_enum_end()
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[deriving(Clone, PartialEq, Show)]
|
||||
|
11
serde.rs
11
serde.rs
@ -1,4 +1,6 @@
|
||||
#![feature(macro_rules, phase)]
|
||||
#![crate_type = "dylib"]
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
// test harness access
|
||||
#[cfg(test)]
|
||||
@ -7,6 +9,9 @@ extern crate test;
|
||||
#[phase(plugin, link)]
|
||||
extern crate log;
|
||||
|
||||
#[phase(plugin)]
|
||||
extern crate serde_macros;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate debug;
|
||||
|
||||
@ -34,3 +39,9 @@ pub mod bench_map;
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod bench_log;
|
||||
|
||||
// an inner module so we can use serde_macros.
|
||||
mod serde {
|
||||
pub use de;
|
||||
pub use ser;
|
||||
}
|
||||
|
179
serde_macros.rs
Normal file
179
serde_macros.rs
Normal file
@ -0,0 +1,179 @@
|
||||
#![crate_type = "dylib"]
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
#![feature(plugin_registrar)]
|
||||
|
||||
extern crate syntax;
|
||||
extern crate rustc;
|
||||
|
||||
use std::gc::Gc;
|
||||
|
||||
use syntax::ast::{MetaItem, Item, Expr, MutMutable, LitNil};
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::ext::base::{ExtCtxt, ItemDecorator};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::ext::deriving::generic::{MethodDef, EnumMatching, FieldInfo, Struct, Substructure, TraitDef, combine_substructure};
|
||||
use syntax::ext::deriving::generic::ty::{Borrowed, LifetimeBounds, Literal, Path, Ptr, Tuple, borrowed_explicit_self};
|
||||
use syntax::parse::token;
|
||||
|
||||
use rustc::plugin::Registry;
|
||||
|
||||
#[plugin_registrar]
|
||||
#[doc(hidden)]
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_syntax_extension(
|
||||
token::intern("deriving_serializable"),
|
||||
ItemDecorator(derive_serialize));
|
||||
}
|
||||
|
||||
fn derive_serialize(cx: &mut ExtCtxt,
|
||||
sp: Span,
|
||||
mitem: Gc<MetaItem>,
|
||||
item: Gc<Item>,
|
||||
push: |Gc<ast::Item>|) {
|
||||
let inline = cx.meta_word(sp, token::InternedString::new("inline"));
|
||||
let attrs = vec!(cx.attribute(sp, inline));
|
||||
|
||||
let trait_def = TraitDef {
|
||||
span: sp,
|
||||
attributes: vec!(),
|
||||
path: Path::new(vec!("serde", "ser", "Serializable")),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: LifetimeBounds::empty(),
|
||||
methods: vec!(
|
||||
MethodDef {
|
||||
name: "serialize",
|
||||
generics: LifetimeBounds {
|
||||
lifetimes: Vec::new(),
|
||||
bounds: vec!(("__S", ast::StaticSize, vec!(Path::new_(
|
||||
vec!("serde", "ser", "Serializer"), None,
|
||||
vec!(box Literal(Path::new_local("__E"))), true))),
|
||||
("__E", ast::StaticSize, vec!()))
|
||||
},
|
||||
explicit_self: borrowed_explicit_self(),
|
||||
args: vec!(Ptr(box Literal(Path::new_local("__S")),
|
||||
Borrowed(None, MutMutable))),
|
||||
ret_ty: Literal(Path::new_(vec!("std", "result", "Result"),
|
||||
None,
|
||||
vec!(box Tuple(Vec::new()),
|
||||
box Literal(Path::new_local("__E"))),
|
||||
true)),
|
||||
attributes: attrs,
|
||||
const_nonmatching: true,
|
||||
combine_substructure: combine_substructure(|a, b, c| {
|
||||
serializable_substructure(a, b, c)
|
||||
}),
|
||||
})
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
fn serializable_substructure(cx: &mut ExtCtxt, trait_span: Span,
|
||||
substr: &Substructure) -> Gc<Expr> {
|
||||
let serializer = substr.nonself_args[0];
|
||||
|
||||
return match *substr.fields {
|
||||
Struct(ref fields) => {
|
||||
if fields.is_empty() {
|
||||
// unit structs have no fields and need to return `Ok()`
|
||||
cx.expr_ok(trait_span, cx.expr_lit(trait_span, LitNil))
|
||||
} else {
|
||||
let mut stmts: Vec<Gc<syntax::codemap::Spanned<syntax::ast::Stmt_>>> = Vec::new();
|
||||
|
||||
let call = cx.expr_method_call(
|
||||
trait_span,
|
||||
serializer,
|
||||
cx.ident_of("serialize_struct_start"),
|
||||
vec!(
|
||||
cx.expr_str(trait_span, token::get_ident(substr.type_ident)),
|
||||
cx.expr_uint(trait_span, fields.len()),
|
||||
)
|
||||
);
|
||||
let call = cx.expr_try(trait_span, call);
|
||||
stmts.push(cx.stmt_expr(call));
|
||||
|
||||
let emit_struct_sep = cx.ident_of("serialize_struct_sep");
|
||||
|
||||
for (i, &FieldInfo {
|
||||
name,
|
||||
self_,
|
||||
span,
|
||||
..
|
||||
}) in fields.iter().enumerate() {
|
||||
let name = match name {
|
||||
Some(id) => token::get_ident(id),
|
||||
None => {
|
||||
token::intern_and_get_ident(format!("_field{}",
|
||||
i).as_slice())
|
||||
}
|
||||
};
|
||||
let call = cx.expr_method_call(span,
|
||||
serializer,
|
||||
emit_struct_sep,
|
||||
vec!(
|
||||
cx.expr_str(span, name),
|
||||
cx.expr_addr_of(span, self_),
|
||||
));
|
||||
|
||||
let call = cx.expr_try(span, call);
|
||||
stmts.push(cx.stmt_expr(call));
|
||||
}
|
||||
|
||||
let call = cx.expr_method_call(trait_span,
|
||||
serializer,
|
||||
cx.ident_of("serialize_struct_end"),
|
||||
vec!());
|
||||
|
||||
cx.expr_block(cx.block(trait_span, stmts, Some(call)))
|
||||
}
|
||||
}
|
||||
|
||||
EnumMatching(_idx, variant, ref fields) => {
|
||||
let mut stmts = vec!();
|
||||
|
||||
let call = cx.expr_method_call(
|
||||
trait_span,
|
||||
serializer,
|
||||
cx.ident_of("serialize_enum_start"),
|
||||
vec!(
|
||||
cx.expr_str(trait_span, token::get_ident(substr.type_ident)),
|
||||
cx.expr_str(trait_span, token::get_ident(variant.node.name)),
|
||||
cx.expr_uint(trait_span, fields.len()),
|
||||
)
|
||||
);
|
||||
|
||||
let call = cx.expr_try(trait_span, call);
|
||||
stmts.push(cx.stmt_expr(call));
|
||||
|
||||
let serialize_struct_sep = cx.ident_of("serialize_enum_sep");
|
||||
|
||||
for &FieldInfo { self_, span, .. } in fields.iter() {
|
||||
let call = cx.expr_method_call(
|
||||
span,
|
||||
serializer,
|
||||
serialize_struct_sep,
|
||||
vec!(
|
||||
cx.expr_addr_of(span, self_),
|
||||
)
|
||||
);
|
||||
|
||||
let call = cx.expr_try(span, call);
|
||||
|
||||
stmts.push(cx.stmt_expr(call));
|
||||
}
|
||||
|
||||
let call = cx.expr_method_call(
|
||||
trait_span,
|
||||
serializer,
|
||||
cx.ident_of("serialize_enum_end"),
|
||||
vec!()
|
||||
);
|
||||
|
||||
cx.expr_block(cx.block(trait_span, stmts, Some(call)))
|
||||
}
|
||||
|
||||
_ => cx.bug("expected Struct or EnumMatching in deriving_serializable")
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user