From 62058962de6ce92d5dc71a424538ec8efb39103f Mon Sep 17 00:00:00 2001 From: Thomas Bahn Date: Sat, 16 May 2015 13:32:58 +0200 Subject: [PATCH] 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),