From 7d52366403321675baaaa99f180a03f7e353806c Mon Sep 17 00:00:00 2001 From: Thomas Bahn Date: Sat, 16 May 2015 11:51:35 +0200 Subject: [PATCH 1/3] Add serialization implementations for fixed size arrays --- src/ser/impls.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ tests/test_ser.rs | 18 ++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/src/ser/impls.rs b/src/ser/impls.rs index 08953727..3483af4f 100644 --- a/src/ser/impls.rs +++ b/src/ser/impls.rs @@ -130,6 +130,53 @@ impl<'a, T> Serialize for &'a [T] } } +macro_rules! array_impls { + ($len:expr) => { + impl Serialize for [T; $len] where T: Serialize { + #[inline] + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer, + { + serializer.visit_seq(SeqIteratorVisitor::new(self.iter(), Some($len))) + } + } + } +} + +array_impls!(0); +array_impls!(1); +array_impls!(2); +array_impls!(3); +array_impls!(4); +array_impls!(5); +array_impls!(6); +array_impls!(7); +array_impls!(8); +array_impls!(9); +array_impls!(10); +array_impls!(11); +array_impls!(12); +array_impls!(13); +array_impls!(14); +array_impls!(15); +array_impls!(16); +array_impls!(17); +array_impls!(18); +array_impls!(19); +array_impls!(20); +array_impls!(21); +array_impls!(22); +array_impls!(23); +array_impls!(24); +array_impls!(25); +array_impls!(26); +array_impls!(27); +array_impls!(28); +array_impls!(29); +array_impls!(30); +array_impls!(31); +array_impls!(32); + impl Serialize for Vec where T: Serialize { #[inline] fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> diff --git a/tests/test_ser.rs b/tests/test_ser.rs index 787c8ca6..60296f12 100644 --- a/tests/test_ser.rs +++ b/tests/test_ser.rs @@ -380,6 +380,24 @@ declare_tests! { Token::SeqEnd, ], } + test_array { + [0; 0] => vec![ + Token::SeqStart(Some(0)), + Token::SeqEnd, + ], + [1, 2, 3] => vec![ + Token::SeqStart(Some(3)), + Token::SeqSep, + Token::I32(1), + + Token::SeqSep, + Token::I32(2), + + Token::SeqSep, + Token::I32(3), + Token::SeqEnd, + ], + } test_vec { Vec::::new() => vec![ Token::SeqStart(Some(0)), From 62058962de6ce92d5dc71a424538ec8efb39103f Mon Sep 17 00:00:00 2001 From: Thomas Bahn Date: Sat, 16 May 2015 13:32:58 +0200 Subject: [PATCH 2/3] Add deserialiation implementations for fixed size arrays --- src/de/impls.rs | 133 +++++++++++++++++++++++++++++++++++++++++++++++ tests/test_de.rs | 40 ++++++++++++++ 2 files changed, 173 insertions(+) diff --git a/src/de/impls.rs b/src/de/impls.rs index f73b3e52..a7bfb8e5 100644 --- a/src/de/impls.rs +++ b/src/de/impls.rs @@ -400,6 +400,139 @@ impl Deserialize for Vec /////////////////////////////////////////////////////////////////////////////// +struct ArrayVisitor0 { + marker: PhantomData, +} + +impl ArrayVisitor0 { + pub fn new() -> Self { + ArrayVisitor0 { + marker: PhantomData, + } + } +} + +impl Visitor for ArrayVisitor0 where T: Deserialize + Default { + type Value = [T; 0]; + + #[inline] + fn visit_unit(&mut self) -> Result<[T; 0], E> + where E: Error, + { + Ok([T::default(); 0]) + } + + #[inline] + fn visit_seq(&mut self, mut visitor: V) -> Result<[T; 0], V::Error> + where V: SeqVisitor, + { + try!(visitor.end()); + Ok([T::default(); 0]) + } +} + +impl Deserialize for [T; 0] + where T: Deserialize + Default +{ + fn deserialize(deserializer: &mut D) -> Result<[T; 0], D::Error> + where D: Deserializer, + { + deserializer.visit(ArrayVisitor0::new()) + } +} + +macro_rules! array_impls { + ($($visitor:ident, $len:expr => ($($name:ident),+),)+) => { + $( + struct $visitor { + marker: PhantomData, + } + + impl $visitor { + pub fn new() -> Self { + $visitor { + marker: PhantomData + } + } + } + + impl Visitor for $visitor where T: Deserialize { + type Value = [T; $len]; + + #[inline] + fn visit_seq(&mut self, mut visitor: V) -> Result<[T; $len], V::Error> + where V: SeqVisitor, + { + $( + let $name = try!(visitor.visit().and_then( + |value| value.ok_or(Error::end_of_stream_error())) + ); + )+; + + try!(visitor.end()); + + Ok([$($name,)+]) + } + } + + impl Deserialize for [T; $len] + where T: Deserialize, + { + fn deserialize(deserializer: &mut D) -> Result<[T; $len], D::Error> + where D: Deserializer, + { + deserializer.visit($visitor::new()) + } + } + )+ + } +} + +array_impls! { + ArrayVisitor1, 1 => (a), + ArrayVisitor2, 2 => (a, b), + ArrayVisitor3, 3 => (a, b, c), + ArrayVisitor4, 4 => (a, b, c, d), + ArrayVisitor5, 5 => (a, b, c, d, e), + ArrayVisitor6, 6 => (a, b, c, d, e, f), + ArrayVisitor7, 7 => (a, b, c, d, e, f, g), + ArrayVisitor8, 8 => (a, b, c, d, e, f, g, h), + ArrayVisitor9, 9 => (a, b, c, d, e, f, g, h, i), + ArrayVisitor10, 10 => (a, b, c, d, e, f, g, h, i, j), + ArrayVisitor11, 11 => (a, b, c, d, e, f, g, h, i, j, k), + ArrayVisitor12, 12 => (a, b, c, d, e, f, g, h, i, j, k, l), + ArrayVisitor13, 13 => (a, b, c, d, e, f, g, h, i, j, k, l, m), + ArrayVisitor14, 14 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n), + ArrayVisitor15, 15 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o), + ArrayVisitor16, 16 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p), + ArrayVisitor17, 17 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q), + ArrayVisitor18, 18 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r), + ArrayVisitor19, 19 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s), + ArrayVisitor20, 20 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s ,t), + ArrayVisitor21, 21 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u), + ArrayVisitor22, 22 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v), + ArrayVisitor23, 23 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w), + ArrayVisitor24, 24 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x), + ArrayVisitor25, 25 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, + y), + ArrayVisitor26, 26 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, + y, z), + ArrayVisitor27, 27 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, + y, z, aa), + ArrayVisitor28, 28 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, + y, z, aa, ab), + ArrayVisitor29, 29 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, + y, z, aa, ab, ac), + ArrayVisitor30, 30 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, + y, z, aa, ab, ac, ad), + ArrayVisitor31, 31 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, + y, z, aa, ab, ac, ad, ae), + ArrayVisitor32, 32 => (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, + y, z, aa, ab, ac, ad, ae, af), +} + +/////////////////////////////////////////////////////////////////////////////// + macro_rules! tuple_impls { () => {}; ($($visitor:ident => ($($name:ident),+),)+) => { diff --git a/tests/test_de.rs b/tests/test_de.rs index 75e54d68..0fb6732b 100644 --- a/tests/test_de.rs +++ b/tests/test_de.rs @@ -652,6 +652,46 @@ declare_tests! { Token::SeqEnd, ], } + test_array { + [0; 0] => vec![ + Token::Unit, + ], + [0; 0] => vec![ + Token::SeqStart(0), + Token::SeqEnd, + ], + ([0; 0], [1], [2, 3]) => vec![ + Token::SeqStart(3), + Token::SeqSep, + Token::SeqStart(0), + Token::SeqEnd, + + Token::SeqSep, + Token::SeqStart(1), + Token::SeqSep, + Token::I32(1), + Token::SeqEnd, + + Token::SeqSep, + Token::SeqStart(2), + Token::SeqSep, + Token::I32(2), + + Token::SeqSep, + Token::I32(3), + Token::SeqEnd, + Token::SeqEnd, + ], + [0; 0] => vec![ + Token::Name("Anything"), + Token::Unit, + ], + [0; 0] => vec![ + Token::Name("Anything"), + Token::SeqStart(0), + Token::SeqEnd, + ], + } test_tuple { (1,) => vec![ Token::SeqStart(1), From 15794a5ed696d2e8f2a4289b8f22b451ada4cac8 Mon Sep 17 00:00:00 2001 From: Thomas Bahn Date: Sat, 16 May 2015 14:36:28 +0200 Subject: [PATCH 3/3] Improve build time --- src/de/impls.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/de/impls.rs b/src/de/impls.rs index a7bfb8e5..bec9c610 100644 --- a/src/de/impls.rs +++ b/src/de/impls.rs @@ -464,9 +464,10 @@ macro_rules! array_impls { where V: SeqVisitor, { $( - let $name = try!(visitor.visit().and_then( - |value| value.ok_or(Error::end_of_stream_error())) - ); + let $name = match try!(visitor.visit()) { + Some(val) => val, + None => { return Err(Error::end_of_stream_error()); } + }; )+; try!(visitor.end());