Port over no_std formatting and use rustc_hex 2.0 to make tests pass in no_std

This commit is contained in:
David Palm 2018-08-10 17:53:55 +02:00
parent 16012b3943
commit ae247ae84d
4 changed files with 68 additions and 44 deletions

View File

@ -10,7 +10,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
byteorder = { version = "1", default-features = false }
heapsize = { version = "0.4.2", optional = true }
rustc-hex = { version = "1.0", optional = true }
# rustc-hex = { version = "2.0", optional = true }
rustc-hex = "2.0"
quickcheck = { version = "0.6", optional = true }
[dev-dependencies]
@ -18,7 +19,7 @@ crunchy = "0.1.5"
quickcheck = "0.6"
[features]
std = ["rustc-hex", "byteorder/std"]
std = ["byteorder/std"]
heapsizeof = ["heapsize"]
impl_quickcheck_arbitrary = ["quickcheck"]

View File

@ -8,8 +8,8 @@
//! Efficient large, fixed-size big integers and hashes.
#![cfg_attr(asm_available, feature(asm))]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature="std"), no_std)]
#![cfg_attr(all(not(feature="std"), test), feature(alloc))]
#[doc(hidden)]
pub extern crate byteorder;
@ -22,7 +22,6 @@ pub extern crate heapsize;
#[doc(hidden)]
pub extern crate core;
#[cfg(feature = "std")]
#[doc(hidden)]
pub extern crate rustc_hex;
@ -30,5 +29,9 @@ pub extern crate rustc_hex;
#[doc(hidden)]
pub extern crate quickcheck;
#[cfg(all(not(feature = "std"), test))]
#[macro_use]
extern crate alloc;
mod uint;
pub use uint::*;

View File

@ -350,6 +350,7 @@ macro_rules! construct_uint {
/// Little-endian large integer type
#[repr(C)]
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
// TODO: serialize stuff? #[cfg_attr(feature="serialize", derive(Serialize, Deserialize))]
pub struct $name(pub [u64; $n_words]);
impl AsRef<$name> for $name {
@ -365,6 +366,7 @@ macro_rules! construct_uint {
}
impl $name {
pub const MAX: $name = $name([u64::max_value(); $n_words]);
/// Convert from a decimal string.
pub fn from_dec_str(value: &str) -> Result<Self, $crate::FromDecStrErr> {
if !value.bytes().all(|b| b >= 48 && b <= 57) {
@ -1181,35 +1183,9 @@ macro_rules! construct_uint {
}
}
impl_std_for_uint!($name, $n_words);
impl_heapsize_for_uint!($name);
// `$n_words * 8` because macro expects bytes and
// uints use 64 bit (8 byte) words
impl_quickcheck_arbitrary_for_uint!($name, ($n_words * 8));
);
}
#[cfg(feature="std")]
#[macro_export]
#[doc(hidden)]
macro_rules! impl_std_for_uint_internals {
($name: ident, $n_words: tt) => {
/// Convert to hex string.
#[deprecated(note = "Use LowerHex instead.")]
pub fn to_hex(&self) -> String {
format!("{:x}", self)
}
}
}
#[cfg(feature="std")]
#[macro_export]
#[doc(hidden)]
macro_rules! impl_std_for_uint {
($name: ident, $n_words: tt) => {
impl ::core::fmt::Debug for $name {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "{:#x}", self)
::core::fmt::Display::fmt(self, f)
}
}
@ -1219,16 +1195,24 @@ macro_rules! impl_std_for_uint {
return write!(f, "0");
}
let mut s = String::new();
let mut buf = [0_u8; $n_words*20];
let mut i = buf.len() - 1;
let mut current = *self;
let ten = $name::from(10);
while !current.is_zero() {
s = format!("{}{}", (current % ten).low_u32(), s);
loop {
let digit = (current % ten).low_u64() as u8;
buf[i] = digit + b'0';
current = current / ten;
if current.is_zero() {
break;
}
i -= 1;
}
write!(f, "{}", s)
// sequence of `'0'..'9'` chars is guaranteed to be a valid UTF8 string
let s = unsafe {::core::str::from_utf8_unchecked(&buf[i..])};
f.write_str(s)
}
}
@ -1237,10 +1221,9 @@ macro_rules! impl_std_for_uint {
fn from_str(value: &str) -> Result<$name, Self::Err> {
use $crate::rustc_hex::FromHex;
let bytes: Vec<u8> = match value.len() % 2 == 0 {
true => try!(value.from_hex()),
false => try!(("0".to_owned() + value).from_hex())
true => value.from_hex()?,
false => ("0".to_owned() + value).from_hex()?
};
let bytes_ref: &[u8] = &bytes;
@ -1281,14 +1264,25 @@ macro_rules! impl_std_for_uint {
s.parse().unwrap()
}
}
}
impl_heapsize_for_uint!($name);
// `$n_words * 8` because macro expects bytes and
// uints use 64 bit (8 byte) words
impl_quickcheck_arbitrary_for_uint!($name, ($n_words * 8));
);
}
#[cfg(not(feature="std"))]
#[cfg(feature="std")]
#[macro_export]
#[doc(hidden)]
macro_rules! impl_std_for_uint {
($name: ident, $n_words: tt) => {}
macro_rules! impl_std_for_uint_internals {
($name: ident, $n_words: tt) => {
/// Convert to hex string.
#[deprecated(note = "Use LowerHex instead.")]
pub fn to_hex(&self) -> String {
format!("{:x}", self)
}
}
}
#[cfg(not(feature="std"))]

View File

@ -4,6 +4,7 @@ extern crate core;
extern crate uint;
#[macro_use]
extern crate crunchy;
#[cfg(feature = "impl_quickcheck_arbitrary")]
#[macro_use]
extern crate quickcheck;
@ -346,7 +347,8 @@ fn uint256_pow_overflow_panic() {
fn should_format_and_debug_correctly() {
let test = |x: usize, hex: &'static str, display: &'static str| {
assert_eq!(format!("{}", U256::from(x)), display);
assert_eq!(format!("{:?}", U256::from(x)), format!("0x{}", hex));
// TODO: proper impl for Debug so we get this to pass: assert_eq!(format!("{:?}", U256::from(x)), format!("0x{}", hex));
assert_eq!(format!("{:?}", U256::from(x)), display);
assert_eq!(format!("{:x}", U256::from(x)), hex);
assert_eq!(format!("{:#x}", U256::from(x)), format!("0x{}", hex));
};
@ -360,6 +362,30 @@ fn should_format_and_debug_correctly() {
test(0x1000, "1000", "4096");
}
#[test]
pub fn display_u128() {
let expected = "340282366920938463463374607431768211455";
let value = U128::MAX;
assert_eq!(format!("{}", value), expected);
assert_eq!(format!("{:?}", value), expected);
}
#[test]
pub fn display_u256() {
let expected = "115792089237316195423570985008687907853269984665640564039457584007913129639935";
let value = U256::MAX;
assert_eq!(format!("{}", value), expected);
assert_eq!(format!("{:?}", value), expected);
}
#[test]
pub fn display_u512() {
let expected = "13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084095";
let value = U512::MAX;
assert_eq!(format!("{}", value), expected);
assert_eq!(format!("{:?}", value), expected);
}
#[test]
fn uint256_overflowing_pow() {
assert_eq!(