Speed up Vec<u8> [d]e[n]code operations by dropping the generic

This commit is contained in:
Matt Corallo 2019-05-23 13:14:43 -04:00
parent ee827e4aa3
commit fa1ec2028d
1 changed files with 51 additions and 12 deletions

View File

@ -45,6 +45,10 @@ use secp256k1;
use util::base58; use util::base58;
use util::psbt; use util::psbt;
use blockdata::transaction::{TxOut, Transaction, TxIn};
use network::message_blockdata::Inventory;
use network::address::Address;
/// Encoding error /// Encoding error
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
@ -551,7 +555,9 @@ impl<S: Encoder> Encodable<S> for [u16; 8] {
} }
// Vectors // Vectors
impl<S: Encoder, T: Encodable<S>> Encodable<S> for Vec<T> { macro_rules! impl_vec {
($type: ty) => {
impl<S: Encoder> Encodable<S> for Vec<$type> {
#[inline] #[inline]
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> { fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> {
VarInt(self.len() as u64).consensus_encode(s)?; VarInt(self.len() as u64).consensus_encode(s)?;
@ -560,12 +566,12 @@ impl<S: Encoder, T: Encodable<S>> Encodable<S> for Vec<T> {
} }
} }
impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> { impl<D: Decoder> Decodable<D> for Vec<$type> {
#[inline] #[inline]
fn consensus_decode(d: &mut D) -> Result<Vec<T>, self::Error> { fn consensus_decode(d: &mut D) -> Result<Vec<$type>, self::Error> {
let len = VarInt::consensus_decode(d)?.0; let len = VarInt::consensus_decode(d)?.0;
let byte_size = (len as usize) let byte_size = (len as usize)
.checked_mul(mem::size_of::<T>()) .checked_mul(mem::size_of::<$type>())
.ok_or(self::Error::ParseFailed("Invalid length"))?; .ok_or(self::Error::ParseFailed("Invalid length"))?;
if byte_size > MAX_VEC_SIZE { if byte_size > MAX_VEC_SIZE {
return Err(self::Error::OversizedVectorAllocation { requested: byte_size, max: MAX_VEC_SIZE }) return Err(self::Error::OversizedVectorAllocation { requested: byte_size, max: MAX_VEC_SIZE })
@ -575,6 +581,39 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> {
Ok(ret) Ok(ret)
} }
} }
}
}
impl_vec!(sha256d::Hash);
impl_vec!(Transaction);
impl_vec!(TxOut);
impl_vec!(TxIn);
impl_vec!(Inventory);
impl_vec!(Vec<u8>);
impl_vec!((u32, Address));
impl_vec!(u64);
impl<S: Encoder> Encodable<S> for Vec<u8> {
#[inline]
fn consensus_encode(&self, s: &mut S) -> Result<(), self::Error> {
VarInt(self.len() as u64).consensus_encode(s)?;
s.emit_slice(&self)
}
}
impl<D: Decoder> Decodable<D> for Vec<u8> {
#[inline]
fn consensus_decode(d: &mut D) -> Result<Vec<u8>, self::Error> {
let len = VarInt::consensus_decode(d)?.0;
let len = len as usize;
if len > MAX_VEC_SIZE {
return Err(self::Error::OversizedVectorAllocation { requested: len, max: MAX_VEC_SIZE })
}
let mut ret = Vec::with_capacity(len);
ret.resize(len, 0);
d.read_slice(&mut ret)?;
Ok(ret)
}
}
impl<S: Encoder> Encodable<S> for Box<[u8]> { impl<S: Encoder> Encodable<S> for Box<[u8]> {
#[inline] #[inline]