diff --git a/src/bytes.rs b/src/bytes.rs index d188eb69b..2cbfb00b4 100644 --- a/src/bytes.rs +++ b/src/bytes.rs @@ -1,27 +1,27 @@ //! Unified interfaces for bytes operations on basic types -//! +//! //! # Examples //! ```rust //! extern crate ethcore_util as util; -//! +//! //! fn bytes_convertable() { //! use util::bytes::BytesConvertable; //! //! let arr = [0; 5]; //! let slice: &[u8] = arr.bytes(); //! } -//! +//! //! fn to_bytes() { //! use util::bytes::ToBytes; -//! +//! //! let a: Vec = "hello_world".to_bytes(); //! let b: Vec = 400u32.to_bytes(); //! let c: Vec = 0xffffffffffffffffu64.to_bytes(); //! } -//! +//! //! fn from_bytes() { //! use util::bytes::FromBytes; -//! +//! //! let a = String::from_bytes(&[b'd', b'o', b'g']); //! let b = u16::from_bytes(&[0xfa]); //! let c = u64::from_bytes(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]); @@ -138,7 +138,7 @@ impl <'a> ToBytes for &'a str { fn to_bytes(&self) -> Vec { From::from(*self) } - + fn to_bytes_len(&self) -> usize { self.len() } } @@ -147,7 +147,7 @@ impl ToBytes for String { let s: &str = self.as_ref(); From::from(s) } - + fn to_bytes_len(&self) -> usize { self.len() } } @@ -166,6 +166,14 @@ impl ToBytes for u64 { fn to_bytes_len(&self) -> usize { 8 - self.leading_zeros() as usize / 8 } } +impl ToBytes for bool { + fn to_bytes(&self) -> Vec { + vec![ if *self { 1u8 } else { 0u8 } ] + } + + fn to_bytes_len(&self) -> usize { 1 } +} + macro_rules! impl_map_to_bytes { ($from: ident, $to: ty) => { impl ToBytes for $from { @@ -182,7 +190,7 @@ impl_map_to_bytes!(u32, u64); macro_rules! impl_uint_to_bytes { ($name: ident) => { impl ToBytes for $name { - fn to_bytes(&self) -> Vec { + fn to_bytes(&self) -> Vec { let mut res= vec![]; let count = self.to_bytes_len(); res.reserve(count); @@ -210,7 +218,7 @@ impl ToBytes for T where T: FixedHash { ptr::copy(self.bytes().as_ptr(), res.as_mut_ptr(), T::size()); res.set_len(T::size()); } - + res } } @@ -264,6 +272,17 @@ impl FromBytes for u64 { } } +impl FromBytes for bool { + fn from_bytes(bytes: &[u8]) -> FromBytesResult { + match bytes.len() { + 0 => Ok(false), + 1 => Ok(bytes[0] != 0), + _ => Err(FromBytesError::DataIsTooLong), + } + } +} + + macro_rules! impl_map_from_bytes { ($from: ident, $to: ident) => { impl FromBytes for $from { diff --git a/src/hash.rs b/src/hash.rs index 5ead8ab11..6d2c4de95 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -14,7 +14,7 @@ use math::log2; use uint::U256; /// Trait for a fixed-size byte array to be used as the output of hash functions. -/// +/// /// Note: types implementing `FixedHash` must be also `BytesConvertable`. pub trait FixedHash: Sized + BytesConvertable { fn new() -> Self; @@ -33,7 +33,7 @@ pub trait FixedHash: Sized + BytesConvertable { macro_rules! impl_hash { ($from: ident, $size: expr) => { - #[derive(Eq)] + #[derive(Eq, Copy)] pub struct $from (pub [u8; $size]); impl BytesConvertable for $from { diff --git a/src/rlp/mod.rs b/src/rlp/mod.rs index 9c15259bd..8aa816c04 100644 --- a/src/rlp/mod.rs +++ b/src/rlp/mod.rs @@ -1,10 +1,10 @@ -//! Rlp serialization module -//! -//! Allows encoding, decoding, and view onto rlp-slice +//! Rlp serialization module +//! +//! Allows encoding, decoding, and view onto rlp-slice //! //!# What should you use when? //! -//!### Use `encode` function when: +//!### Use `encode` function when: //! * You want to encode something inline. //! * You do not work on big set of data. //! * You want to encode whole data structure at once. @@ -23,7 +23,7 @@ //! * You want to get view onto rlp-slice. //! * You don't want to decode whole rlp at once. //! -//!### Use `UntrustedRlp` when: +//!### Use `UntrustedRlp` when: //! * You are working on untrusted data (~corrupted). //! * You need to handle data corruption errors. //! * You are working on input data. @@ -47,14 +47,16 @@ pub use self::rlpstream::{RlpStream}; use super::hash::H256; pub const NULL_RLP: [u8; 1] = [0x80; 1]; +pub const EMPTY_LIST_RLP: [u8; 1] = [0xC0; 1]; pub const SHA3_NULL_RLP: H256 = H256( [0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x55, 0xa6, 0xff, 0x83, 0x45, 0xe6, 0x92, 0xc0, 0xf8, 0x6e, 0x5b, 0x48, 0xe0, 0x1b, 0x99, 0x6c, 0xad, 0xc0, 0x01, 0x62, 0x2f, 0xb5, 0xe3, 0x63, 0xb4, 0x21] ); +pub const SHA3_EMPTY_LIST_RLP: H256 = H256( [0x1d, 0xcc, 0x4d, 0xe8, 0xde, 0xc7, 0x5d, 0x7a, 0xab, 0x85, 0xb5, 0x67, 0xb6, 0xcc, 0xd4, 0x1a, 0xd3, 0x12, 0x45, 0x1b, 0x94, 0x8a, 0x74, 0x13, 0xf0, 0xa1, 0x42, 0xfd, 0x40, 0xd4, 0x93, 0x47] ); /// Shortcut function to decode trusted rlp -/// +/// /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; -/// +/// /// fn main () { /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; /// let animals: Vec = decode(&data); @@ -71,7 +73,7 @@ pub fn decode(bytes: &[u8]) -> T where T: Decodable { /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; -/// +/// /// fn main () { /// let animals = vec!["cat", "dog"]; /// let out = encode(&animals); diff --git a/src/rlp/rlptraits.rs b/src/rlp/rlptraits.rs index 067c438bf..26b663811 100644 --- a/src/rlp/rlptraits.rs +++ b/src/rlp/rlptraits.rs @@ -1,10 +1,11 @@ -use rlp::DecoderError; +use rlp::{DecoderError, UntrustedRlp}; pub trait Decoder: Sized { fn read_value(&self, f: F) -> Result where F: FnOnce(&[u8]) -> Result; fn as_list(&self) -> Result, DecoderError>; + fn as_rlp<'a>(&'a self) -> &'a UntrustedRlp<'a>; } pub trait Decodable: Sized { @@ -22,11 +23,11 @@ pub trait View<'a, 'view>: Sized { fn new(bytes: &'a [u8]) -> Self; /// The raw data of the RLP. - /// + /// /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; /// let rlp = Rlp::new(&data); @@ -34,7 +35,7 @@ pub trait View<'a, 'view>: Sized { /// assert_eq!(dog, &[0x83, b'd', b'o', b'g']); /// } /// ``` - fn raw(&'view self) -> &'a [u8]; + fn raw(&'view self) -> &'a [u8]; /// Get the prototype of the RLP. fn prototype(&self) -> Self::Prototype; @@ -44,11 +45,11 @@ pub trait View<'a, 'view>: Sized { fn data(&'view self) -> Self::Data; /// Returns number of RLP items. - /// + /// /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; /// let rlp = Rlp::new(&data); @@ -60,11 +61,11 @@ pub trait View<'a, 'view>: Sized { fn item_count(&self) -> usize; /// Returns the number of bytes in the data, or zero if it isn't data. - /// + /// /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; /// let rlp = Rlp::new(&data); @@ -76,14 +77,14 @@ pub trait View<'a, 'view>: Sized { fn size(&self) -> usize; /// Get view onto RLP-slice at index. - /// + /// /// Caches offset to given index, so access to successive /// slices is faster. - /// + /// /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; /// let rlp = Rlp::new(&data); @@ -93,11 +94,11 @@ pub trait View<'a, 'view>: Sized { fn at(&'view self, index: usize) -> Self::Item; /// No value - /// + /// /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let data = vec![]; /// let rlp = Rlp::new(&data); @@ -107,11 +108,11 @@ pub trait View<'a, 'view>: Sized { fn is_null(&self) -> bool; /// Contains a zero-length string or zero-length list. - /// + /// /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let data = vec![0xc0]; /// let rlp = Rlp::new(&data); @@ -121,11 +122,11 @@ pub trait View<'a, 'view>: Sized { fn is_empty(&self) -> bool; /// List value - /// + /// /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; /// let rlp = Rlp::new(&data); @@ -135,11 +136,11 @@ pub trait View<'a, 'view>: Sized { fn is_list(&self) -> bool; /// String value - /// + /// /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; /// let rlp = Rlp::new(&data); @@ -149,11 +150,11 @@ pub trait View<'a, 'view>: Sized { fn is_data(&self) -> bool; /// Int value - /// + /// /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let data = vec![0xc1, 0x10]; /// let rlp = Rlp::new(&data); @@ -164,11 +165,11 @@ pub trait View<'a, 'view>: Sized { fn is_int(&self) -> bool; /// Get iterator over rlp-slices - /// + /// /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; /// let rlp = Rlp::new(&data); @@ -204,7 +205,7 @@ pub trait Stream: Sized { /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let mut stream = RlpStream::new_list(2); /// stream.append(&"cat").append(&"dog"); @@ -219,11 +220,11 @@ pub trait Stream: Sized { /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let mut stream = RlpStream::new_list(2); /// stream.append_list(2).append(&"cat").append(&"dog"); - /// stream.append(&""); + /// stream.append(&""); /// let out = stream.out(); /// assert_eq!(out, vec![0xca, 0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g', 0x80]); /// } @@ -235,7 +236,7 @@ pub trait Stream: Sized { /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let mut stream = RlpStream::new_list(2); /// stream.append_empty_data().append_empty_data(); @@ -249,11 +250,11 @@ pub trait Stream: Sized { fn append_raw<'a>(&'a mut self, bytes: &[u8], item_count: usize) -> &'a mut Self; /// Clear the output stream so far. - /// + /// /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let mut stream = RlpStream::new_list(3); /// stream.append(&"cat"); @@ -269,7 +270,7 @@ pub trait Stream: Sized { /// ```rust /// extern crate ethcore_util as util; /// use util::rlp::*; - /// + /// /// fn main () { /// let mut stream = RlpStream::new_list(2); /// stream.append(&"cat"); @@ -284,7 +285,7 @@ pub trait Stream: Sized { fn raw(&self) -> &[u8]; /// Streams out encoded bytes. - /// + /// /// panic! if stream is not finished. fn out(self) -> Vec; } diff --git a/src/rlp/untrusted_rlp.rs b/src/rlp/untrusted_rlp.rs index d88563c30..b2c7784e7 100644 --- a/src/rlp/untrusted_rlp.rs +++ b/src/rlp/untrusted_rlp.rs @@ -321,6 +321,10 @@ impl<'a> Decoder for BasicDecoder<'a> { .collect(); Ok(v) } + + fn as_rlp<'s>(&'s self) -> &'s UntrustedRlp<'s> { + &self.rlp + } } impl Decodable for T where T: FromBytes { diff --git a/src/sha3.rs b/src/sha3.rs index f7a298c4a..cea953f5c 100644 --- a/src/sha3.rs +++ b/src/sha3.rs @@ -6,20 +6,22 @@ use bytes::BytesConvertable; use hash::{FixedHash, H256}; /// Types implementing this trait are sha3able. -/// +/// /// ``` /// extern crate ethcore_util as util; /// use std::str::FromStr; /// use util::sha3::*; /// use util::hash::*; -/// +/// /// fn main() { /// assert_eq!([0u8; 0].sha3(), H256::from_str("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").unwrap()); /// } /// ``` pub trait Hashable { fn sha3(&self) -> H256; - fn sha3_into(&self, dest: &mut [u8]); + fn sha3_into(&self, dest: &mut [u8]) { + self.sha3().copy_to(dest); + } } impl Hashable for T where T: BytesConvertable { diff --git a/src/uint.rs b/src/uint.rs index b8eccc4cc..6b2af4b3b 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -52,11 +52,17 @@ macro_rules! construct_uint { impl $name { /// Conversion to u32 #[inline] - fn low_u32(&self) -> u32 { + pub fn low_u32(&self) -> u32 { let &$name(ref arr) = self; arr[0] as u32 } + /// Conversion to u64 + #[inline] + pub fn low_u64(&self) -> u64 { + let &$name(ref arr) = self; + arr[0] + } /// Return the least number of bits needed to represent the number #[inline] pub fn bits(&self) -> usize { @@ -101,7 +107,7 @@ macro_rules! construct_uint { pub fn zero() -> $name { From::from(0u64) } - + #[inline] pub fn one() -> $name { From::from(1u64) @@ -410,7 +416,7 @@ macro_rules! construct_uint { fn from_dec_str(value: &str) -> Result { Ok(value.bytes() .map(|b| b - 48) - .fold($name::from(0u64), | acc, c | + .fold($name::from(0u64), | acc, c | // fast multiplication by 10 // (acc << 3) + (acc << 1) => acc * 10 (acc << 3) + (acc << 1) + $name::from(c) @@ -434,6 +440,18 @@ impl From for U256 { } } +impl From for u64 { + fn from(value: U256) -> u64 { + value.low_u64() + } +} + +impl From for u32 { + fn from(value: U256) -> u32 { + value.low_u32() + } +} + pub const ZERO_U256: U256 = U256([0x00u64; 4]); pub const ONE_U256: U256 = U256([0x01u64, 0x00u64, 0x00u64, 0x00u64]); pub const BAD_U256: U256 = U256([0xffffffffffffffffu64; 4]);