Stack-based allocation for serialization.

This commit is contained in:
Tomasz Drwięga 2018-02-02 13:42:25 +01:00
parent 1320986642
commit 90a3ada499
No known key found for this signature in database
GPG Key ID: B2BA26B1C688F8FC
4 changed files with 40 additions and 32 deletions

View File

@ -52,8 +52,9 @@ use tiny_keccak::keccak256;
// 3 according to yellowpaper // 3 according to yellowpaper
const BLOOM_BITS: u32 = 3; const BLOOM_BITS: u32 = 3;
const BLOOM_SIZE: usize = 256;
construct_hash!(Bloom, 256); construct_hash!(Bloom, BLOOM_SIZE);
/// Returns log2. /// Returns log2.
fn log2(x: usize) -> u32 { fn log2(x: usize) -> u32 {
@ -175,20 +176,20 @@ impl Bloom {
pub fn accrue_bloom<'a, B>(&mut self, bloom: B) where BloomRef<'a>: From<B> { pub fn accrue_bloom<'a, B>(&mut self, bloom: B) where BloomRef<'a>: From<B> {
let bloom_ref: BloomRef = bloom.into(); let bloom_ref: BloomRef = bloom.into();
assert_eq!(self.0.len(), 256); assert_eq!(self.0.len(), BLOOM_SIZE);
assert_eq!(bloom_ref.0.len(), 256); assert_eq!(bloom_ref.0.len(), BLOOM_SIZE);
for i in 0..256 { for i in 0..BLOOM_SIZE {
self.0[i] |= bloom_ref.0[i]; self.0[i] |= bloom_ref.0[i];
} }
} }
pub fn data(&self) -> &[u8; 256] { pub fn data(&self) -> &[u8; BLOOM_SIZE] {
&self.0 &self.0
} }
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct BloomRef<'a>(&'a [u8; 256]); pub struct BloomRef<'a>(&'a [u8; BLOOM_SIZE]);
impl<'a> BloomRef<'a> { impl<'a> BloomRef<'a> {
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
@ -202,9 +203,9 @@ impl<'a> BloomRef<'a> {
pub fn contains_bloom<'b, B>(&self, bloom: B) -> bool where BloomRef<'b>: From<B> { pub fn contains_bloom<'b, B>(&self, bloom: B) -> bool where BloomRef<'b>: From<B> {
let bloom_ref: BloomRef = bloom.into(); let bloom_ref: BloomRef = bloom.into();
assert_eq!(self.0.len(), 256); assert_eq!(self.0.len(), BLOOM_SIZE);
assert_eq!(bloom_ref.0.len(), 256); assert_eq!(bloom_ref.0.len(), BLOOM_SIZE);
for i in 0..256 { for i in 0..BLOOM_SIZE {
let a = self.0[i]; let a = self.0[i];
let b = bloom_ref.0[i]; let b = bloom_ref.0[i];
if (a & b) != b { if (a & b) != b {
@ -214,13 +215,13 @@ impl<'a> BloomRef<'a> {
true true
} }
pub fn data(&self) -> &'a [u8; 256] { pub fn data(&self) -> &'a [u8; BLOOM_SIZE] {
self.0 self.0
} }
} }
impl<'a> From<&'a [u8; 256]> for BloomRef<'a> { impl<'a> From<&'a [u8; BLOOM_SIZE]> for BloomRef<'a> {
fn from(data: &'a [u8; 256]) -> Self { fn from(data: &'a [u8; BLOOM_SIZE]) -> Self {
BloomRef(data) BloomRef(data)
} }
} }
@ -234,14 +235,15 @@ impl<'a> From<&'a Bloom> for BloomRef<'a> {
#[cfg(feature="serialize")] #[cfg(feature="serialize")]
impl Serialize for Bloom { impl Serialize for Bloom {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
ethereum_types_serialize::serialize(&self.0, serializer) let mut slice = [0u8; 2 + 2 * BLOOM_SIZE];
ethereum_types_serialize::serialize(&mut slice, &self.0, serializer)
} }
} }
#[cfg(feature="serialize")] #[cfg(feature="serialize")]
impl<'de> Deserialize<'de> for Bloom { impl<'de> Deserialize<'de> for Bloom {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
let mut bytes = [0; 256]; let mut bytes = [0; BLOOM_SIZE];
ethereum_types_serialize::deserialize_check_len(deserializer, ethereum_types_serialize::ExpectedLen::Exact(&mut bytes))?; ethereum_types_serialize::deserialize_check_len(deserializer, ethereum_types_serialize::ExpectedLen::Exact(&mut bytes))?;
Ok(Bloom(bytes)) Ok(Bloom(bytes))
} }

View File

@ -81,7 +81,8 @@ macro_rules! impl_serde {
#[cfg(feature="serialize")] #[cfg(feature="serialize")]
impl Serialize for $name { impl Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
ethereum_types_serialize::serialize(&self.0, serializer) let mut slice = [0u8; 2 + 2 * $len];
ethereum_types_serialize::serialize(&mut slice, &self.0, serializer)
} }
} }

View File

@ -334,9 +334,10 @@ macro_rules! impl_serde {
#[cfg(feature="serialize")] #[cfg(feature="serialize")]
impl Serialize for $name { impl Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
let mut slice = [0u8; 2 + 2 * $len * 8];
let mut bytes = [0u8; $len * 8]; let mut bytes = [0u8; $len * 8];
self.to_big_endian(&mut bytes); self.to_big_endian(&mut bytes);
ethereum_types_serialize::serialize_uint(&bytes, serializer) ethereum_types_serialize::serialize_uint(&mut slice, &bytes, serializer)
} }
} }

View File

@ -5,38 +5,43 @@ use serde::{de, Serializer, Deserializer};
static CHARS: &'static[u8] = b"0123456789abcdef"; static CHARS: &'static[u8] = b"0123456789abcdef";
fn to_hex(bytes: &[u8], skip_leading_zero: bool) -> String { fn to_hex<'a>(v: &'a mut [u8], bytes: &[u8], skip_leading_zero: bool) -> &'a str {
let mut v = Vec::with_capacity(2 + bytes.len() * 2); assert!(v.len() > 1 + bytes.len() * 2);
v.push('0' as u8);
v.push('x' as u8);
v[0] = '0' as u8;
v[1] = 'x' as u8;
let mut idx = 2;
let first_nibble = bytes[0] >> 4; let first_nibble = bytes[0] >> 4;
if first_nibble != 0 || !skip_leading_zero { if first_nibble != 0 || !skip_leading_zero {
v.push(CHARS[first_nibble as usize]); v[idx] = CHARS[first_nibble as usize];
idx += 1;
} }
v.push(CHARS[(bytes[0] & 0xf) as usize]); v[idx] = CHARS[(bytes[0] & 0xf) as usize];
idx += 1;
for &byte in bytes.iter().skip(1) { for &byte in bytes.iter().skip(1) {
v.push(CHARS[(byte >> 4) as usize]); v[idx] = CHARS[(byte >> 4) as usize];
v.push(CHARS[(byte & 0xf) as usize]); v[idx + 1] = CHARS[(byte & 0xf) as usize];
idx += 2;
} }
unsafe { ::std::str::from_utf8(&v[0..idx]).expect("All characters are coming from CHARS")
String::from_utf8_unchecked(v)
}
} }
/// Serializes a slice of bytes. /// Serializes a slice of bytes.
pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error> where pub fn serialize<S>(slice: &mut [u8], bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error> where
S: Serializer, S: Serializer,
{ {
serializer.serialize_str(&to_hex(bytes, false)) let mut v = Vec::with_capacity(2 + bytes.len() * 2);
v.resize(2 + bytes.len() * 2, 0);
serializer.serialize_str(to_hex(slice, bytes, false))
} }
/// Serialize a slice of bytes as uint. /// Serialize a slice of bytes as uint.
/// ///
/// The representation will have all leading zeros trimmed. /// The representation will have all leading zeros trimmed.
pub fn serialize_uint<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error> where pub fn serialize_uint<S>(slice: &mut [u8], bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error> where
S: Serializer, S: Serializer,
{ {
let non_zero = bytes.iter().take_while(|b| **b == 0).count(); let non_zero = bytes.iter().take_while(|b| **b == 0).count();
@ -45,8 +50,7 @@ pub fn serialize_uint<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
return serializer.serialize_str("0x0"); return serializer.serialize_str("0x0");
} }
let string = to_hex(bytes, true); serializer.serialize_str(to_hex(slice, bytes, true))
serializer.serialize_str(&*string)
} }
/// Expected length of bytes vector. /// Expected length of bytes vector.