From 4e520dfc9dca66fbbb9c53572c4d6cdeef52fccd Mon Sep 17 00:00:00 2001 From: Sam Wilson Date: Thu, 17 Dec 2020 15:29:42 -0500 Subject: [PATCH] Implement Num from num-traits --- ethereum-types/Cargo.toml | 1 + ethereum-types/src/lib.rs | 2 + primitive-types/Cargo.toml | 2 + primitive-types/impls/num-traits/Cargo.toml | 16 +++ primitive-types/impls/num-traits/src/lib.rs | 127 ++++++++++++++++++++ primitive-types/src/lib.rs | 12 ++ 6 files changed, 160 insertions(+) create mode 100644 primitive-types/impls/num-traits/Cargo.toml create mode 100644 primitive-types/impls/num-traits/src/lib.rs diff --git a/ethereum-types/Cargo.toml b/ethereum-types/Cargo.toml index e3b413f20..544d6fa69 100644 --- a/ethereum-types/Cargo.toml +++ b/ethereum-types/Cargo.toml @@ -26,3 +26,4 @@ serialize = ["std", "impl-serde", "primitive-types/serde", "ethbloom/serialize"] arbitrary = ["ethbloom/arbitrary", "fixed-hash/arbitrary", "uint-crate/arbitrary"] rlp = ["impl-rlp", "ethbloom/rlp", "primitive-types/rlp"] codec = ["impl-codec", "ethbloom/codec"] +num-traits = ["primitive-types/num-traits"] diff --git a/ethereum-types/src/lib.rs b/ethereum-types/src/lib.rs index d94ae57c0..ce84e3731 100644 --- a/ethereum-types/src/lib.rs +++ b/ethereum-types/src/lib.rs @@ -13,6 +13,8 @@ mod uint; pub use ethbloom::{Bloom, BloomRef, Input as BloomInput}; pub use hash::{BigEndianHash, H128, H160, H256, H264, H32, H512, H520, H64}; +#[cfg(feature = "num-traits")] +pub use primitive_types::{FromStrRadixErr, FromStrRadixErrKind}; pub use uint::{FromDecStrErr, U128, U256, U512, U64}; pub type Address = H160; diff --git a/primitive-types/Cargo.toml b/primitive-types/Cargo.toml index d881bce56..4c691d812 100644 --- a/primitive-types/Cargo.toml +++ b/primitive-types/Cargo.toml @@ -12,6 +12,7 @@ fixed-hash = { version = "0.6", path = "../fixed-hash", default-features = false uint = { version = "0.8.3", path = "../uint", default-features = false } impl-serde = { version = "0.3.1", path = "impls/serde", default-features = false, optional = true } impl-codec = { version = "0.4.1", path = "impls/codec", default-features = false, optional = true } +impl-num-traits = { version = "0.1.0", path = "impls/num-traits", default-features = false, optional = true } impl-rlp = { version = "0.3", path = "impls/rlp", default-features = false, optional = true } scale-info = { version = "0.4", features = ["derive"], default-features = false, optional = true } @@ -26,6 +27,7 @@ codec = ["impl-codec"] rlp = ["impl-rlp"] arbitrary = ["fixed-hash/arbitrary", "uint/arbitrary"] fp-conversion = ["std"] +num-traits = ["impl-num-traits"] [[test]] name = "scale_info" diff --git a/primitive-types/impls/num-traits/Cargo.toml b/primitive-types/impls/num-traits/Cargo.toml new file mode 100644 index 000000000..fed7c898e --- /dev/null +++ b/primitive-types/impls/num-traits/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "impl-num-traits" +version = "0.1.0" +authors = ["Parity Technologies "] +license = "MIT OR Apache-2.0" +homepage = "https://github.com/paritytech/parity-common" +description = "num-traits implementation for uint." +edition = "2018" + +[dependencies] +num-traits = { version = "0.2", default-features = false } +uint = { version = "0.8.5", path = "../../../uint", default-features = false } + +[features] +default = ["std"] +std = ["num-traits/std", "uint/std"] diff --git a/primitive-types/impls/num-traits/src/lib.rs b/primitive-types/impls/num-traits/src/lib.rs new file mode 100644 index 000000000..0cd8e0cf5 --- /dev/null +++ b/primitive-types/impls/num-traits/src/lib.rs @@ -0,0 +1,127 @@ +// Copyright 2020 Parity Technologies +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! num-traits support for uint. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[doc(hidden)] +pub use num_traits; + +use core::fmt; + +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +pub enum FromStrRadixErrKind { + Parse, + UnsupportedRadix, +} + +#[derive(Debug)] +enum FromStrRadixErrSrc { + Hex(uint::FromHexError), + Dec(uint::FromDecStrErr), +} + +impl fmt::Display for FromStrRadixErrSrc { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + FromStrRadixErrSrc::Dec(d) => write!(f, "{}", d), + FromStrRadixErrSrc::Hex(h) => write!(f, "{}", h), + } + } +} + +#[derive(Debug)] +pub struct FromStrRadixErr { + kind: FromStrRadixErrKind, + source: Option, +} + +impl FromStrRadixErr { + pub fn unsupported() -> Self { + Self { kind: FromStrRadixErrKind::UnsupportedRadix, source: None } + } + + pub fn kind(&self) -> FromStrRadixErrKind { + self.kind + } +} + +impl fmt::Display for FromStrRadixErr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.kind { + FromStrRadixErrKind::UnsupportedRadix => write!(f, "the given radix is not supported"), + FromStrRadixErrKind::Parse => match self.source { + Some(ref src) => write!(f, "{}", src), + None => write!(f, "parsing error"), + }, + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for FromStrRadixErr { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self.source { + Some(FromStrRadixErrSrc::Dec(ref d)) => Some(d), + Some(FromStrRadixErrSrc::Hex(ref h)) => Some(h), + None => None, + } + } +} + +impl From for FromStrRadixErr { + fn from(e: uint::FromDecStrErr) -> Self { + Self { kind: FromStrRadixErrKind::Parse, source: Some(FromStrRadixErrSrc::Dec(e)) } + } +} + +impl From for FromStrRadixErr { + fn from(e: uint::FromHexError) -> Self { + Self { kind: FromStrRadixErrKind::Parse, source: Some(FromStrRadixErrSrc::Hex(e)) } + } +} + +/// Add num-traits support to an integer created by `construct_uint!`. +#[macro_export] +macro_rules! impl_uint_num_traits { + ($name: ident, $len: expr) => { + impl $crate::num_traits::identities::Zero for $name { + #[inline] + fn zero() -> Self { + Self::zero() + } + + #[inline] + fn is_zero(&self) -> bool { + self.is_zero() + } + } + + impl $crate::num_traits::identities::One for $name { + #[inline] + fn one() -> Self { + Self::one() + } + } + + impl $crate::num_traits::Num for $name { + type FromStrRadixErr = $crate::FromStrRadixErr; + + fn from_str_radix(txt: &str, radix: u32) -> Result { + let parsed = match radix { + 10 => Self::from_dec_str(txt)?, + 16 => core::str::FromStr::from_str(txt)?, + _ => return Err(Self::FromStrRadixErr::unsupported()), + }; + + Ok(parsed) + } + } + }; +} diff --git a/primitive-types/src/lib.rs b/primitive-types/src/lib.rs index fe1eb4ac7..74a0d6773 100644 --- a/primitive-types/src/lib.rs +++ b/primitive-types/src/lib.rs @@ -19,6 +19,8 @@ mod fp_conversion; use core::convert::TryFrom; use fixed_hash::{construct_fixed_hash, impl_fixed_hash_conversions}; +#[cfg(feature = "num-traits")] +pub use impl_num_traits::{FromStrRadixErr, FromStrRadixErrKind}; #[cfg(feature = "scale-info")] use scale_info::TypeInfo; use uint::{construct_uint, uint_full_mul_reg}; @@ -68,6 +70,16 @@ construct_fixed_hash! { pub struct H512(64); } +#[cfg(feature = "num-traits")] +mod num_traits { + use super::*; + use impl_num_traits::impl_uint_num_traits; + + impl_uint_num_traits!(U128, 2); + impl_uint_num_traits!(U256, 4); + impl_uint_num_traits!(U512, 8); +} + #[cfg(feature = "impl-serde")] mod serde { use super::*;