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 /// Output a boolean
fn emit_bool(&mut self, v: bool) -> Result<(), Error>; 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 /// A simple Decoder trait
@ -286,6 +289,9 @@ pub trait Decoder {
/// Read a boolean /// Read a boolean
fn read_bool(&mut self) -> Result<bool, Error>; 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 { macro_rules! encoder_fn {
@ -326,6 +332,10 @@ impl<W: Write> Encoder for W {
fn emit_bool(&mut self, v: bool) -> Result<(), Error> { fn emit_bool(&mut self, v: bool) -> Result<(), Error> {
self.write_i8(if v {1} else {0}).map_err(Error::Io) 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 { impl<R: Read> Decoder for R {
@ -348,6 +358,10 @@ impl<R: Read> Decoder for R {
fn read_bool(&mut self) -> Result<bool, Error> { fn read_bool(&mut self) -> Result<bool, Error> {
Decoder::read_i8(self).map(|bit| bit != 0) 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 /// Maximum size, in bytes, of a vector we are allowed to decode
@ -491,21 +505,18 @@ impl<D: Decoder> Decodable<D> for String {
// Arrays // Arrays
macro_rules! impl_array { macro_rules! impl_array {
( $size:expr ) => ( ( $size:expr ) => (
impl<S: Encoder, T: Encodable<S>> Encodable<S> for [T; $size] { impl<S: Encoder> Encodable<S> for [u8; $size] {
#[inline] #[inline]
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> {
for i in self.iter() { i.consensus_encode(s)?; } s.emit_slice(&self[..])
Ok(())
} }
} }
impl<D: Decoder, T:Decodable<D> + Copy> Decodable<D> for [T; $size] { impl<D: Decoder> Decodable<D> for [u8; $size] {
#[inline] #[inline]
fn consensus_decode(d: &mut D) -> Result<[T; $size], self::Error> { fn consensus_decode(d: &mut D) -> Result<[u8; $size], self::Error> {
// Set everything to the first decode let mut ret = [0; $size];
let mut ret = [Decodable::consensus_decode(d)?; $size]; d.read_slice(&mut ret)?;
// Set the rest
for item in ret.iter_mut().take($size).skip(1) { *item = Decodable::consensus_decode(d)?; }
Ok(ret) Ok(ret)
} }
} }
@ -520,6 +531,25 @@ impl_array!(16);
impl_array!(32); impl_array!(32);
impl_array!(33); 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] { impl<S: Encoder, T: Encodable<S>> Encodable<S> for [T] {
#[inline] #[inline]
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { 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 { impl<D: ::consensus::encode::Decoder> ::consensus::encode::Decodable<D> for $name {
fn consensus_decode(d: &mut D) -> Result<$name, encode::Error> { fn consensus_decode(d: &mut D) -> Result<$name, encode::Error> {
use consensus::encode::Decodable; 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)) Ok($name(ret))
} }
} }