Add slice consensus encode/decode functions and use for short arrays

This commit is contained in:
Matt Corallo 2019-05-22 18:21:15 -04:00
parent 4139f2a1ca
commit 7015b064dd
2 changed files with 43 additions and 10 deletions

View File

@ -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<bool, Error>;
/// Read a byte slice
fn read_slice(&mut self, slice: &mut [u8]) -> Result<(), Error>;
}
macro_rules! encoder_fn {
@ -326,6 +332,10 @@ impl<W: Write> 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<R: Read> Decoder for R {
@ -348,6 +358,10 @@ impl<R: Read> Decoder for R {
fn read_bool(&mut self) -> Result<bool, Error> {
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<D: Decoder> Decodable<D> for String {
// Arrays
macro_rules! impl_array {
( $size:expr ) => (
impl<S: Encoder, T: Encodable<S>> Encodable<S> for [T; $size] {
impl<S: Encoder> Encodable<S> 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<D: Decoder, T:Decodable<D> + Copy> Decodable<D> for [T; $size] {
impl<D: Decoder> Decodable<D> 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<D: Decoder> Decodable<D> 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<S: Encoder> Encodable<S> 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<S: Encoder, T: Encodable<S>> Encodable<S> for [T] {
#[inline]
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> {

View File

@ -348,7 +348,10 @@ macro_rules! construct_uint {
impl<D: ::consensus::encode::Decoder> ::consensus::encode::Decodable<D> 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))
}
}