Compare commits

...

14 Commits

Author SHA1 Message Date
Erick Tryzelaar 37c0ad19bb Version bump 2015-06-25 16:10:52 -07:00
Erick Tryzelaar ed5b4d7319 Fix serializing generic enums
This fixes generic enums with variants that don't use all lifetime
and typarams. Closes #88.
2015-06-18 08:45:03 -07:00
Erick Tryzelaar b09c0fc653 Fix an indent typo 2015-06-18 07:49:13 -07:00
Erick Tryzelaar ab3e40ca45 Version bump 2015-06-08 07:12:27 -07:00
Erick Tryzelaar 8f67e9c048 Switch exponent bounds checking back to using powi 2015-06-08 07:07:09 -07:00
Erick Tryzelaar 7dc1a64f03 Merge pull request #80 from ProtectedMode/master
Fix #77, integer overflow when parsing JSON scientific notation number.
2015-06-08 06:57:33 -07:00
Erick Tryzelaar ac3a3e922f Fix compilation with rust nightly (613e57b44) and syntex 0.7.0 2015-06-08 06:55:36 -07:00
Erick Tryzelaar 4e50c56542 Merge pull request #87 from Manishearth/patch-1
Use correct attribute syntax
2015-06-07 20:46:44 -07:00
Manish Goregaokar 26b1ed79c0 !!!!!! 2015-06-06 18:08:33 +05:30
ProtectedMode 2e8ef0f768 Add test for #77, integer overflow when parsing JSON scientific notation number. 2015-05-21 09:59:14 +02:00
Erick Tryzelaar c993414b92 serde_tests tests doesn't need the test crate 2015-05-20 22:57:19 -07:00
Erick Tryzelaar ed6ef4e149 Travis work 2015-05-20 22:44:50 -07:00
Erick Tryzelaar 859cdcc815 Remove unnecessary lifetime 2015-05-20 09:02:38 -07:00
ProtectedMode 745a95b607 Fix #77, integer overflow when parsing JSON scientific notation number. 2015-05-20 16:32:10 +02:00
15 changed files with 155 additions and 64 deletions
+25 -7
View File
@@ -1,16 +1,34 @@
language: rust
rust:
- stable
- beta
- nightly
env:
global:
secure: HO41LMpMXkF2In9+1sxWVu7fgolL+y9+4Q5PI6wZX2L5pDwpPJCjxaQarQXCEnoIxED1PlP03JuF7ULNz0zw1ylYhAOfOSdkxFZRnE2wMZqq6qvXBHwyMiDrAociIzoPKSGv7JVrKPsjsnd+96K6xxueIodQZrmAdyq7N/M82Mc=
matrix:
- CRATE=serde_tests TARGET=test
matrix:
include:
- rust: nightly
env: CRATE=serde_macros TARGET=test
- rust: nightly
env: CRATE=serde_macros TARGET=bench
- rust: nightly
env: CRATE=serde_tests TARGET=bench
script:
- cargo test
- cargo bench
- cargo doc
- (cd $CRATE && cargo $TARGET)
after_success: |
[ $TRAVIS_BRANCH = "master" ] &&
[ $TRAVIS_PULL_REQUEST = false ] &&
cargo doc &&
mkdir -p target/doc &&
(cd serde && cargo doc --no-deps) &&
(cd serde_codegen && cargo doc --no-deps) &&
(cd serde_macros && cargo doc --no-deps) &&
cp -r serde/target/doc target/doc/serde &&
cp -r serde_codegen/target/doc target/doc/serde_codegen &&
cp -r serde_macros/target/doc target/doc/serde_macros &&
echo "<meta http-equiv=refresh content=0;url=`echo $TRAVIS_REPO_SLUG | cut -d '/' -f 2`/index.html>" > target/doc/index.html &&
sudo pip install ghp-import &&
ghp-import -n target/doc &&
git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
env:
global:
secure: HO41LMpMXkF2In9+1sxWVu7fgolL+y9+4Q5PI6wZX2L5pDwpPJCjxaQarQXCEnoIxED1PlP03JuF7ULNz0zw1ylYhAOfOSdkxFZRnE2wMZqq6qvXBHwyMiDrAociIzoPKSGv7JVrKPsjsnd+96K6xxueIodQZrmAdyq7N/M82Mc=
+2 -2
View File
@@ -24,8 +24,8 @@ and
for the annotated type:
```rust
#[feature(custom_derive, plugin)]
#[plugin(serde_macros)]
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
extern crate serde;
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde"
version = "0.4.0"
version = "0.4.2"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
+21 -14
View File
@@ -1,4 +1,5 @@
use std::char;
use std::i32;
use std::io;
use std::str;
@@ -13,6 +14,15 @@ pub struct Deserializer<Iter: Iterator<Item=io::Result<u8>>> {
str_buf: Vec<u8>,
}
macro_rules! try_or_invalid {
($self_:expr, $e:expr) => {
match $e {
Some(v) => v,
None => { return Err($self_.error(ErrorCode::InvalidNumber)); }
}
}
}
impl<Iter> Deserializer<Iter>
where Iter: Iterator<Item=io::Result<u8>>,
{
@@ -198,16 +208,8 @@ impl<Iter> Deserializer<Iter>
while !self.eof() {
match self.ch_or_null() {
c @ b'0' ... b'9' => {
macro_rules! try_or_invalid {
($e: expr) => {
match $e {
Some(v) => v,
None => { return Err(self.error(ErrorCode::InvalidNumber)); }
}
}
}
accum = try_or_invalid!(accum.checked_mul(10));
accum = try_or_invalid!(accum.checked_add((c as u64) - ('0' as u64)));
accum = try_or_invalid!(self, accum.checked_mul(10));
accum = try_or_invalid!(self, accum.checked_add((c as u64) - ('0' as u64)));
try!(self.bump());
}
@@ -249,7 +251,7 @@ impl<Iter> Deserializer<Iter>
fn parse_exponent(&mut self, mut res: f64) -> Result<f64, Error> {
try!(self.bump());
let mut exp = 0;
let mut exp: u64 = 0;
let mut neg_exp = false;
if self.ch_is(b'+') {
@@ -267,8 +269,8 @@ impl<Iter> Deserializer<Iter>
while !self.eof() {
match self.ch_or_null() {
c @ b'0' ... b'9' => {
exp *= 10;
exp += (c as i32) - (b'0' as i32);
exp = try_or_invalid!(self, exp.checked_mul(10));
exp = try_or_invalid!(self, exp.checked_add((c as u64) - (b'0' as u64)));
try!(self.bump());
}
@@ -276,7 +278,12 @@ impl<Iter> Deserializer<Iter>
}
}
let exp: f64 = 10_f64.powi(exp);
let exp = if exp <= i32::MAX as u64 {
10_f64.powi(exp as i32)
} else {
return Err(self.error(ErrorCode::InvalidNumber));
};
if neg_exp {
res /= exp;
} else {
+1 -1
View File
@@ -57,7 +57,7 @@ impl Value {
///
/// assert!(obj.lookup("x.a").unwrap() == &Value::U64(1));
/// ```
pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a Value> {
pub fn lookup<'a>(&'a self, path: &str) -> Option<&'a Value> {
let mut target = self;
for key in path.split('.') {
match target.find(key) {
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_codegen"
version = "0.4.0"
version = "0.4.2"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
+4 -4
View File
@@ -24,11 +24,11 @@ pub fn expand_derive_deserialize(
cx: &mut ExtCtxt,
span: Span,
meta_item: &MetaItem,
annotatable: Annotatable,
annotatable: &Annotatable,
push: &mut FnMut(Annotatable)
) {
let item = match annotatable {
Annotatable::Item(item) => item,
let item = match *annotatable {
Annotatable::Item(ref item) => item,
_ => {
cx.span_err(
meta_item.span,
@@ -280,7 +280,7 @@ fn deserialize_tuple_struct(
impl_generics,
vec![deserializer_ty_param(builder)],
vec![deserializer_ty_arg(builder)],
);
);
let visit_seq_expr = deserialize_seq(
cx,
+56 -29
View File
@@ -19,11 +19,11 @@ pub fn expand_derive_serialize(
cx: &mut ExtCtxt,
span: Span,
meta_item: &MetaItem,
annotatable: Annotatable,
annotatable: &Annotatable,
push: &mut FnMut(Annotatable)
) {
let item = match annotatable {
Annotatable::Item(item) => item,
let item = match *annotatable {
Annotatable::Item(ref item) => item,
_ => {
cx.span_err(
meta_item.span,
@@ -55,7 +55,10 @@ pub fn expand_derive_serialize(
&builder,
&item,
&impl_generics,
ty.clone(),
builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(ty.clone()),
);
let where_clause = &impl_generics.where_clause;
@@ -98,6 +101,7 @@ fn serialize_body(
builder,
item.ident,
impl_generics,
ty,
enum_def,
)
}
@@ -176,15 +180,11 @@ fn serialize_tuple_struct(
ty: P<ast::Ty>,
fields: usize,
) -> P<ast::Expr> {
let value_ty = builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(ty);
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
cx,
builder,
value_ty,
ty.clone(),
ty,
fields,
impl_generics,
);
@@ -197,6 +197,7 @@ fn serialize_tuple_struct(
serializer.visit_named_seq($type_name, Visitor {
value: self,
state: 0,
_structure_ty: ::std::marker::PhantomData,
})
})
}
@@ -210,15 +211,11 @@ fn serialize_struct(
struct_def: &StructDef,
fields: Vec<Ident>,
) -> P<ast::Expr> {
let value_ty = builder.ty()
.ref_()
.lifetime("'__a")
.build_ty(ty.clone());
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
cx,
builder,
value_ty,
ty.clone(),
ty,
struct_def,
impl_generics,
fields.iter().map(|field| quote_expr!(cx, &self.value.$field)),
@@ -232,6 +229,7 @@ fn serialize_struct(
serializer.visit_named_map($type_name, Visitor {
value: self,
state: 0,
_structure_ty: ::std::marker::PhantomData,
})
})
}
@@ -241,6 +239,7 @@ fn serialize_item_enum(
builder: &aster::AstBuilder,
type_ident: Ident,
impl_generics: &ast::Generics,
ty: P<ast::Ty>,
enum_def: &ast::EnumDef,
) -> P<ast::Expr> {
let arms: Vec<ast::Arm> = enum_def.variants.iter()
@@ -250,6 +249,7 @@ fn serialize_item_enum(
builder,
type_ident,
impl_generics,
ty.clone(),
variant,
)
})
@@ -267,6 +267,7 @@ fn serialize_variant(
builder: &aster::AstBuilder,
type_ident: Ident,
generics: &ast::Generics,
ty: P<ast::Ty>,
variant: &ast::Variant,
) -> ast::Arm {
let type_name = builder.expr().str(type_ident);
@@ -305,6 +306,7 @@ fn serialize_variant(
type_name,
variant_name,
generics,
ty,
args,
fields,
);
@@ -340,6 +342,7 @@ fn serialize_variant(
type_name,
variant_name,
generics,
ty,
struct_def,
fields,
);
@@ -355,10 +358,11 @@ fn serialize_tuple_variant(
type_name: P<ast::Expr>,
variant_name: P<ast::Expr>,
generics: &ast::Generics,
structure_ty: P<ast::Ty>,
args: &[ast::VariantArg],
fields: Vec<Ident>,
) -> P<ast::Expr> {
let value_ty = builder.ty().tuple()
let variant_ty = builder.ty().tuple()
.with_tys(
args.iter().map(|arg| {
builder.ty()
@@ -369,6 +373,15 @@ fn serialize_tuple_variant(
)
.build();
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
cx,
builder,
structure_ty,
variant_ty,
args.len(),
generics,
);
let value_expr = builder.expr().tuple()
.with_exprs(
fields.iter().map(|field| {
@@ -379,20 +392,13 @@ fn serialize_tuple_variant(
)
.build();
let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor(
cx,
builder,
value_ty,
args.len(),
generics,
);
quote_expr!(cx, {
$visitor_struct
$visitor_impl
serializer.visit_enum_seq($type_name, $variant_name, Visitor {
value: $value_expr,
state: 0,
_structure_ty: ::std::marker::PhantomData,
})
})
}
@@ -403,6 +409,7 @@ fn serialize_struct_variant(
type_name: P<ast::Expr>,
variant_name: P<ast::Expr>,
generics: &ast::Generics,
structure_ty: P<ast::Ty>,
struct_def: &ast::StructDef,
fields: Vec<Ident>,
) -> P<ast::Expr> {
@@ -430,6 +437,7 @@ fn serialize_struct_variant(
let (visitor_struct, visitor_impl) = serialize_struct_visitor(
cx,
builder,
structure_ty,
value_ty,
struct_def,
generics,
@@ -446,6 +454,7 @@ fn serialize_struct_variant(
serializer.visit_enum_map($type_name, $variant_name, Visitor {
value: $value_expr,
state: 0,
_structure_ty: ::std::marker::PhantomData,
})
})
}
@@ -453,7 +462,8 @@ fn serialize_struct_variant(
fn serialize_tuple_struct_visitor(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
value_ty: P<ast::Ty>,
structure_ty: P<ast::Ty>,
variant_ty: P<ast::Ty>,
fields: usize,
generics: &ast::Generics
) -> (P<ast::Item>, P<ast::Item>) {
@@ -484,11 +494,19 @@ fn serialize_tuple_struct_visitor(
.strip_bounds()
.build();
// Variants don't necessarily reference all generic lifetimes and type parameters,
// so to avoid a compilation failure, we'll just add a phantom type to capture these
// unused values.
let structure_ty = builder.ty()
.phantom_data()
.build(structure_ty);
(
quote_item!(cx,
struct Visitor $visitor_impl_generics $where_clause {
state: usize,
value: $value_ty,
value: $variant_ty,
_structure_ty: $structure_ty,
}
).unwrap(),
@@ -518,7 +536,8 @@ fn serialize_tuple_struct_visitor(
fn serialize_struct_visitor<I>(
cx: &ExtCtxt,
builder: &aster::AstBuilder,
value_ty: P<ast::Ty>,
structure_ty: P<ast::Ty>,
variant_ty: P<ast::Ty>,
struct_def: &StructDef,
generics: &ast::Generics,
value_exprs: I,
@@ -563,11 +582,19 @@ fn serialize_struct_visitor<I>(
.strip_bounds()
.build();
// Variants don't necessarily reference all generic lifetimes and type parameters,
// so to avoid a compilation failure, we'll just add a phantom type to capture these
// unused values.
let structure_ty = builder.ty()
.phantom_data()
.build(structure_ty);
(
quote_item!(cx,
struct Visitor $visitor_impl_generics $where_clause {
state: usize,
value: $value_ty,
value: $variant_ty,
_structure_ty: $structure_ty,
}
).unwrap(),
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_macros"
version = "0.4.0"
version = "0.4.2"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Macros to auto-generate implementations for the serde framework"
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "serde_tests"
version = "0.4.0"
version = "0.4.1"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "A generic serialization/deserialization framework"
-3
View File
@@ -1,6 +1,3 @@
#![feature(test)]
extern crate serde;
extern crate test;
include!(concat!(env!("OUT_DIR"), "/test.rs"));
+4
View File
@@ -1,7 +1,11 @@
/*
mod test_annotations;
mod test_bytes;
mod test_de;
mod test_json;
mod test_json_builder;
*/
mod test_macros;
/*
mod test_ser;
*/
+1
View File
@@ -703,6 +703,7 @@ fn test_parse_number_errors() {
("1e+", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 3)),
("1a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 2)),
("777777777777777777777777777", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 20)),
("1e777777777777777777777777777", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 22)),
]);
}
+37
View File
@@ -123,6 +123,14 @@ enum DeEnum<B, C: /* Trait */, D> /* where D: Trait */ {
},
}
#[derive(Serialize)]
enum Lifetimes<'a> {
LifetimeSeq(&'a i32),
NoLifetimeSeq(i32),
LifetimeMap { a: &'a i32 },
NoLifetimeMap { a: i32 },
}
#[test]
fn test_named_unit() {
let named_unit = NamedUnit;
@@ -438,3 +446,32 @@ fn test_de_enum_map() {
}
);
}
#[test]
fn test_lifetimes() {
let value = 5;
let lifetime = Lifetimes::LifetimeSeq(&value);
assert_eq!(
json::to_string(&lifetime).unwrap(),
"{\"LifetimeSeq\":[5]}"
);
let lifetime = Lifetimes::NoLifetimeSeq(5);
assert_eq!(
json::to_string(&lifetime).unwrap(),
"{\"NoLifetimeSeq\":[5]}"
);
let value = 5;
let lifetime = Lifetimes::LifetimeMap { a: &value };
assert_eq!(
json::to_string(&lifetime).unwrap(),
"{\"LifetimeMap\":{\"a\":5}}"
);
let lifetime = Lifetimes::NoLifetimeMap { a: 5 };
assert_eq!(
json::to_string(&lifetime).unwrap(),
"{\"NoLifetimeMap\":{\"a\":5}}"
);
}