From 7015b064dd62163490117dd1e24e6646b7454a71 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 22 May 2019 18:21:15 -0400 Subject: [PATCH] Add slice consensus encode/decode functions and use for short arrays --- src/consensus/encode.rs | 48 +++++++++++++++++++++++++++++++++-------- src/util/uint.rs | 5 ++++- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index de01451..7101be2 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -262,6 +262,9 @@ pub trait Encoder { /// Output a boolean fn emit_bool(&mut self, v: bool) -> Result<(), Error>; + + /// Output a byte slice + fn emit_slice(&mut self, v: &[u8]) -> Result<(), Error>; } /// A simple Decoder trait @@ -286,6 +289,9 @@ pub trait Decoder { /// Read a boolean fn read_bool(&mut self) -> Result; + + /// Read a byte slice + fn read_slice(&mut self, slice: &mut [u8]) -> Result<(), Error>; } macro_rules! encoder_fn { @@ -326,6 +332,10 @@ impl Encoder for W { fn emit_bool(&mut self, v: bool) -> Result<(), Error> { self.write_i8(if v {1} else {0}).map_err(Error::Io) } + #[inline] + fn emit_slice(&mut self, v: &[u8]) -> Result<(), Error> { + self.write_all(v).map_err(Error::Io) + } } impl Decoder for R { @@ -348,6 +358,10 @@ impl Decoder for R { fn read_bool(&mut self) -> Result { Decoder::read_i8(self).map(|bit| bit != 0) } + #[inline] + fn read_slice(&mut self, slice: &mut [u8]) -> Result<(), Error> { + self.read_exact(slice).map_err(Error::Io) + } } /// Maximum size, in bytes, of a vector we are allowed to decode @@ -491,21 +505,18 @@ impl Decodable for String { // Arrays macro_rules! impl_array { ( $size:expr ) => ( - impl> Encodable for [T; $size] { + impl Encodable for [u8; $size] { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { - for i in self.iter() { i.consensus_encode(s)?; } - Ok(()) + s.emit_slice(&self[..]) } } - impl + Copy> Decodable for [T; $size] { + impl Decodable for [u8; $size] { #[inline] - fn consensus_decode(d: &mut D) -> Result<[T; $size], self::Error> { - // Set everything to the first decode - let mut ret = [Decodable::consensus_decode(d)?; $size]; - // Set the rest - for item in ret.iter_mut().take($size).skip(1) { *item = Decodable::consensus_decode(d)?; } + fn consensus_decode(d: &mut D) -> Result<[u8; $size], self::Error> { + let mut ret = [0; $size]; + d.read_slice(&mut ret)?; Ok(ret) } } @@ -520,6 +531,25 @@ impl_array!(16); impl_array!(32); impl_array!(33); +impl Decodable for [u16; 8] { + #[inline] + fn consensus_decode(d: &mut D) -> Result<[u16; 8], self::Error> { + let mut res = [0; 8]; + for i in 0..8 { + res[i] = Decodable::consensus_decode(d)?; + } + Ok(res) + } +} + +impl Encodable for [u16; 8] { + #[inline] + fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { + for c in self.iter() { c.consensus_encode(s)?; } + Ok(()) + } +} + impl> Encodable for [T] { #[inline] fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { diff --git a/src/util/uint.rs b/src/util/uint.rs index 6a0c9f6..05d4a95 100644 --- a/src/util/uint.rs +++ b/src/util/uint.rs @@ -348,7 +348,10 @@ macro_rules! construct_uint { impl ::consensus::encode::Decodable for $name { fn consensus_decode(d: &mut D) -> Result<$name, encode::Error> { use consensus::encode::Decodable; - let ret: [u64; $n_words] = Decodable::consensus_decode(d)?; + let mut ret: [u64; $n_words] = [0; $n_words]; + for i in 0..$n_words { + ret[i] = Decodable::consensus_decode(d)?; + } Ok($name(ret)) } }