From 3fac47e01cbb10c2b6c519f354e9ce1f3792e567 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Wed, 18 Feb 2015 22:59:16 -0800 Subject: [PATCH] Fix #[derive_serialize] for enums --- serde2/Cargo.toml | 4 - serde2/serde2_macros/Cargo.toml | 3 +- serde2/serde2_macros/src/lib.rs | 305 +++++++++++++--- serde2/src/bin.rs | 620 -------------------------------- serde2/src/de.rs | 23 +- serde2/src/json/de.rs | 113 +++--- serde2/src/json/mod.rs | 9 +- serde2/src/json/ser.rs | 18 +- serde2/src/json/value.rs | 213 +++++++++-- serde2/src/lib.rs | 5 +- 10 files changed, 527 insertions(+), 786 deletions(-) delete mode 100644 serde2/src/bin.rs diff --git a/serde2/Cargo.toml b/serde2/Cargo.toml index 23997a64..d72444a8 100644 --- a/serde2/Cargo.toml +++ b/serde2/Cargo.toml @@ -6,10 +6,6 @@ authors = ["Erick Tryzelaar "] [lib] name = "serde2" -#[[bin]] -#name = "serde2" -#path = "src/bin.rs" - [dependencies] rustc-serialize = "*" diff --git a/serde2/serde2_macros/Cargo.toml b/serde2/serde2_macros/Cargo.toml index ce207c55..d2b7e6e1 100644 --- a/serde2/serde2_macros/Cargo.toml +++ b/serde2/serde2_macros/Cargo.toml @@ -3,7 +3,6 @@ name = "serde2_macros" version = "0.1.0" authors = ["Erick Tryzelaar "] -[[lib]] +[lib] name = "serde2_macros" -path = "src/lib.rs" plugin = true diff --git a/serde2/serde2_macros/src/lib.rs b/serde2/serde2_macros/src/lib.rs index 49db6680..e0dd752b 100644 --- a/serde2/serde2_macros/src/lib.rs +++ b/serde2/serde2_macros/src/lib.rs @@ -52,12 +52,13 @@ pub fn plugin_registrar(reg: &mut Registry) { Decorator(Box::new(expand_derive_deserialize))); } -fn expand_derive_serialize<>(cx: &mut ExtCtxt, - sp: Span, - mitem: &MetaItem, - item: &Item, - mut push: Box)>) -{ +fn expand_derive_serialize( + cx: &mut ExtCtxt, + sp: Span, + mitem: &MetaItem, + item: &Item, + mut push: Box)> +) { let inline = cx.meta_word(sp, token::InternedString::new("inline")); let attrs = vec!(cx.attribute(sp, inline)); @@ -103,7 +104,7 @@ fn expand_derive_serialize<>(cx: &mut ExtCtxt, ), attributes: attrs, combine_substructure: combine_substructure(Box::new(|a, b, c| { - serialize_substructure(a, b, c) + serialize_substructure(a, b, c, item) })), } ] @@ -112,11 +113,14 @@ fn expand_derive_serialize<>(cx: &mut ExtCtxt, trait_def.expand(cx, mitem, item, |item| push(item)) } -fn serialize_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> P { +fn serialize_substructure(cx: &ExtCtxt, + span: Span, + substr: &Substructure, + item: &Item) -> P { let visitor = substr.nonself_args[0].clone(); - match *substr.fields { - Struct(ref fields) => { + match (&item.node, &*substr.fields) { + (&ast::ItemStruct(..), &Struct(ref fields)) => { if fields.is_empty() { serialize_tuple_struct(cx) } else { @@ -124,8 +128,14 @@ fn serialize_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> P< } } - EnumMatching(_idx, variant, ref fields) => { - serialize_enum(cx, span, visitor, substr.type_ident, variant, fields) + (&ast::ItemEnum(_, ref generics), &EnumMatching(_idx, variant, ref fields)) => { + serialize_enum(cx, + span, + visitor, + substr.type_ident, + variant, + &fields[], + generics) } _ => cx.bug("expected Struct or EnumMatching in derive_serialize") @@ -141,8 +151,7 @@ fn serialize_struct(cx: &ExtCtxt, span: Span, visitor: P, type_ident: Ident, - fields: &Vec) -> P { - + fields: &[FieldInfo]) -> P { let type_name = cx.expr_str( span, token::get_ident(type_ident)); @@ -203,44 +212,258 @@ fn serialize_struct(cx: &ExtCtxt, }) } -fn serialize_enum(cx: &ExtCtxt, - span: Span, - visitor: P, - type_ident: Ident, - variant: &ast::Variant, - fields: &Vec) -> P { - let type_name = cx.expr_str( - span, - token::get_ident(type_ident) - ); - let variant_name = cx.expr_str( - span, - token::get_ident(variant.node.name) + + + +fn serialize_enum( + cx: &ExtCtxt, + span: Span, + visitor: P, + type_ident: Ident, + variant: &ast::Variant, + fields: &[FieldInfo], + generics: &ast::Generics, +) -> P { + let type_name = cx.expr_str(span, token::get_ident(type_ident)); + let variant_ident = variant.node.name; + let variant_name = cx.expr_str(span, token::get_ident(variant_ident)); + + if fields.is_empty() { + quote_expr!(cx, + ::serde2::ser::Visitor::visit_enum_unit( + $visitor, + $type_name, + $variant_name) + ) + } else { + serialize_variant( + cx, + span, + visitor, + type_name, + variant_name, + generics, + variant, + fields) + } +} + + +fn serialize_variant( + cx: &ExtCtxt, + span: Span, + visitor: P, + type_name: P, + variant_name: P, + generics: &ast::Generics, + variant: &ast::Variant, + fields: &[FieldInfo], +) -> P { + // We'll take a reference to the values in the variant, so we need a new lifetime. + let lifetimes = generics.lifetimes.iter() + .map(|lifetime_def| lifetime_def.lifetime.clone()) + .collect(); + + let mut generics = generics.clone(); + generics.lifetimes.push( + cx.lifetime_def( + span, + cx.name_of("'__a"), + lifetimes + ) ); + + let ( + trait_name, + visitor_method_name, + tys, + ): (Ident, Ident, Vec>) = match variant.node.kind { + ast::TupleVariantKind(ref args) => { + ( + cx.ident_of("SeqVisitor"), + cx.ident_of("visit_enum_seq"), + args.iter() + .map(|arg| arg.ty.clone()) + .collect() + ) + } + + ast::StructVariantKind(ref struct_def) => { + ( + cx.ident_of("SeqVisitor"), + cx.ident_of("visit_enum_seq"), + struct_def.fields.iter() + .map(|field| field.node.ty.clone()) + .collect() + ) + } + }; + let len = fields.len(); - let stmts: Vec> = fields.iter() - .map(|&FieldInfo { ref self_, .. }| { - quote_stmt!( - cx, - try!($visitor.serialize_enum_elt(&$self_)) + let visitor_field_names: Vec = (0 .. len) + .map(|i| token::str_to_ident(&format!("field{}", i))) + .collect(); + + let mut visitor_fields = vec![ + respan( + span, + ast::StructField_ { + kind: ast::NamedField( + cx.ident_of("state"), + ast::Visibility::Inherited, + ), + id: ast::DUMMY_NODE_ID, + ty: cx.ty_ident(span, cx.ident_of("u32")), + attrs: Vec::new(), + } + ), + ]; + + visitor_fields.extend( + visitor_field_names.iter() + .zip(tys.iter()) + .map(|(name, ty)| { + respan( + span, + ast::StructField_ { + kind: ast::NamedField( + *name, + ast::Visibility::Inherited, + ), + id: ast::DUMMY_NODE_ID, + ty: cx.ty_rptr( + span, + ty.clone(), + Some(cx.lifetime(span, cx.name_of("'__a"))), + ast::MutImmutable, + ), + attrs: Vec::new(), + } + ) + }) + ); + + let visitor_ident = cx.ident_of("__Visitor"); + + let visitor_struct = cx.item_struct_poly( + span, + visitor_ident, + ast::StructDef { + fields: visitor_fields, + ctor_id: None, + }, + generics, + ); + + let mut visitor_field_exprs = vec![ + cx.field_imm( + span, + cx.ident_of("state"), + quote_expr!(cx, 0), + ), + ]; + + visitor_field_exprs.extend( + visitor_field_names.iter() + .zip(fields.iter()) + .map(|(name, field)| { + let e = cx.expr_addr_of( + span, + field.self_.clone(), + ); + + cx.field_imm(span, *name, e) + }) + ); + + let visitor_expr = cx.expr_struct( + span, + cx.path_ident(span, visitor_ident), + visitor_field_exprs); + + let mut first = true; + + let visitor_arms: Vec = visitor_field_names.iter() + .zip(fields.iter()) + .enumerate() + .map(|(state, (name, field))| { + let field_expr = cx.expr_field_access( + span, + cx.expr_self(span), + *name, + ); + + let visit_expr = match field.name { + Some(real_name) => { + let real_name = cx.expr_str(span, token::get_ident(real_name)); + quote_expr!(cx, + ::serde2::ser::Visitor::visit_map_elt( + visitor, + $first, + $real_name, + $field_expr, + ) + ) + } + None => { + quote_expr!(cx, + ::serde2::ser::Visitor::visit_seq_elt( + visitor, + $first, + $field_expr, + ) + ) + } + }; + + first = false; + + let state = state as u32; + + quote_arm!(cx, + $state => { + self.state += 1; + Ok(Some(try!($visit_expr))) + } ) }) .collect(); quote_expr!(cx, { - try!($visitor.serialize_enum_start($type_name, $variant_name, $len)); - $stmts - $visitor.serialize_enum_end() + $visitor_struct + + impl<'__a> ::serde2::ser::$trait_name for __Visitor<'__a> { + fn visit< + V: ::serde2::ser::Visitor, + >(&mut self, visitor: &mut V) -> Result, V::Error> { + match self.state { + $visitor_arms + _ => Ok(None), + } + } + + fn size_hint(&self) -> (usize, Option) { + ($len - self.state as usize, Some($len - self.state as usize)) + } + } + + ::serde2::ser::Visitor::$visitor_method_name( + $visitor, + $type_name, + $variant_name, + $visitor_expr, + ) }) } -pub fn expand_derive_deserialize(cx: &mut ExtCtxt, - sp: Span, - mitem: &MetaItem, - item: &Item, - mut push: Box)>) -{ +pub fn expand_derive_deserialize( + cx: &mut ExtCtxt, + sp: Span, + mitem: &MetaItem, + item: &Item, + mut push: Box)> +) { let inline = cx.meta_word(sp, token::InternedString::new("inline")); let attrs = vec!(cx.attribute(sp, inline)); diff --git a/serde2/src/bin.rs b/serde2/src/bin.rs deleted file mode 100644 index 9fce9f29..00000000 --- a/serde2/src/bin.rs +++ /dev/null @@ -1,620 +0,0 @@ -extern crate serde2; - -use std::collections::HashMap; -use std::option; -use std::string; - -use serde2::de; -use serde2::de::{Deserialize, Deserializer}; - -#[derive(Show)] -pub enum Token { - Null, - Int(int), - String(string::String), - Option(bool), - SeqStart(uint), - MapStart(uint), - End, -} - -#[derive(Show)] -enum Error { - SyntaxError, - EndOfStreamError, -} - -impl de::Error for Error { - fn syntax_error() -> Error { - Error::SyntaxError - } - - fn end_of_stream_error() -> Error { - Error::EndOfStreamError - } -} - -/////////////////////////////////////////////////////////////////////////////// - -struct MyDeserializer { - tokens: Iter, - peeked: option::Option, -} - -impl> MyDeserializer { - pub fn new(tokens: Iter) -> MyDeserializer { - MyDeserializer { - tokens: tokens, - peeked: None, - } - } - - fn next(&mut self) -> option::Option { - match self.peeked.take() { - Some(token) => { return Some(token); } - None => { } - } - - self.tokens.next() - } - - fn peek<'a>(&'a mut self) -> option::Option<&'a Token> { - match self.peeked { - Some(_) => { } - None => { self.peeked = self.tokens.next(); } - } - - self.peeked.as_ref() - } -} - -impl> Deserializer for MyDeserializer { - fn visit< - R, - V: de::Visitor, R, Error>, - >(&mut self, visitor: &mut V) -> Result { - use serde2::de::Error; - - match self.next() { - Some(Token::Null) => { - visitor.visit_null() - } - Some(Token::Int(v)) => { - visitor.visit_int(v) - } - Some(Token::String(v)) => { - visitor.visit_string(v) - } - Some(Token::Option(is_some)) => { - visitor.visit_option(MyOptionVisitor { d: self, is_some: is_some }) - } - Some(Token::SeqStart(len)) => { - visitor.visit_seq(MySeqVisitor { d: self, len: len }) - } - Some(Token::MapStart(len)) => { - visitor.visit_map(MyMapVisitor { d: self, len: len }) - } - Some(Token::End) => { - Err(Error::syntax_error()) - } - None => { - Err(Error::end_of_stream_error()) - } - } - } - - fn visit_option< - R, - V: de::Visitor, R, Error>, - >(&mut self, visitor: &mut V) -> Result { - match self.peek() { - Some(&Token::Null) => { - self.next(); - visitor.visit_option(MyOptionVisitor { - d: self, - is_some: false, - }) - } - Some(&Token::Option(is_some)) => { - self.next(); - visitor.visit_option(MyOptionVisitor { - d: self, - is_some: is_some, - }) - } - _ => { - visitor.visit_option(MyOptionVisitor { - d: self, - is_some: true, - }) - } - } - } -} - -struct MyOptionVisitor<'a, Iter: 'a> { - d: &'a mut MyDeserializer, - is_some: bool, -} - -impl< - 'a, - Iter: Iterator, -> de::OptionVisitor, Error> for MyOptionVisitor<'a, Iter> { - fn visit< - T: Deserialize, Error>, - >(&mut self) -> Result, Error> { - if self.is_some { - self.is_some = false; - let value = try!(Deserialize::deserialize(self.d)); - Ok(Some(value)) - } else { - Ok(None) - } - } -} - -struct MySeqVisitor<'a, Iter: 'a> { - d: &'a mut MyDeserializer, - len: uint, -} - -impl< - 'a, - Iter: Iterator, -> de::SeqVisitor, Error> for MySeqVisitor<'a, Iter> { - fn visit< - T: Deserialize, Error> - >(&mut self) -> Result, Error> { - use serde2::de::Error; - - match self.d.peek() { - Some(&Token::End) => { - self.d.next(); - Ok(None) - } - Some(_) => { - self.len -= 1; - let value = try!(Deserialize::deserialize(self.d)); - Ok(Some(value)) - } - None => { - Err(Error::syntax_error()) - } - } - } - - fn end(&mut self) -> Result<(), Error> { - use serde2::de::Error; - - match self.d.next() { - Some(Token::End) => Ok(()), - Some(_) => Err(Error::syntax_error()), - None => Err(Error::end_of_stream_error()), - } - } - - fn size_hint(&self) -> (uint, option::Option) { - (self.len, Some(self.len)) - } -} - -struct MyMapVisitor<'a, Iter: 'a> { - d: &'a mut MyDeserializer, - len: uint, -} - -impl< - 'a, - Iter: Iterator, -> de::MapVisitor, Error> for MyMapVisitor<'a, Iter> { - fn visit_key< - K: Deserialize, Error>, - >(&mut self) -> Result, Error> { - use serde2::de::Error; - - match self.d.peek() { - Some(&Token::End) => { - self.d.next(); - Ok(None) - } - Some(_) => { - self.len -= 1; - - Ok(Some(try!(Deserialize::deserialize(self.d)))) - } - None => { - Err(Error::syntax_error()) - } - } - } - - fn visit_value< - V: Deserialize, Error>, - >(&mut self) -> Result { - Ok(try!(Deserialize::deserialize(self.d))) - } - - fn end(&mut self) -> Result<(), Error> { - use serde2::de::Error; - - match self.d.next() { - Some(Token::End) => Ok(()), - Some(_) => Err(Error::syntax_error()), - None => Err(Error::end_of_stream_error()), - } - } - - fn size_hint(&self) -> (uint, option::Option) { - (self.len, Some(self.len)) - } -} - -/////////////////////////////////////////////////////////////////////////////// - -mod json { - use std::collections::BTreeMap; - use serde2::de; - - #[derive(Show)] - pub enum Value { - Null, - //Bool(bool), - Int(int), - //String(String), - List(Vec), - Map(BTreeMap), - } - - impl< - D: de::Deserializer, - E: de::Error, - > de::Deserialize for Value { - fn deserialize(d: &mut D) -> Result { - struct Visitor; - - impl< - D: de::Deserializer, - E: de::Error, - > de::Visitor for Visitor { - fn visit_null(&mut self) -> Result { - Ok(Value::Null) - } - - fn visit_int(&mut self, v: int) -> Result { - Ok(Value::Int(v)) - } - - /* - fn visit_string(&mut self, _d: &mut D, v: String) -> Result { - Ok(Value::String(v)) - } - */ - - fn visit_option< - Visitor: de::OptionVisitor, - >(&mut self, mut visitor: Visitor) -> Result { - match try!(visitor.visit()) { - Some(value) => Ok(value), - None => Ok(Value::Null), - } - } - - fn visit_seq< - Visitor: de::SeqVisitor, - >(&mut self, mut visitor: Visitor) -> Result { - let (len, _) = visitor.size_hint(); - let mut values = Vec::with_capacity(len); - - loop { - match try!(visitor.visit()) { - Some(value) => { - values.push(value); - } - None => { - break; - } - } - } - - Ok(Value::List(values)) - } - - fn visit_map< - Visitor: de::MapVisitor, - >(&mut self, mut visitor: Visitor) -> Result { - let mut values = BTreeMap::new(); - - loop { - match try!(visitor.visit()) { - Some((key, value)) => { - values.insert(key, value); - } - None => { - break; - } - } - } - - Ok(Value::Map(values)) - } - } - - d.visit(&mut Visitor) - } - } -} - -/////////////////////////////////////////////////////////////////////////////// - -pub fn main() { - let tokens = vec!( - Token::SeqStart(2), - Token::Int(1), - Token::Int(2), - Token::End, - ); - let mut state = MyDeserializer::new(tokens.into_iter()); - - let v: Result, Error> = Deserialize::deserialize(&mut state); - println!("vec: {:?}", v); - - //// - - let tokens = vec!( - Token::SeqStart(2), - Token::Int(3), - Token::Int(4), - Token::End, - ); - let mut state = MyDeserializer::new(tokens.into_iter()); - - let v: Result<(int, int), Error> = Deserialize::deserialize(&mut state); - println!("tuple: {:?}", v); - - //// - - let tokens = vec!( - Token::SeqStart(2), - Token::Int(5), - Token::Int(6), - Token::End, - ); - let mut state = MyDeserializer::new(tokens.into_iter()); - - let v: Result = Deserialize::deserialize(&mut state); - println!("value: {:?}", v); - - //// - - let tokens = vec!( - Token::Option(true), - Token::Int(7), - ); - let mut state = MyDeserializer::new(tokens.into_iter()); - - let v: Result, Error> = Deserialize::deserialize(&mut state); - println!("optiony: {:?}", v); - - //// - - let tokens = vec!( - Token::Option(false), - ); - let mut state = MyDeserializer::new(tokens.into_iter()); - - let v: Result, Error> = Deserialize::deserialize(&mut state); - println!("optiony: {:?}", v); - - //// - - let tokens = vec!( - Token::Option(true), - Token::Int(8), - ); - let mut state = MyDeserializer::new(tokens.into_iter()); - - let v: Result = Deserialize::deserialize(&mut state); - println!("optiony value: {:?}", v); - - //// - - let tokens = vec!( - Token::Option(false), - ); - let mut state = MyDeserializer::new(tokens.into_iter()); - - let v: Result = Deserialize::deserialize(&mut state); - println!("optiony value: {:?}", v); - - //// - - let tokens = vec!( - Token::Int(9), - ); - let mut state = MyDeserializer::new(tokens.into_iter()); - - let v: Result, Error> = Deserialize::deserialize(&mut state); - println!("option: {:?}", v); - - //// - - let tokens = vec!( - Token::Null, - ); - let mut state = MyDeserializer::new(tokens.into_iter()); - - let v: Result, Error> = Deserialize::deserialize(&mut state); - println!("option: {:?}", v); - - //// - - let tokens = vec!( - Token::Int(10), - ); - let mut state = MyDeserializer::new(tokens.into_iter()); - - let v: Result = Deserialize::deserialize(&mut state); - println!("option value: {:?}", v); - - //// - - let tokens = vec!( - Token::Null, - ); - let mut state = MyDeserializer::new(tokens.into_iter()); - - let v: Result = Deserialize::deserialize(&mut state); - println!("option value: {:?}", v); - - //// - - let tokens = vec!( - Token::MapStart(2), - Token::String("a".to_string()), - Token::Int(1), - Token::String("b".to_string()), - Token::Int(2), - Token::End - ); - let mut state = MyDeserializer::new(tokens.into_iter()); - - let v: Result, Error> = Deserialize::deserialize(&mut state); - println!("{:?}", v); - - //// - - let tokens = vec!( - Token::MapStart(2), - Token::String("a".to_string()), - Token::Int(1), - Token::String("b".to_string()), - Token::Int(2), - Token::End - ); - let mut state = MyDeserializer::new(tokens.into_iter()); - - let v: Result = Deserialize::deserialize(&mut state); - println!("{:?}", v); -} - - -/* -use std::collections::BTreeMap; -use serde::{Serialize, GatherTokens}; -use serde::json; - -/////////////////////////////////////////////////////////////////////////////// - -struct Foo { - x: int, - y: int, - z: &'static str, -} - -impl, R> serde::Serialize for Foo { - fn serialize(&self, state: &mut S) -> R { - state.visit_named_map("Foo", FooSerialize { - value: self, - state: 0, - }) - } -} - -struct FooSerialize<'a> { - value: &'a Foo, - state: uint, -} - -impl<'a, S: serde::VisitorState, R> serde::Visitor for FooSerialize<'a> { - fn visit(&mut self, state: &mut S) -> Option { - match self.state { - 0 => { - self.state += 1; - Some(state.visit_map_elt(true, "x", &self.value.x)) - } - 1 => { - self.state += 1; - Some(state.visit_map_elt(false, "y", &self.value.y)) - } - 2 => { - self.state += 1; - Some(state.visit_map_elt(false, "z", &self.value.z)) - } - _ => { - None - } - } - } - - fn size_hint(&self) -> (uint, Option) { - let size = 3 - self.state; - (size, Some(size)) - } -} - -/////////////////////////////////////////////////////////////////////////////// - -fn main() { - let value = 5i; - - let mut s = GatherTokens::new(); - value.serialize(&mut s); - println!("tokens: {:?}", s.unwrap()); - - println!("json: {:?}", json::to_string(&value).unwrap().unwrap()); - println!(""); - - //// - - let value = vec!(1i, 2, 3); - - let mut s = GatherTokens::new(); - value.serialize(&mut s); - println!("tokens: {:?}", s.unwrap()); - - println!("json: {:?}", json::to_string(&value).unwrap().unwrap()); - println!(""); - - //// - - let mut value = BTreeMap::new(); - value.insert("a", 1i); - value.insert("b", 2); - value.insert("c", 3); - - let mut s = GatherTokens::new(); - value.serialize(&mut s); - println!("tokens: {:?}", s.unwrap()); - - println!("json: {:?}", json::to_string(&value).unwrap().unwrap()); - println!(""); - - //// - - /* - println!("{:?}", to_format_vec(&5i)); - println!("{:?}", to_format_string(&5i)); - */ - - let value = Foo { x: 1, y: 2, z: "abc" }; - - let mut s = GatherTokens::new(); - value.serialize(&mut s); - println!("tokens: {:?}", s.unwrap()); - - println!("json: {:?}", json::to_string(&value).unwrap().unwrap()); - println!(""); - - //// - - let value = (1i, "abc"); - - let mut s = GatherTokens::new(); - value.serialize(&mut s); - println!("tokens: {:?}", s.unwrap()); - - println!("json: {:?}", json::to_string(&value).unwrap().unwrap()); - println!(""); -} -*/ diff --git a/serde2/src/de.rs b/serde2/src/de.rs index 20839eb0..0cd139c8 100644 --- a/serde2/src/de.rs +++ b/serde2/src/de.rs @@ -213,9 +213,8 @@ pub trait Visitor { pub trait SeqVisitor { type Error: Error; - fn visit< - T: Deserialize, - >(&mut self) -> Result, Self::Error>; + fn visit(&mut self) -> Result, Self::Error> + where T: Deserialize; fn end(&mut self) -> Result<(), Self::Error>; @@ -229,10 +228,10 @@ pub trait MapVisitor { type Error: Error; #[inline] - fn visit< - K: Deserialize, - V: Deserialize, - >(&mut self) -> Result, Self::Error> { + fn visit(&mut self) -> Result, Self::Error> + where K: Deserialize, + V: Deserialize, + { match try!(self.visit_key()) { Some(key) => { let value = try!(self.visit_value()); @@ -242,13 +241,11 @@ pub trait MapVisitor { } } - fn visit_key< - K: Deserialize, - >(&mut self) -> Result, Self::Error>; + fn visit_key(&mut self) -> Result, Self::Error> + where K: Deserialize; - fn visit_value< - V: Deserialize, - >(&mut self) -> Result; + fn visit_value(&mut self) -> Result + where V: Deserialize; fn end(&mut self) -> Result<(), Self::Error>; diff --git a/serde2/src/json/de.rs b/serde2/src/json/de.rs index 85e23a4d..14ab32f1 100644 --- a/serde2/src/json/de.rs +++ b/serde2/src/json/de.rs @@ -4,10 +4,9 @@ use unicode::str::Utf16Item; use std::str; use de; -use de::Deserializer; use super::error::{Error, ErrorCode}; -pub struct Parser { +pub struct Deserializer { rdr: Iter, ch: Option, line: usize, @@ -15,11 +14,11 @@ pub struct Parser { buf: Vec, } -impl> Parser { +impl> Deserializer { /// Creates the JSON parser. #[inline] - pub fn new(rdr: Iter) -> Parser { - let mut p = Parser { + pub fn new(rdr: Iter) -> Deserializer { + let mut p = Deserializer { rdr: rdr, ch: Some(b'\x00'), line: 1, @@ -111,11 +110,17 @@ impl> Parser { } b'[' => { self.bump(); - visitor.visit_seq(SeqVisitor { parser: self, first: true }) + visitor.visit_seq(SeqVisitor { + de: self, + first: true, + }) } b'{' => { self.bump(); - visitor.visit_map(MapVisitor { parser: self, first: true }) + visitor.visit_map(MapVisitor { + de: self, + first: true, + }) } _ => { Err(self.error(ErrorCode::ExpectedSomeValue)) @@ -377,7 +382,7 @@ impl> Parser { } } -impl> Deserializer for Parser { +impl> de::Deserializer for Deserializer { type Error = Error; #[inline] @@ -389,7 +394,7 @@ impl> Deserializer for Parser { } struct SeqVisitor<'a, Iter: 'a> { - parser: &'a mut Parser, + de: &'a mut Deserializer, first: bool, } @@ -399,43 +404,43 @@ impl<'a, Iter: Iterator> de::SeqVisitor for SeqVisitor<'a, Iter> { fn visit< T: de::Deserialize, >(&mut self) -> Result, Error> { - self.parser.parse_whitespace(); + self.de.parse_whitespace(); - if self.parser.ch_is(b']') { - self.parser.bump(); + if self.de.ch_is(b']') { + self.de.bump(); return Ok(None); } if self.first { self.first = false; } else { - if self.parser.ch_is(b',') { - self.parser.bump(); - } else if self.parser.eof() { - return Err(self.parser.error(ErrorCode::EOFWhileParsingList)); + if self.de.ch_is(b',') { + self.de.bump(); + } else if self.de.eof() { + return Err(self.de.error(ErrorCode::EOFWhileParsingList)); } else { - return Err(self.parser.error(ErrorCode::ExpectedListCommaOrEnd)); + return Err(self.de.error(ErrorCode::ExpectedListCommaOrEnd)); } } - let value = try!(de::Deserialize::deserialize(self.parser)); + let value = try!(de::Deserialize::deserialize(self.de)); Ok(Some(value)) } fn end(&mut self) -> Result<(), Error> { - if self.parser.ch_is(b']') { - self.parser.bump(); + if self.de.ch_is(b']') { + self.de.bump(); Ok(()) - } else if self.parser.eof() { - Err(self.parser.error(ErrorCode::EOFWhileParsingList)) + } else if self.de.eof() { + Err(self.de.error(ErrorCode::EOFWhileParsingList)) } else { - Err(self.parser.error(ErrorCode::TrailingCharacters)) + Err(self.de.error(ErrorCode::TrailingCharacters)) } } } struct MapVisitor<'a, Iter: 'a> { - parser: &'a mut Parser, + de: &'a mut Deserializer, first: bool, } @@ -445,63 +450,63 @@ impl<'a, Iter: Iterator> de::MapVisitor for MapVisitor<'a, Iter> { fn visit_key< K: de::Deserialize, >(&mut self) -> Result, Error> { - self.parser.parse_whitespace(); + self.de.parse_whitespace(); - if self.parser.ch_is(b'}') { - self.parser.bump(); + if self.de.ch_is(b'}') { + self.de.bump(); return Ok(None); } if self.first { self.first = false; } else { - if self.parser.ch_is(b',') { - self.parser.bump(); - self.parser.parse_whitespace(); - } else if self.parser.eof() { - return Err(self.parser.error(ErrorCode::EOFWhileParsingObject)); + if self.de.ch_is(b',') { + self.de.bump(); + self.de.parse_whitespace(); + } else if self.de.eof() { + return Err(self.de.error(ErrorCode::EOFWhileParsingObject)); } else { - return Err(self.parser.error(ErrorCode::ExpectedObjectCommaOrEnd)); + return Err(self.de.error(ErrorCode::ExpectedObjectCommaOrEnd)); } } - if self.parser.eof() { - return Err(self.parser.error(ErrorCode::EOFWhileParsingValue)); + if self.de.eof() { + return Err(self.de.error(ErrorCode::EOFWhileParsingValue)); } - if !self.parser.ch_is(b'"') { - return Err(self.parser.error(ErrorCode::KeyMustBeAString)); + if !self.de.ch_is(b'"') { + return Err(self.de.error(ErrorCode::KeyMustBeAString)); } - Ok(Some(try!(de::Deserialize::deserialize(self.parser)))) + Ok(Some(try!(de::Deserialize::deserialize(self.de)))) } fn visit_value< V: de::Deserialize, >(&mut self) -> Result { - self.parser.parse_whitespace(); + self.de.parse_whitespace(); - if self.parser.ch_is(b':') { - self.parser.bump(); - } else if self.parser.eof() { - return Err(self.parser.error(ErrorCode::EOFWhileParsingObject)); + if self.de.ch_is(b':') { + self.de.bump(); + } else if self.de.eof() { + return Err(self.de.error(ErrorCode::EOFWhileParsingObject)); } else { - return Err(self.parser.error(ErrorCode::ExpectedColon)); + return Err(self.de.error(ErrorCode::ExpectedColon)); } - self.parser.parse_whitespace(); + self.de.parse_whitespace(); - Ok(try!(de::Deserialize::deserialize(self.parser))) + Ok(try!(de::Deserialize::deserialize(self.de))) } fn end(&mut self) -> Result<(), Error> { - if self.parser.ch_is(b']') { - self.parser.bump(); + if self.de.ch_is(b']') { + self.de.bump(); Ok(()) - } else if self.parser.eof() { - Err(self.parser.error(ErrorCode::EOFWhileParsingList)) + } else if self.de.eof() { + Err(self.de.error(ErrorCode::EOFWhileParsingList)) } else { - Err(self.parser.error(ErrorCode::TrailingCharacters)) + Err(self.de.error(ErrorCode::TrailingCharacters)) } } } @@ -511,11 +516,11 @@ pub fn from_iter(iter: I) -> Result where I: Iterator, T: de::Deserialize { - let mut parser = Parser::new(iter); - let value = try!(de::Deserialize::deserialize(&mut parser)); + let mut de = Deserializer::new(iter); + let value = try!(de::Deserialize::deserialize(&mut de)); // Make sure the whole stream has been consumed. - try!(parser.end()); + try!(de.end()); Ok(value) } diff --git a/serde2/src/json/mod.rs b/serde2/src/json/mod.rs index 55b6bab3..faf57ff7 100644 --- a/serde2/src/json/mod.rs +++ b/serde2/src/json/mod.rs @@ -1,8 +1,7 @@ -pub use self::ser::Writer; -pub use self::ser::{to_vec, to_string}; -pub use self::ser::escape_str; - -pub use self::de::from_str; +pub use self::de::{Deserializer, from_str}; +pub use self::error::{Error, ErrorCode}; +pub use self::ser::{Serializer, to_vec, to_string, escape_str}; +pub use self::value::{Value, to_value, from_value}; pub mod builder; pub mod de; diff --git a/serde2/src/json/ser.rs b/serde2/src/json/ser.rs index 96e4604d..7cb27a4d 100644 --- a/serde2/src/json/ser.rs +++ b/serde2/src/json/ser.rs @@ -3,31 +3,31 @@ use std::io; use std::num::{Float, FpCategory}; use std::string::FromUtf8Error; -use ser::{self, Serializer}; +use ser; /// A structure for implementing serialization to JSON. -pub struct Writer { +pub struct Serializer { writer: W, } -impl Writer { +impl Serializer { /// Creates a new JSON visitr whose output will be written to the writer /// specified. #[inline] - pub fn new(writer: W) -> Writer { - Writer { + pub fn new(writer: W) -> Serializer { + Serializer { writer: writer, } } - /// Unwrap the Writer from the Serializer. + /// Unwrap the `Writer` from the `Serializer`. #[inline] pub fn into_inner(self) -> W { self.writer } } -impl ser::Serializer for Writer { +impl ser::Serializer for Serializer { type Value = (); type Error = io::Error; @@ -278,8 +278,8 @@ pub fn to_writer(writer: &mut W, value: &T) -> io::Result<()> where W: io::Write, T: ser::Serialize, { - let mut writer = Writer::new(writer); - try!(writer.visit(value)); + let mut ser = Serializer::new(writer); + try!(ser::Serializer::visit(&mut ser, value)); Ok(()) } diff --git a/serde2/src/json/value.rs b/serde2/src/json/value.rs index 9ad08589..6906544e 100644 --- a/serde2/src/json/value.rs +++ b/serde2/src/json/value.rs @@ -1,9 +1,12 @@ -use std::collections::BTreeMap; +use std::collections::{BTreeMap, btree_map}; use std::fmt; use std::io; use std::str; +use std::vec; -use ser::{self, Serializer}; +use de; +use ser; +use super::error::Error; #[derive(PartialEq)] pub enum Value { @@ -22,27 +25,13 @@ impl ser::Serialize for Value { V: ser::Visitor, >(&self, visitor: &mut V) -> Result { match *self { - Value::Null => { - visitor.visit_unit() - } - Value::Bool(v) => { - visitor.visit_bool(v) - } - Value::I64(v) => { - visitor.visit_i64(v) - } - Value::F64(v) => { - visitor.visit_f64(v) - } - Value::String(ref v) => { - visitor.visit_str(&v) - } - Value::Array(ref v) => { - v.visit(visitor) - } - Value::Object(ref v) => { - v.visit(visitor) - } + Value::Null => visitor.visit_unit(), + Value::Bool(v) => visitor.visit_bool(v), + Value::I64(v) => visitor.visit_i64(v), + Value::F64(v) => visitor.visit_f64(v), + Value::String(ref v) => visitor.visit_str(&v), + Value::Array(ref v) => v.visit(visitor), + Value::Object(ref v) => v.visit(visitor), } } } @@ -72,25 +61,19 @@ impl fmt::Debug for Value { } } -pub fn to_value(value: &T) -> Value where T: ser::Serialize { - let mut writer = Writer::new(); - writer.visit(value).ok().unwrap(); - writer.unwrap() -} - enum State { Value(Value), Array(Vec), Object(BTreeMap), } -pub struct Writer { +pub struct Serializer { state: Vec, } -impl Writer { - pub fn new() -> Writer { - Writer { +impl Serializer { + pub fn new() -> Serializer { + Serializer { state: Vec::with_capacity(4), } } @@ -103,7 +86,7 @@ impl Writer { } } -impl ser::Serializer for Writer { +impl ser::Serializer for Serializer { type Value = (); type Error = (); @@ -116,7 +99,7 @@ impl ser::Serializer for Writer { } } -impl ser::Visitor for Writer { +impl ser::Visitor for Serializer { type Value = (); type Error = (); @@ -264,3 +247,163 @@ impl ser::Visitor for Writer { Ok(()) } } + +pub struct Deserializer { + value: Option, +} + +impl Deserializer { + /// Creates a new deserializer instance for deserializing the specified JSON value. + pub fn new(value: Value) -> Deserializer { + Deserializer { + value: Some(value), + } + } +} + +impl de::Deserializer for Deserializer { + type Error = Error; + + #[inline] + fn visit< + V: de::Visitor, + >(&mut self, visitor: &mut V) -> Result { + let value = match self.value.take() { + Some(value) => value, + None => { return Err(de::Error::end_of_stream_error()); } + }; + + match value { + Value::Null => visitor.visit_unit(), + Value::Bool(v) => visitor.visit_bool(v), + Value::I64(v) => visitor.visit_i64(v), + Value::F64(v) => visitor.visit_f64(v), + Value::String(v) => visitor.visit_string(v), + Value::Array(v) => { + let len = v.len(); + visitor.visit_seq(SeqDeserializer { + de: self, + iter: v.into_iter(), + len: len, + }) + } + Value::Object(v) => { + let len = v.len(); + visitor.visit_map(MapDeserializer { + de: self, + iter: v.into_iter(), + value: None, + len: len, + }) + } + } + } + + #[inline] + fn visit_option< + V: de::Visitor, + >(&mut self, visitor: &mut V) -> Result { + match self.value { + Some(Value::Null) => visitor.visit_none(), + Some(_) => visitor.visit_some(self), + None => Err(de::Error::end_of_stream_error()), + } + } +} + +struct SeqDeserializer<'a> { + de: &'a mut Deserializer, + iter: vec::IntoIter, + len: usize, +} + +impl<'a> de::SeqVisitor for SeqDeserializer<'a> { + type Error = Error; + + fn visit(&mut self) -> Result, Error> + where T: de::Deserialize + { + match self.iter.next() { + Some(value) => { + self.len -= 1; + self.de.value = Some(value); + Ok(Some(try!(de::Deserialize::deserialize(self.de)))) + } + None => Ok(None), + } + } + + fn end(&mut self) -> Result<(), Error> { + if self.len == 0 { + Ok(()) + } else { + Err(de::Error::end_of_stream_error()) + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) + } +} + +struct MapDeserializer<'a> { + de: &'a mut Deserializer, + iter: btree_map::IntoIter, + value: Option, + len: usize, +} + +impl<'a> de::MapVisitor for MapDeserializer<'a> { + type Error = Error; + + fn visit_key(&mut self) -> Result, Error> + where T: de::Deserialize + { + match self.iter.next() { + Some((key, value)) => { + self.len -= 1; + self.value = Some(value); + self.de.value = Some(Value::String(key)); + Ok(Some(try!(de::Deserialize::deserialize(self.de)))) + } + None => Ok(None), + } + } + + fn visit_value(&mut self) -> Result + where T: de::Deserialize + { + let value = self.value.take().unwrap(); + self.de.value = Some(value); + Ok(try!(de::Deserialize::deserialize(self.de))) + } + + fn end(&mut self) -> Result<(), Error> { + if self.len == 0 { + Ok(()) + } else { + Err(de::Error::end_of_stream_error()) + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) + } +} + +/// Shortcut function to encode a `T` into a JSON `Value` +pub fn to_value(value: &T) -> Value + where T: ser::Serialize +{ + let mut ser = Serializer::new(); + ser::Serializer::visit(&mut ser, value).ok().unwrap(); + ser.unwrap() +} + +/// Shortcut function to decode a JSON `Value` into a `T` +pub fn from_value(value: Value) -> Result + where T: de::Deserialize +{ + let mut de = Deserializer::new(value); + de::Deserialize::deserialize(&mut de) +} diff --git a/serde2/src/lib.rs b/serde2/src/lib.rs index 8e4a2887..0fd403e3 100644 --- a/serde2/src/lib.rs +++ b/serde2/src/lib.rs @@ -2,9 +2,8 @@ extern crate unicode; -//pub use ser::{Serialize, Serializer}; -//pub use ser::{Visitor, VisitorState}; -//pub use ser::GatherTokens; +pub use ser::{Serialize, Serializer}; +pub use de::{Deserialize, Deserializer, Error}; pub mod ser; pub mod de;