Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
97c034d
Implement all uint features
sorpaas Dec 2, 2018
b242323
Improve uint defs and finish fixed hash impls
sorpaas Dec 2, 2018
84b1856
Add license header to everything
sorpaas Dec 2, 2018
41aa107
Fix new crate license field
sorpaas Dec 2, 2018
96ee827
Add docs
sorpaas Dec 2, 2018
84f56d8
Move basic derive to macro
sorpaas Dec 2, 2018
2eb6b4e
Revert uint convenience improvements so that dep PR works
sorpaas Dec 2, 2018
5243639
Fix license of impls
sorpaas Dec 2, 2018
e61e1c2
Fix license of primitive-types
sorpaas Dec 2, 2018
d93f59b
Add U512 in primitive-types
sorpaas Dec 2, 2018
765aeb3
Release primitive-types 0.1.1 so things are not blocked here
sorpaas Dec 2, 2018
52c6847
Remove unused std feature
sorpaas Dec 2, 2018
7803bc4
Fix nostd compile for primitive-types
sorpaas Dec 2, 2018
7989816
Disable std on impl-serde/codec/rlp crate
sorpaas Dec 2, 2018
37ea789
Missed nostd attr in impl-codec
sorpaas Dec 2, 2018
ee3f55d
Remove rlp default features for impl-rlp
sorpaas Dec 3, 2018
59d9672
Add all feature gates from fixed-hash and uint
sorpaas Dec 3, 2018
c264679
Update license
sorpaas Dec 4, 2018
7714a2a
Move impls to primitive-types subfolder
sorpaas Dec 4, 2018
5bbb03f
typo: 2.0.1 -> 2
sorpaas Dec 4, 2018
9f22691
Expand primitive types docs
sorpaas Dec 4, 2018
cfc2a5d
Force std feature in serde and rlp
sorpaas Dec 4, 2018
8a06e41
Fix style nit
sorpaas Dec 4, 2018
8d6d787
Fix unnecessary std dep
sorpaas Dec 4, 2018
5adf9f1
Remove `From<u64>` from primitive types
sorpaas Dec 4, 2018
559e5a2
Copyright year 2015-2018
sorpaas Dec 4, 2018
dfc65a1
Use impl_fixed_hash_conversions
sorpaas Dec 5, 2018
e72a4c8
Merge branch 'master' of https://github.com/paritytech/parity-common …
sorpaas Dec 21, 2018
88efc9b
Use new construct int style
sorpaas Dec 21, 2018
42f557d
Remove crunchy and update uint version
sorpaas Dec 21, 2018
d632b4c
Bump primitive-types patch version
sorpaas Dec 21, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ members = [
"trace-time",
"trie-standardmap",
"triehash",
"uint"
"uint",
"primitive-types",
]
25 changes: 25 additions & 0 deletions primitive-types/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
name = "primitive-types"
version = "0.1.5"
authors = ["Parity Technologies <admin@parity.io>"]
license = "Apache-2.0/MIT"
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.6", path = "../uint", 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", "impl-codec/std"]
heapsize = ["uint/heapsize", "fixed-hash/heapsize"]
byteorder = ["fixed-hash/byteorder"]
libc = ["fixed-hash/libc"]
rustc-hex = ["fixed-hash/rustc-hex"]
serde = ["std", "impl-serde"]
codec = ["impl-codec"]
rlp = ["std", "impl-rlp"]
14 changes: 14 additions & 0 deletions primitive-types/impls/codec/Cargo.toml
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/MIT"
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"]
52 changes: 52 additions & 0 deletions primitive-types/impls/codec/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2015-2018 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.

//! 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)
}
}
}
}
10 changes: 10 additions & 0 deletions primitive-types/impls/rlp/Cargo.toml
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/MIT"
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 }
70 changes: 70 additions & 0 deletions primitive-types/impls/rlp/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2015-2018 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))
}
})
}
}
}
}
11 changes: 11 additions & 0 deletions primitive-types/impls/serde/Cargo.toml
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/MIT"
homepage = "https://github.com/paritytech/parity-common"
description = "Serde serialization support for uint and fixed hash."

[dependencies]
serde = "1.0"
rustc-hex = "2"
58 changes: 58 additions & 0 deletions primitive-types/impls/serde/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2015-2018 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))
}
}
}
}
120 changes: 120 additions & 0 deletions primitive-types/impls/serde/src/serialize.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright 2015-2018 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
// (visit_bytes, visit_bytes_buf)
deserializer.deserialize_str(Visitor { len })
}
Loading