implemented rem, lenient from_str, from_dec_str for uint

This commit is contained in:
debris 2015-12-12 06:04:24 +01:00
parent 16cadf1a64
commit 862702b9c7

View File

@ -28,6 +28,11 @@ use std::str::FromStr;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use rustc_serialize::hex::{FromHex, FromHexError}; use rustc_serialize::hex::{FromHex, FromHexError};
pub trait FromDecStr: Sized {
type Err;
fn from_dec_str(value: &str) -> Result<Self, Self::Err>;
}
macro_rules! impl_map_from { macro_rules! impl_map_from {
($thing:ident, $from:ty, $to:ty) => { ($thing:ident, $from:ty, $to:ty) => {
impl From<$from> for $thing { impl From<$from> for $thing {
@ -139,8 +144,13 @@ macro_rules! construct_uint {
type Err = FromHexError; type Err = FromHexError;
fn from_str(value: &str) -> Result<$name, Self::Err> { fn from_str(value: &str) -> Result<$name, Self::Err> {
let bytes: &[u8] = &try!(value.from_hex()); let bytes: Vec<u8> = match value.len() % 2 == 0 {
Ok(From::from(bytes)) true => try!(value.from_hex()),
false => try!(("0".to_string() + value).from_hex())
};
let bytes_ref: &[u8] = &bytes;
Ok(From::from(bytes_ref))
} }
} }
@ -222,6 +232,15 @@ macro_rules! construct_uint {
} }
} }
impl Rem<$name> for $name {
type Output = $name;
fn rem(self, other: $name) -> $name {
let times = self / other;
self - (times * other)
}
}
impl BitAnd<$name> for $name { impl BitAnd<$name> for $name {
type Output = $name; type Output = $name;
@ -358,9 +377,21 @@ macro_rules! construct_uint {
state.finish(); state.finish();
} }
} }
impl FromDecStr for $name {
type Err = FromHexError;
/// TODO: optimize, throw appropriate err
fn from_dec_str(value: &str) -> Result<Self, Self::Err> {
let ten = $name::from(10u64);
Ok(value.bytes().map(|b| b - 48).fold($name::from(0u64), | acc, c | acc * ten + $name::from(c) ))
}
}
); );
} }
construct_uint!(U512, 8);
construct_uint!(U256, 4); construct_uint!(U256, 4);
construct_uint!(U128, 2); construct_uint!(U128, 2);
@ -374,6 +405,10 @@ impl From<U128> for U256 {
} }
} }
pub const ZERO_U256: U256 = U256([0x00u64; 4]); pub const ZERO_U256: U256 = U256([0x00u64; 4]);
pub const ONE_U256: U256 = U256([0x01u64, 0x00u64, 0x00u64, 0x00u64]); pub const ONE_U256: U256 = U256([0x01u64, 0x00u64, 0x00u64, 0x00u64]);
pub const BAD_U256: U256 = U256([0xffffffffffffffffu64; 4]); pub const BAD_U256: U256 = U256([0xffffffffffffffffu64; 4]);
@ -381,6 +416,7 @@ pub const BAD_U256: U256 = U256([0xffffffffffffffffu64; 4]);
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use uint::U256; use uint::U256;
use uint::FromDecStr;
use std::str::FromStr; use std::str::FromStr;
#[test] #[test]
@ -565,5 +601,17 @@ mod tests {
assert_eq!(U256::from(10u64) / U256::from(2u64), U256::from(5u64)); assert_eq!(U256::from(10u64) / U256::from(2u64), U256::from(5u64));
assert_eq!(U256::from(10u64) / U256::from(3u64), U256::from(3u64)); assert_eq!(U256::from(10u64) / U256::from(3u64), U256::from(3u64));
} }
#[test]
fn uint256_rem() {
assert_eq!(U256::from(10u64) % U256::from(1u64), U256::from(0u64));
assert_eq!(U256::from(10u64) % U256::from(3u64), U256::from(1u64));
}
#[test]
fn uint256_from_dec_str() {
assert_eq!(U256::from_dec_str("10").unwrap(), U256::from(10u64));
assert_eq!(U256::from_dec_str("1024").unwrap(), U256::from(1024u64));
}
} }