Use primitive-types crate to unify Parity Ethereum primitives (#1187)

* Unify primitive types with parity-ethereum

* Update primtive-types patch version

* Fix merge issue

* Add necessary fixed-hash features

* Fix node-primitives compile

* Reexport impl_serde::serialize as bytes to avoid path changes
This commit is contained in:
Wei Tang
2019-01-07 15:54:59 +01:00
committed by Gav Wood
parent cb52401350
commit f5c4abd0f3
8 changed files with 55 additions and 290 deletions
@@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
#[cfg(feature = "std")]
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use H256;
-158
View File
@@ -1,158 +0,0 @@
// Copyright 2017-2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate 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.
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Simple type for representing Vec<u8> with regards to serde.
use core::fmt;
use serde::{de, Serializer, Deserializer};
#[cfg(not(feature = "std"))]
mod alloc_types {
pub use ::alloc::string::String;
pub use ::alloc::vec::Vec;
}
#[cfg(feature = "std")]
mod alloc_types {
pub use ::std::vec::Vec;
pub use ::std::string::String;
}
pub use self::alloc_types::*;
/// Serializes a slice of bytes.
pub fn serialize<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error> where
S: Serializer,
{
let hex: String = ::rustc_hex::ToHex::to_hex(bytes);
serializer.serialize_str(&format!("0x{}", hex))
}
/// Serialize a slice of bytes as uint.
///
/// The representation will have all leading zeros trimmed.
pub fn serialize_uint<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error> where
S: Serializer,
{
let non_zero = bytes.iter().take_while(|b| **b == 0).count();
let bytes = &bytes[non_zero..];
if bytes.is_empty() {
return serializer.serialize_str("0x0");
}
let hex: String = ::rustc_hex::ToHex::to_hex(bytes);
let has_leading_zero = !hex.is_empty() && &hex[0..1] == "0";
serializer.serialize_str(
&format!("0x{}", if has_leading_zero { &hex[1..] } else { &hex })
)
}
/// Expected length of bytes vector.
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum ExpectedLen {
/// Any length in bytes.
#[cfg_attr(not(feature = "std"), allow(unused))]
Any,
/// Exact length in bytes.
Exact(usize),
/// A bytes length between (min; max].
Between(usize, usize),
}
impl fmt::Display for ExpectedLen {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
ExpectedLen::Any => write!(fmt, "even length"),
ExpectedLen::Exact(v) => write!(fmt, "length of {}", v * 2),
ExpectedLen::Between(min, max) => write!(fmt, "length between ({}; {}]", min * 2, max * 2),
}
}
}
/// Deserialize into vector of bytes.
#[cfg(feature = "std")]
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error> where
D: Deserializer<'de>,
{
deserialize_check_len(deserializer, ExpectedLen::Any)
}
/// Deserialize into vector of bytes with additional size check.
pub fn deserialize_check_len<'de, D>(deserializer: D, len: ExpectedLen) -> Result<Vec<u8>, D::Error> where
D: Deserializer<'de>,
{
struct Visitor {
len: ExpectedLen,
}
impl<'a> de::Visitor<'a> for Visitor {
type Value = Vec<u8>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a 0x-prefixed hex string with {}", self.len)
}
fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
if v.len() < 2 || &v[0..2] != "0x" {
return Err(E::custom("prefix is missing"))
}
let is_len_valid = match self.len {
// just make sure that we have all nibbles
ExpectedLen::Any => v.len() % 2 == 0,
ExpectedLen::Exact(len) => v.len() == 2 * len + 2,
ExpectedLen::Between(min, max) => v.len() <= 2 * max + 2 && v.len() > 2 * min + 2,
};
if !is_len_valid {
return Err(E::invalid_length(v.len() - 2, &self))
}
let bytes = match self.len {
ExpectedLen::Between(..) if v.len() % 2 != 0 => {
::rustc_hex::FromHex::from_hex(&*format!("0{}", &v[2..]))
},
_ => ::rustc_hex::FromHex::from_hex(&v[2..])
};
#[cfg(feature = "std")]
fn format_err(e: ::rustc_hex::FromHexError) -> String {
format!("invalid hex value: {:?}", e)
}
#[cfg(not(feature = "std"))]
fn format_err(e: ::rustc_hex::FromHexError) -> String {
match e {
::rustc_hex::InvalidHexLength => format!("invalid hex value: invalid length"),
::rustc_hex::InvalidHexCharacter(c, p) =>
format!("invalid hex value: invalid character {} at position {}", c, p),
}
}
bytes.map_err(|e| E::custom(format_err(e)))
}
#[cfg(feature = "std")]
fn visit_string<E: de::Error>(self, v: String) -> Result<Self::Value, E> {
self.visit_str(&v)
}
}
// TODO [ToDr] Use raw bytes if we switch to RLP / binencoding
// (visit_bytes, visit_bytes_buf)
deserializer.deserialize_str(Visitor { len })
}
+1 -59
View File
@@ -16,65 +16,7 @@
//! A fixed hash type.
#[cfg(feature = "std")]
use serde::{Serialize, Serializer, Deserialize, Deserializer};
#[cfg(feature = "std")]
use bytes;
macro_rules! impl_rest {
($name: ident, $len: expr) => {
#[cfg(feature = "std")]
impl Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
bytes::serialize(&self.0, serializer)
}
}
#[cfg(feature = "std")]
impl<'de> Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
bytes::deserialize_check_len(deserializer, bytes::ExpectedLen::Exact($len))
.map(|x| $name::from_slice(&x))
}
}
impl ::codec::Encode for $name {
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
self.0.using_encoded(f)
}
}
impl ::codec::Decode for $name {
fn decode<I: ::codec::Input>(input: &mut I) -> Option<Self> {
<[u8; $len] as ::codec::Decode>::decode(input).map($name)
}
}
#[cfg(feature = "std")]
impl From<u64> for $name {
fn from(val: u64) -> Self {
Self::from_low_u64_be(val)
}
}
}
}
construct_fixed_hash!{
/// Fixed-size uninterpreted hash type with 20 bytes (160 bits) size.
pub struct H160(20);
}
construct_fixed_hash!{
/// Fixed-size uninterpreted hash type with 32 bytes (256 bits) size.
pub struct H256(32);
}
construct_fixed_hash!{
/// Fixed-size uninterpreted hash type with 64 bytes (512 bits) size.
pub struct H512(64);
}
impl_rest!(H160, 20);
impl_rest!(H256, 32);
impl_rest!(H512, 64);
pub use primitive_types::{H160, H256, H512};
/// Hash conversion. Used to convert between unbound associated hash types in traits,
/// implemented by the same hash type.
+1 -2
View File
@@ -57,7 +57,7 @@ impl AsBytesRef for [u8] {
fn as_bytes_ref(&self) -> &[u8] { &self }
}
impl AsBytesRef for ::bytes::Vec<u8> {
impl AsBytesRef for Vec<u8> {
fn as_bytes_ref(&self) -> &[u8] { &self }
}
@@ -91,4 +91,3 @@ pub fn ascii_format(asciish: &[u8]) -> String {
}
r
}
+7 -7
View File
@@ -21,12 +21,7 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(alloc))]
#[macro_use]
extern crate crunchy;
#[macro_use]
extern crate fixed_hash;
#[macro_use]
extern crate uint as uint_crate;
extern crate primitive_types;
#[macro_use]
extern crate parity_codec_derive;
@@ -51,6 +46,10 @@ extern crate untrusted;
#[macro_use]
extern crate hex_literal;
#[cfg(feature = "std")]
#[macro_use]
extern crate impl_serde;
#[cfg(feature = "std")]
#[macro_use]
extern crate serde_derive;
@@ -84,7 +83,8 @@ use rstd::prelude::*;
use rstd::ops::Deref;
#[cfg(feature = "std")]
pub mod bytes;
pub use impl_serde::serialize as bytes;
#[cfg(feature = "std")]
pub mod hashing;
#[cfg(feature = "std")]
+1 -49
View File
@@ -16,55 +16,7 @@
//! An unsigned fixed-size integer.
#[cfg(feature = "std")]
use serde::{Serialize, Serializer, Deserialize, Deserializer};
#[cfg(feature = "std")]
use bytes;
macro_rules! impl_serde {
($name: ident, $len: expr) => {
#[cfg(feature = "std")]
impl Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
let mut bytes = [0u8; $len * 8];
self.to_big_endian(&mut bytes);
bytes::serialize_uint(&bytes, serializer)
}
}
#[cfg(feature = "std")]
impl<'de> Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
bytes::deserialize_check_len(deserializer, bytes::ExpectedLen::Between(0, $len * 8))
.map(|x| (&*x).into())
}
}
}
}
macro_rules! impl_codec {
($name: ident, $len: expr) => {
impl ::codec::Encode for $name {
fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
let mut bytes = [0u8; $len * 8];
self.to_little_endian(&mut bytes);
bytes.using_encoded(f)
}
}
impl ::codec::Decode for $name {
fn decode<I: ::codec::Input>(input: &mut I) -> Option<Self> {
<[u8; $len * 8] as ::codec::Decode>::decode(input)
.map(|b| $name::from_little_endian(&b))
}
}
}
}
construct_uint!(U256, 4);
impl_serde!(U256, 4);
impl_codec!(U256, 4);
pub use primitive_types::U256;
#[cfg(test)]
mod tests {