2016-02-05 13:40:41 +01:00
|
|
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
|
|
|
// This file is part of Parity.
|
|
|
|
|
|
|
|
// Parity is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
|
|
|
// Parity is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2015-11-28 03:58:37 +01:00
|
|
|
//! Unified interfaces for bytes operations on basic types
|
2015-12-26 15:48:41 +01:00
|
|
|
//!
|
2015-11-25 02:53:35 +01:00
|
|
|
//! # Examples
|
2015-11-28 03:58:37 +01:00
|
|
|
//! ```rust
|
|
|
|
//! extern crate ethcore_util as util;
|
2015-12-26 15:48:41 +01:00
|
|
|
//!
|
2015-11-28 03:58:37 +01:00
|
|
|
//! fn bytes_convertable() {
|
|
|
|
//! use util::bytes::BytesConvertable;
|
|
|
|
//!
|
|
|
|
//! let arr = [0; 5];
|
|
|
|
//! let slice: &[u8] = arr.bytes();
|
|
|
|
//! }
|
2015-12-26 15:48:41 +01:00
|
|
|
//!
|
2015-11-28 03:58:37 +01:00
|
|
|
//! fn main() {
|
|
|
|
//! bytes_convertable();
|
|
|
|
//! }
|
|
|
|
//! ```
|
2015-11-25 02:53:35 +01:00
|
|
|
|
|
|
|
use std::fmt;
|
2016-01-08 11:02:32 +01:00
|
|
|
use std::slice;
|
2016-01-13 15:14:24 +01:00
|
|
|
use std::ops::{Deref, DerefMut};
|
2015-11-28 11:25:00 +01:00
|
|
|
use hash::FixedHash;
|
2016-01-27 12:14:57 +01:00
|
|
|
use elastic_array::*;
|
2016-04-17 13:06:14 +02:00
|
|
|
use std::mem;
|
|
|
|
use std::cmp::Ordering;
|
2015-11-25 02:53:35 +01:00
|
|
|
|
2016-01-27 12:14:57 +01:00
|
|
|
/// Vector like object
|
|
|
|
pub trait VecLike<T> {
|
|
|
|
/// Add an element to the collection
|
2016-01-27 16:58:22 +01:00
|
|
|
fn vec_push(&mut self, value: T);
|
2016-01-27 12:14:57 +01:00
|
|
|
|
|
|
|
/// Add a slice to the collection
|
2016-01-27 16:58:22 +01:00
|
|
|
fn vec_extend(&mut self, slice: &[T]);
|
2016-01-27 12:14:57 +01:00
|
|
|
}
|
|
|
|
|
2016-01-27 16:58:22 +01:00
|
|
|
impl<T> VecLike<T> for Vec<T> where T: Copy {
|
|
|
|
fn vec_push(&mut self, value: T) {
|
|
|
|
Vec::<T>::push(self, value)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn vec_extend(&mut self, slice: &[T]) {
|
|
|
|
Vec::<T>::extend_from_slice(self, slice)
|
|
|
|
}
|
|
|
|
}
|
2016-01-27 12:14:57 +01:00
|
|
|
|
|
|
|
macro_rules! impl_veclike_for_elastic_array {
|
|
|
|
($from: ident) => {
|
|
|
|
impl<T> VecLike<T> for $from<T> where T: Copy {
|
2016-01-27 16:58:22 +01:00
|
|
|
fn vec_push(&mut self, value: T) {
|
2016-01-27 12:14:57 +01:00
|
|
|
$from::<T>::push(self, value)
|
|
|
|
}
|
2016-01-27 16:58:22 +01:00
|
|
|
fn vec_extend(&mut self, slice: &[T]) {
|
2016-01-27 12:14:57 +01:00
|
|
|
$from::<T>::append_slice(self, slice)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl_veclike_for_elastic_array!(ElasticArray16);
|
|
|
|
impl_veclike_for_elastic_array!(ElasticArray32);
|
|
|
|
impl_veclike_for_elastic_array!(ElasticArray1024);
|
|
|
|
|
|
|
|
/// Slie pretty print helper
|
2015-12-01 18:25:18 +01:00
|
|
|
pub struct PrettySlice<'a> (&'a [u8]);
|
|
|
|
|
|
|
|
impl<'a> fmt::Debug for PrettySlice<'a> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
for i in 0..self.0.len() {
|
2015-12-01 19:09:48 +01:00
|
|
|
match i > 0 {
|
|
|
|
true => { try!(write!(f, "·{:02x}", self.0[i])); },
|
|
|
|
false => { try!(write!(f, "{:02x}", self.0[i])); },
|
|
|
|
}
|
2015-12-01 18:25:18 +01:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-17 12:43:50 +01:00
|
|
|
impl<'a> fmt::Display for PrettySlice<'a> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
for i in 0..self.0.len() {
|
|
|
|
try!(write!(f, "{:02x}", self.0[i]));
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-03 13:20:32 +01:00
|
|
|
/// Trait to allow a type to be pretty-printed in `format!`, where unoverridable
|
|
|
|
/// defaults cannot otherwise be avoided.
|
2015-12-01 18:25:18 +01:00
|
|
|
pub trait ToPretty {
|
2016-02-03 13:20:32 +01:00
|
|
|
/// Convert a type into a derivative form in order to make `format!` print it prettily.
|
2015-12-01 18:25:18 +01:00
|
|
|
fn pretty(&self) -> PrettySlice;
|
2016-02-03 13:20:32 +01:00
|
|
|
/// Express the object as a hex string.
|
2015-12-17 12:43:50 +01:00
|
|
|
fn to_hex(&self) -> String {
|
|
|
|
format!("{}", self.pretty())
|
|
|
|
}
|
2015-12-01 18:25:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> ToPretty for &'a [u8] {
|
|
|
|
fn pretty(&self) -> PrettySlice {
|
|
|
|
PrettySlice(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> ToPretty for &'a Bytes {
|
|
|
|
fn pretty(&self) -> PrettySlice {
|
|
|
|
PrettySlice(self.bytes())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl ToPretty for Bytes {
|
|
|
|
fn pretty(&self) -> PrettySlice {
|
|
|
|
PrettySlice(self.bytes())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-03 16:43:48 +01:00
|
|
|
/// A byte collection reference that can either be a slice or a vector
|
2016-01-13 15:14:24 +01:00
|
|
|
pub enum BytesRef<'a> {
|
2016-02-03 16:43:48 +01:00
|
|
|
/// This is a reference to a vector
|
2016-01-13 15:14:24 +01:00
|
|
|
Flexible(&'a mut Bytes),
|
2016-02-03 16:43:48 +01:00
|
|
|
/// This is a reference to a slice
|
2016-01-13 15:14:24 +01:00
|
|
|
Fixed(&'a mut [u8])
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Deref for BytesRef<'a> {
|
|
|
|
type Target = [u8];
|
|
|
|
|
|
|
|
fn deref(&self) -> &[u8] {
|
2016-01-19 12:14:29 +01:00
|
|
|
match *self {
|
|
|
|
BytesRef::Flexible(ref bytes) => bytes,
|
2016-02-19 11:31:40 +01:00
|
|
|
BytesRef::Fixed(ref bytes) => bytes,
|
2016-01-13 15:14:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl <'a> DerefMut for BytesRef<'a> {
|
|
|
|
fn deref_mut(&mut self) -> &mut [u8] {
|
2016-01-19 12:14:29 +01:00
|
|
|
match *self {
|
|
|
|
BytesRef::Flexible(ref mut bytes) => bytes,
|
2016-02-19 11:31:40 +01:00
|
|
|
BytesRef::Fixed(ref mut bytes) => bytes,
|
2016-01-13 15:14:24 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-28 03:58:37 +01:00
|
|
|
/// Vector of bytes
|
2015-11-28 00:14:40 +01:00
|
|
|
pub type Bytes = Vec<u8>;
|
|
|
|
|
2015-11-28 03:58:37 +01:00
|
|
|
/// Slice of bytes to underlying memory
|
2015-11-27 17:54:33 +01:00
|
|
|
pub trait BytesConvertable {
|
2016-01-05 19:05:51 +01:00
|
|
|
// TODO: rename to as_slice
|
2016-02-03 13:20:32 +01:00
|
|
|
/// Get the underlying byte-wise representation of the value.
|
|
|
|
/// Deprecated - use `as_slice` instead.
|
2015-11-27 17:54:33 +01:00
|
|
|
fn bytes(&self) -> &[u8];
|
2016-02-03 13:20:32 +01:00
|
|
|
/// Get the underlying byte-wise representation of the value.
|
2016-01-05 19:05:51 +01:00
|
|
|
fn as_slice(&self) -> &[u8] { self.bytes() }
|
2016-02-03 13:20:32 +01:00
|
|
|
/// Get a copy of the underlying byte-wise representation.
|
2016-01-05 19:05:51 +01:00
|
|
|
fn to_bytes(&self) -> Bytes { self.as_slice().to_vec() }
|
2015-11-27 17:54:33 +01:00
|
|
|
}
|
|
|
|
|
2016-02-15 11:54:38 +01:00
|
|
|
impl<T> BytesConvertable for T where T: AsRef<[u8]> {
|
|
|
|
fn bytes(&self) -> &[u8] { self.as_ref() }
|
2015-11-27 18:15:44 +01:00
|
|
|
}
|
|
|
|
|
2015-11-27 17:54:33 +01:00
|
|
|
#[test]
|
|
|
|
fn bytes_convertable() {
|
|
|
|
assert_eq!(vec![0x12u8, 0x34].bytes(), &[0x12u8, 0x34]);
|
2016-03-14 10:53:37 +01:00
|
|
|
assert!([0u8; 0].as_slice().is_empty());
|
2015-11-27 17:54:33 +01:00
|
|
|
}
|
|
|
|
|
2016-01-07 23:59:50 +01:00
|
|
|
/// Simple trait to allow for raw population of a Sized object from a byte slice.
|
|
|
|
pub trait Populatable {
|
2016-01-08 11:02:32 +01:00
|
|
|
/// Copies a bunch of bytes `d` to `self`, overwriting as necessary.
|
|
|
|
///
|
|
|
|
/// If `d` is smaller, zero-out the remaining bytes.
|
2016-01-08 11:43:11 +01:00
|
|
|
fn populate_raw(&mut self, d: &[u8]) {
|
|
|
|
let mut s = self.as_slice_mut();
|
|
|
|
for i in 0..s.len() {
|
|
|
|
s[i] = if i < d.len() {d[i]} else {0};
|
|
|
|
}
|
|
|
|
}
|
2016-01-08 11:02:32 +01:00
|
|
|
|
|
|
|
/// Copies a bunch of bytes `d` to `self`, overwriting as necessary.
|
|
|
|
///
|
|
|
|
/// If `d` is smaller, will leave some bytes untouched.
|
2016-01-08 12:05:38 +01:00
|
|
|
fn copy_raw(&mut self, d: &[u8]) {
|
2016-01-08 11:43:11 +01:00
|
|
|
use std::io::Write;
|
|
|
|
self.as_slice_mut().write(&d).unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Copies the raw representation of an object `d` to `self`, overwriting as necessary.
|
|
|
|
///
|
|
|
|
/// If `d` is smaller, zero-out the remaining bytes.
|
|
|
|
fn populate_raw_from(&mut self, d: &BytesConvertable) { self.populate_raw(d.as_slice()); }
|
|
|
|
|
|
|
|
/// Copies the raw representation of an object `d` to `self`, overwriting as necessary.
|
|
|
|
///
|
|
|
|
/// If `d` is smaller, will leave some bytes untouched.
|
2016-01-08 12:05:38 +01:00
|
|
|
fn copy_raw_from(&mut self, d: &BytesConvertable) { self.copy_raw(d.as_slice()); }
|
2016-01-08 11:43:11 +01:00
|
|
|
|
|
|
|
/// Get the raw slice for this object.
|
|
|
|
fn as_slice_mut(&mut self) -> &mut [u8];
|
2016-01-07 23:59:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Populatable for T where T: Sized {
|
2016-01-08 11:43:11 +01:00
|
|
|
fn as_slice_mut(&mut self) -> &mut [u8] {
|
2016-01-07 23:59:50 +01:00
|
|
|
use std::mem;
|
|
|
|
unsafe {
|
|
|
|
slice::from_raw_parts_mut(self as *mut T as *mut u8, mem::size_of::<T>())
|
2016-01-08 11:43:11 +01:00
|
|
|
}
|
2016-01-07 23:59:50 +01:00
|
|
|
}
|
|
|
|
}
|
2016-01-08 11:02:32 +01:00
|
|
|
|
2016-01-08 11:43:11 +01:00
|
|
|
impl<T> Populatable for [T] where T: Sized {
|
|
|
|
fn as_slice_mut(&mut self) -> &mut [u8] {
|
2016-01-08 11:02:32 +01:00
|
|
|
use std::mem;
|
2016-01-07 23:59:50 +01:00
|
|
|
unsafe {
|
2016-01-08 11:43:11 +01:00
|
|
|
slice::from_raw_parts_mut(self.as_mut_ptr() as *mut u8, mem::size_of::<T>() * self.len())
|
|
|
|
}
|
2016-01-07 23:59:50 +01:00
|
|
|
}
|
|
|
|
}
|
2016-01-08 11:02:32 +01:00
|
|
|
|
2016-02-17 00:32:16 +01:00
|
|
|
#[derive(Debug)]
|
|
|
|
/// Bytes array deserialization error
|
|
|
|
pub enum FromBytesError {
|
|
|
|
/// Not enough bytes for the requested type
|
|
|
|
NotLongEnough,
|
|
|
|
/// Too many bytes for the requested type
|
|
|
|
TooLong,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Value that can be serialized from bytes array
|
|
|
|
pub trait FromRawBytes : Sized {
|
|
|
|
/// function that will instantiate and initialize object from slice
|
|
|
|
fn from_bytes(d: &[u8]) -> Result<Self, FromBytesError>;
|
|
|
|
}
|
|
|
|
|
2016-04-17 10:06:59 +02:00
|
|
|
impl<T> FromRawBytes for T where T: FixedHash {
|
2016-02-17 00:32:16 +01:00
|
|
|
fn from_bytes(bytes: &[u8]) -> Result<Self, FromBytesError> {
|
|
|
|
match bytes.len().cmp(&mem::size_of::<T>()) {
|
|
|
|
Ordering::Less => return Err(FromBytesError::NotLongEnough),
|
|
|
|
Ordering::Greater => return Err(FromBytesError::TooLong),
|
|
|
|
Ordering::Equal => ()
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut res: Self = unsafe { mem::uninitialized() };
|
|
|
|
res.copy_raw(bytes);
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-16 19:11:18 +02:00
|
|
|
impl FromRawBytes for u16 {
|
|
|
|
fn from_bytes(bytes: &[u8]) -> Result<Self, FromBytesError> {
|
|
|
|
match bytes.len().cmp(&2) {
|
|
|
|
Ordering::Less => return Err(FromBytesError::NotLongEnough),
|
|
|
|
Ordering::Greater => return Err(FromBytesError::TooLong),
|
|
|
|
Ordering::Equal => ()
|
|
|
|
};
|
|
|
|
let mut res: Self = unsafe { mem::uninitialized() };
|
|
|
|
res.copy_raw(bytes);
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-17 10:06:59 +02:00
|
|
|
/// Value that can be serialized from variable-length byte array
|
|
|
|
pub trait FromRawBytesVariable : Sized {
|
|
|
|
/// Create value from slice
|
2016-04-17 13:06:14 +02:00
|
|
|
fn from_bytes_variable(bytes: &[u8]) -> Result<Self, FromBytesError>;
|
2016-04-17 10:06:59 +02:00
|
|
|
}
|
2016-04-16 19:11:18 +02:00
|
|
|
|
2016-04-17 10:06:59 +02:00
|
|
|
impl<T> FromRawBytesVariable for T where T: FromRawBytes {
|
2016-04-17 13:06:14 +02:00
|
|
|
fn from_bytes_variable(bytes: &[u8]) -> Result<Self, FromBytesError> {
|
|
|
|
match bytes.len().cmp(&mem::size_of::<T>()) {
|
2016-04-16 19:11:18 +02:00
|
|
|
Ordering::Less => return Err(FromBytesError::NotLongEnough),
|
|
|
|
Ordering::Greater => return Err(FromBytesError::TooLong),
|
|
|
|
Ordering::Equal => ()
|
|
|
|
};
|
|
|
|
|
2016-04-17 13:06:14 +02:00
|
|
|
T::from_bytes(bytes)
|
2016-04-16 19:11:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromRawBytesVariable for String {
|
2016-04-17 13:06:14 +02:00
|
|
|
fn from_bytes_variable(bytes: &[u8]) -> Result<String, FromBytesError> {
|
2016-02-17 00:32:16 +01:00
|
|
|
Ok(::std::str::from_utf8(bytes).unwrap().to_owned())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-16 19:11:18 +02:00
|
|
|
impl<T> FromRawBytesVariable for Vec<T> where T: FromRawBytes {
|
2016-04-17 13:06:14 +02:00
|
|
|
fn from_bytes_variable(bytes: &[u8]) -> Result<Self, FromBytesError> {
|
|
|
|
let size_of_t = mem::size_of::<T>();
|
|
|
|
let length_in_chunks = bytes.len() / size_of_t;
|
|
|
|
|
|
|
|
let mut result = Vec::with_capacity(length_in_chunks );
|
|
|
|
unsafe { result.set_len(length_in_chunks) };
|
|
|
|
for i in 0..length_in_chunks {
|
|
|
|
*result.get_mut(i).unwrap() = try!(T::from_bytes(
|
|
|
|
&bytes[size_of_t * i..size_of_t * (i+1)]))
|
|
|
|
}
|
2016-04-16 19:11:18 +02:00
|
|
|
Ok(result)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<V1, T2> FromRawBytes for (V1, T2) where V1: FromRawBytesVariable, T2: FromRawBytes {
|
2016-04-17 13:06:14 +02:00
|
|
|
fn from_bytes(bytes: &[u8]) -> Result<Self, FromBytesError> {
|
2016-04-16 19:11:18 +02:00
|
|
|
let header = 8usize;
|
2016-04-17 13:06:14 +02:00
|
|
|
let mut map: (u64, ) = unsafe { mem::uninitialized() };
|
2016-04-16 19:11:18 +02:00
|
|
|
|
2016-04-17 13:06:14 +02:00
|
|
|
if bytes.len() < header { return Err(FromBytesError::NotLongEnough); }
|
|
|
|
map.copy_raw(&bytes[0..header]);
|
2016-04-16 19:11:18 +02:00
|
|
|
|
|
|
|
Ok((
|
2016-04-17 13:06:14 +02:00
|
|
|
try!(V1::from_bytes_variable(&bytes[header..header + (map.0 as usize)])),
|
|
|
|
try!(T2::from_bytes(&bytes[header + (map.0 as usize)..bytes.len()])),
|
2016-04-16 19:11:18 +02:00
|
|
|
))
|
2016-02-17 00:32:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-17 13:06:14 +02:00
|
|
|
impl<V1, T2> BytesConvertable for (Vec<V1>, T2) where V1: BytesConvertable, T2: BytesConvertable {
|
|
|
|
fn bytes(&self) -> &[u8] {
|
|
|
|
let header = 8usize;
|
|
|
|
let mut result = Vec::new(header + self.0.len() * mem::size_of::<V1>() + mem::size_of::<T2>());
|
|
|
|
|
|
|
|
*result[0..header] = (self.0.len() as u64).as_slice();
|
|
|
|
for i in 0..self.0.len() {
|
|
|
|
*result[header + i*mem::size_of::<V1>()..header + (i+1)*mem::size_of::<V1>()] =
|
|
|
|
self.0[i].as_slice();
|
|
|
|
}
|
|
|
|
*result[header + self.0.len()..result.len()] = self.1.as_slice();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromRawBytesVariable for Vec<u8> {
|
|
|
|
fn from_bytes_variable(bytes: &[u8]) -> Result<Vec<u8>, FromBytesError> {
|
|
|
|
Ok(bytes.clone().to_vec())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-08 11:02:32 +01:00
|
|
|
#[test]
|
2016-01-08 11:43:11 +01:00
|
|
|
fn fax_raw() {
|
2016-01-08 11:02:32 +01:00
|
|
|
let mut x = [255u8; 4];
|
2016-01-08 12:05:38 +01:00
|
|
|
x.copy_raw(&[1u8; 2][..]);
|
2016-01-08 11:02:32 +01:00
|
|
|
assert_eq!(x, [1u8, 1, 255, 255]);
|
2016-01-08 11:43:11 +01:00
|
|
|
let mut x = [255u8; 4];
|
2016-01-08 12:05:38 +01:00
|
|
|
x.copy_raw(&[1u8; 6][..]);
|
2016-01-08 11:02:32 +01:00
|
|
|
assert_eq!(x, [1u8, 1, 1, 1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn populate_raw() {
|
|
|
|
let mut x = [255u8; 4];
|
|
|
|
x.populate_raw(&[1u8; 2][..]);
|
|
|
|
assert_eq!(x, [1u8, 1, 0, 0]);
|
2016-01-08 11:43:11 +01:00
|
|
|
let mut x = [255u8; 4];
|
2016-01-08 11:02:32 +01:00
|
|
|
x.populate_raw(&[1u8; 6][..]);
|
|
|
|
assert_eq!(x, [1u8, 1, 1, 1]);
|
2016-01-08 11:43:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn populate_raw_dyn() {
|
|
|
|
let mut x = [255u8; 4];
|
|
|
|
x.populate_raw(&[1u8; 2][..]);
|
|
|
|
assert_eq!(&x[..], [1u8, 1, 0, 0]);
|
|
|
|
let mut x = [255u8; 4];
|
|
|
|
x.populate_raw(&[1u8; 6][..]);
|
|
|
|
assert_eq!(&x[..], [1u8, 1, 1, 1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn fax_raw_dyn() {
|
|
|
|
let mut x = [255u8; 4];
|
2016-01-08 12:05:38 +01:00
|
|
|
x.copy_raw(&[1u8; 2][..]);
|
2016-01-08 11:43:11 +01:00
|
|
|
assert_eq!(&x[..], [1u8, 1, 255, 255]);
|
|
|
|
let mut x = [255u8; 4];
|
2016-01-08 12:05:38 +01:00
|
|
|
x.copy_raw(&[1u8; 6][..]);
|
2016-01-08 11:43:11 +01:00
|
|
|
assert_eq!(&x[..], [1u8, 1, 1, 1]);
|
2016-01-08 12:02:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn populate_big_types() {
|
|
|
|
use hash::*;
|
|
|
|
let a = address_from_hex("ffffffffffffffffffffffffffffffffffffffff");
|
|
|
|
let mut h = h256_from_u64(0x69);
|
|
|
|
h.populate_raw_from(&a);
|
|
|
|
assert_eq!(h, h256_from_hex("ffffffffffffffffffffffffffffffffffffffff000000000000000000000000"));
|
|
|
|
let mut h = h256_from_u64(0x69);
|
2016-01-08 12:05:38 +01:00
|
|
|
h.copy_raw_from(&a);
|
2016-01-08 12:02:26 +01:00
|
|
|
assert_eq!(h, h256_from_hex("ffffffffffffffffffffffffffffffffffffffff000000000000000000000069"));
|
2016-01-13 15:14:24 +01:00
|
|
|
}
|
2016-04-16 19:11:18 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn raw_bytes_from_tuple() {
|
|
|
|
let tup = (vec![1u16, 1u16, 1u16, 1u16], 10u16);
|
|
|
|
let bytes = vec![
|
|
|
|
// map
|
2016-04-17 10:06:59 +02:00
|
|
|
8u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
|
2016-04-16 19:11:18 +02:00
|
|
|
// four 1u16
|
2016-04-17 10:06:59 +02:00
|
|
|
1u8, 0u8,
|
|
|
|
1u8, 0u8,
|
|
|
|
1u8, 0u8,
|
|
|
|
1u8, 0u8,
|
2016-04-16 19:11:18 +02:00
|
|
|
// 10u16
|
2016-04-17 10:06:59 +02:00
|
|
|
10u8, 0u8];
|
2016-04-16 19:11:18 +02:00
|
|
|
|
2016-04-17 10:06:59 +02:00
|
|
|
type Tup = (Vec<u16>, u16);
|
2016-04-16 19:11:18 +02:00
|
|
|
|
2016-04-17 10:06:59 +02:00
|
|
|
let tup_from = Tup::from_bytes(&bytes).unwrap();
|
2016-04-16 19:11:18 +02:00
|
|
|
assert_eq!(tup, tup_from);
|
2016-04-17 13:06:14 +02:00
|
|
|
|
|
|
|
let bytes_to = Tup::as_slice();
|
|
|
|
assert_eq!(bytes_to, bytes);
|
2016-04-16 19:11:18 +02:00
|
|
|
}
|