-
Notifications
You must be signed in to change notification settings - Fork 245
Unify primitive types for Parity Ethereum and Substrate #86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 17 commits
97c034d
b242323
84b1856
41aa107
96ee827
84f56d8
2eb6b4e
5243639
e61e1c2
d93f59b
765aeb3
52c6847
7803bc4
7989816
37ea789
ee3f55d
59d9672
c264679
7714a2a
5bbb03f
9f22691
cfc2a5d
8a06e41
8d6d787
5adf9f1
559e5a2
dfc65a1
e72a4c8
88efc9b
42f557d
d632b4c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| [package] | ||
| name = "impl-codec" | ||
| version = "0.1.1" | ||
| authors = ["Parity Technologies <admin@parity.io>"] | ||
| license = "Apache-2.0" | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
| homepage = "https://github.com/paritytech/parity-common" | ||
| description = "Parity Codec serialization support for uint and fixed hash." | ||
|
|
||
| [dependencies] | ||
| parity-codec = { version = "2.1", default-features = false } | ||
|
|
||
| [features] | ||
| default = ["std"] | ||
| std = ["parity-codec/std"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| // Copyright 2015-2017 Parity Technologies | ||
|
bkchr marked this conversation as resolved.
Outdated
|
||
| // | ||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
| // option. This file may not be copied, modified, or distributed | ||
| // except according to those terms. | ||
|
|
||
| //! Parity Codec serialization support for uint and fixed hash. | ||
|
|
||
| #![cfg_attr(not(feature = "std"), no_std)] | ||
|
|
||
| #[doc(hidden)] | ||
| pub extern crate parity_codec as codec; | ||
|
|
||
| /// Add Parity Codec serialization support to an integer created by `construct_uint!`. | ||
| #[macro_export] | ||
| macro_rules! impl_uint_codec { | ||
| ($name: ident, $len: expr) => { | ||
| impl $crate::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 $crate::codec::Decode for $name { | ||
| fn decode<I: $crate::codec::Input>(input: &mut I) -> Option<Self> { | ||
| <[u8; $len * 8] as $crate::codec::Decode>::decode(input) | ||
| .map(|b| $name::from_little_endian(&b)) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Add Parity Codec serialization support to a fixed-sized hash type created by `construct_fixed_hash!`. | ||
| #[macro_export] | ||
| macro_rules! impl_fixed_hash_codec { | ||
| ($name: ident, $len: expr) => { | ||
| impl $crate::codec::Encode for $name { | ||
| fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R { | ||
| self.0.using_encoded(f) | ||
| } | ||
| } | ||
| impl $crate::codec::Decode for $name { | ||
| fn decode<I: $crate::codec::Input>(input: &mut I) -> Option<Self> { | ||
| <[u8; $len] as $crate::codec::Decode>::decode(input).map($name) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| [package] | ||
| name = "impl-rlp" | ||
| version = "0.1.1" | ||
| authors = ["Parity Technologies <admin@parity.io>"] | ||
| license = "Apache-2.0" | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
| homepage = "https://github.com/paritytech/parity-common" | ||
| description = "RLP serialization support for uint and fixed hash." | ||
|
|
||
| [dependencies] | ||
| rlp = { version = "0.3", path = "../../rlp", default-features = false } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| // Copyright 2015-2017 Parity Technologies | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
| // option. This file may not be copied, modified, or distributed | ||
| // except according to those terms. | ||
|
|
||
| //! RLP serialization support for uint and fixed hash. | ||
|
|
||
| #[doc(hidden)] | ||
| pub extern crate rlp; | ||
|
|
||
| #[doc(hidden)] | ||
| pub extern crate core as core_; | ||
|
|
||
| /// Add RLP serialization support to an integer created by `construct_uint!`. | ||
| #[macro_export] | ||
| macro_rules! impl_uint_rlp { | ||
| ($name: ident, $size: expr) => { | ||
| impl $crate::rlp::Encodable for $name { | ||
| fn rlp_append(&self, s: &mut $crate::rlp::RlpStream) { | ||
| let leading_empty_bytes = $size - (self.bits() + 7) / 8; | ||
| let mut buffer = [0u8; $size]; | ||
| self.to_big_endian(&mut buffer); | ||
| s.encoder().encode_value(&buffer[leading_empty_bytes..]); | ||
| } | ||
| } | ||
|
|
||
| impl $crate::rlp::Decodable for $name { | ||
| fn decode(rlp: &$crate::rlp::Rlp) -> Result<Self, $crate::rlp::DecoderError> { | ||
| rlp.decoder().decode_value(|bytes| { | ||
| if !bytes.is_empty() && bytes[0] == 0 { | ||
| Err($crate::rlp::DecoderError::RlpInvalidIndirection) | ||
| } else if bytes.len() <= $size { | ||
| Ok($name::from(bytes)) | ||
| } else { | ||
| Err($crate::rlp::DecoderError::RlpIsTooBig) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Add RLP serialization support to a fixed-sized hash type created by `construct_fixed_hash!`. | ||
| #[macro_export] | ||
| macro_rules! impl_fixed_hash_rlp { | ||
| ($name: ident, $size: expr) => { | ||
| impl $crate::rlp::Encodable for $name { | ||
| fn rlp_append(&self, s: &mut $crate::rlp::RlpStream) { | ||
| s.encoder().encode_value(self.as_ref()); | ||
| } | ||
| } | ||
|
|
||
| impl $crate::rlp::Decodable for $name { | ||
| fn decode(rlp: &$crate::rlp::Rlp) -> Result<Self, $crate::rlp::DecoderError> { | ||
| rlp.decoder().decode_value(|bytes| match bytes.len().cmp(&$size) { | ||
| $crate::core_::cmp::Ordering::Less => Err($crate::rlp::DecoderError::RlpIsTooShort), | ||
| $crate::core_::cmp::Ordering::Greater => Err($crate::rlp::DecoderError::RlpIsTooBig), | ||
| $crate::core_::cmp::Ordering::Equal => { | ||
| let mut t = [0u8; $size]; | ||
| t.copy_from_slice(bytes); | ||
| Ok($name(t)) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| [package] | ||
| name = "impl-serde" | ||
| version = "0.1.1" | ||
| authors = ["Parity Technologies <admin@parity.io>"] | ||
| license = "Apache-2.0" | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
| homepage = "https://github.com/paritytech/parity-common" | ||
| description = "Serde serialization support for uint and fixed hash." | ||
|
|
||
| [dependencies] | ||
| serde = "1.0" | ||
| rustc-hex = "2.0.1" | ||
This comment was marked as resolved.
Sorry, something went wrong. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| // Copyright 2015-2017 Parity Technologies | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
| // option. This file may not be copied, modified, or distributed | ||
| // except according to those terms. | ||
|
|
||
| //! Serde serialization support for uint and fixed hash. | ||
|
|
||
| #[doc(hidden)] | ||
| pub extern crate serde; | ||
|
|
||
| #[doc(hidden)] | ||
| pub extern crate rustc_hex; | ||
|
|
||
| #[doc(hidden)] | ||
| pub mod serialize; | ||
|
|
||
| /// Add Serde serialization support to an integer created by `construct_uint!`. | ||
| #[macro_export] | ||
| macro_rules! impl_uint_serde { | ||
| ($name: ident, $len: expr) => { | ||
| impl $crate::serde::Serialize for $name { | ||
| fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: $crate::serde::Serializer { | ||
| let mut bytes = [0u8; $len * 8]; | ||
| self.to_big_endian(&mut bytes); | ||
| $crate::serialize::serialize_uint(&bytes, serializer) | ||
| } | ||
| } | ||
|
|
||
| impl<'de> $crate::serde::Deserialize<'de> for $name { | ||
| fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: $crate::serde::Deserializer<'de> { | ||
| $crate::serialize::deserialize_check_len(deserializer, $crate::serialize::ExpectedLen::Between(0, $len * 8)) | ||
| .map(|x| (&*x).into()) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Add Serde serialization support to a fixed-sized hash type created by `construct_fixed_hash!`. | ||
| #[macro_export] | ||
| macro_rules! impl_fixed_hash_serde { | ||
| ($name: ident, $len: expr) => { | ||
| impl $crate::serde::Serialize for $name { | ||
| fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: $crate::serde::Serializer { | ||
| $crate::serialize::serialize(&self.0, serializer) | ||
| } | ||
| } | ||
|
|
||
| impl<'de> $crate::serde::Deserialize<'de> for $name { | ||
| fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: $crate::serde::Deserializer<'de> { | ||
| $crate::serialize::deserialize_check_len(deserializer, $crate::serialize::ExpectedLen::Exact($len)) | ||
| .map(|x| $name::from_slice(&x)) | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| // Copyright 2015-2017 Parity Technologies | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
| // option. This file may not be copied, modified, or distributed | ||
| // except according to those terms. | ||
|
|
||
| use std::fmt; | ||
|
|
||
| use serde::{de, Serializer, Deserializer}; | ||
|
|
||
| /// 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, Debug)] | ||
| pub enum ExpectedLen { | ||
| /// Any length in bytes. | ||
| 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. | ||
| 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..]) | ||
| }; | ||
|
|
||
| fn format_err(e: ::rustc_hex::FromHexError) -> String { | ||
| format!("invalid hex value: {:?}", e) | ||
| } | ||
|
|
||
| bytes.map_err(|e| E::custom(format_err(e))) | ||
| } | ||
|
|
||
| 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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment tells me this is not new code. It's unfortunate that we're losing git history for these files. :/ Did you consider doing
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me try. This file was from the substrate codebase (and it was adopted from a file in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I gave up... It just span across two different repositories for a really long time with file path changes, which makes it really difficult. |
||
| // (visit_bytes, visit_bytes_buf) | ||
| deserializer.deserialize_str(Visitor { len }) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| [package] | ||
| name = "primitive-types" | ||
| version = "0.1.4" | ||
| authors = ["Parity Technologies <admin@parity.io>"] | ||
| license = "Apache-2.0" | ||
| homepage = "https://github.com/paritytech/parity-common" | ||
| description = "Primitive types shared by Ethereum and Substrate" | ||
|
|
||
| [dependencies] | ||
| fixed-hash = { version = "0.3", path = "../fixed-hash", default-features = false } | ||
| uint = { version = "0.5", path = "../uint", default-features = false } | ||
| crunchy = { version = "0.2", default-features = false } | ||
| impl-serde = { version = "0.1", path = "../impls/serde", default-features = false, optional = true } | ||
| impl-codec = { version = "0.1", path = "../impls/codec", default-features = false, optional = true } | ||
| impl-rlp = { version = "0.1", path = "../impls/rlp", default-features = false, optional = true } | ||
|
|
||
| [features] | ||
| default = ["std"] | ||
| std = ["uint/std", "fixed-hash/std", "crunchy/std", "impl-codec/std"] | ||
| heapsize = ["uint/heapsize", "fixed-hash/heapsize"] | ||
| byteorder = ["fixed-hash/byteorder"] | ||
| libc = ["fixed-hash/libc"] | ||
| rustc-hex = ["fixed-hash/rustc-hex"] | ||
| serde = ["impl-serde"] | ||
| codec = ["impl-codec"] | ||
| rlp = ["impl-rlp"] |
Uh oh!
There was an error while loading. Please reload this page.