Add hex parsing to pow types
The `pow` types implement `fmt::LowerHex` but do not implement hex parsing. Add inherent methods `from_hex` and `from_prefixed_hex` to the `pow` types.
This commit is contained in:
parent
d33625f6e2
commit
f019e24f1f
|
@ -18,12 +18,22 @@ use units::parse;
|
||||||
use crate::blockdata::block::BlockHash;
|
use crate::blockdata::block::BlockHash;
|
||||||
use crate::consensus::encode::{self, Decodable, Encodable};
|
use crate::consensus::encode::{self, Decodable, Encodable};
|
||||||
use crate::consensus::Params;
|
use crate::consensus::Params;
|
||||||
use crate::error::{ContainsPrefixError, MissingPrefixError, PrefixedHexError, UnprefixedHexError};
|
use crate::error::{ContainsPrefixError, MissingPrefixError, ParseIntError, PrefixedHexError, UnprefixedHexError};
|
||||||
|
|
||||||
/// Implement traits and methods shared by `Target` and `Work`.
|
/// Implement traits and methods shared by `Target` and `Work`.
|
||||||
macro_rules! do_impl {
|
macro_rules! do_impl {
|
||||||
($ty:ident) => {
|
($ty:ident) => {
|
||||||
impl $ty {
|
impl $ty {
|
||||||
|
/// Creates `Self` from a prefixed hex string.
|
||||||
|
pub fn from_hex(s: &str) -> Result<Self, PrefixedHexError> {
|
||||||
|
Ok($ty(U256::from_hex(s)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates `Self` from an unprefixed hex string.
|
||||||
|
pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
|
||||||
|
Ok($ty(U256::from_unprefixed_hex(s)?))
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates `Self` from a big-endian byte array.
|
/// Creates `Self` from a big-endian byte array.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_be_bytes(bytes: [u8; 32]) -> $ty { $ty(U256::from_be_bytes(bytes)) }
|
pub fn from_be_bytes(bytes: [u8; 32]) -> $ty { $ty(U256::from_be_bytes(bytes)) }
|
||||||
|
@ -390,6 +400,43 @@ impl U256 {
|
||||||
|
|
||||||
const ONE: U256 = U256(0, 1);
|
const ONE: U256 = U256(0, 1);
|
||||||
|
|
||||||
|
/// Creates a `U256` from an prefixed hex string.
|
||||||
|
fn from_hex(s: &str) -> Result<Self, PrefixedHexError> {
|
||||||
|
let stripped = if let Some(stripped) = s.strip_prefix("0x") {
|
||||||
|
stripped
|
||||||
|
} else if let Some(stripped) = s.strip_prefix("0X") {
|
||||||
|
stripped
|
||||||
|
} else {
|
||||||
|
return Err(MissingPrefixError::new(s).into());
|
||||||
|
};
|
||||||
|
Ok(U256::from_hex_internal(stripped)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a `CompactTarget` from an unprefixed hex string.
|
||||||
|
fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
|
||||||
|
if s.starts_with("0x") || s.starts_with("0X") {
|
||||||
|
return Err(ContainsPrefixError::new(s).into());
|
||||||
|
}
|
||||||
|
Ok(U256::from_hex_internal(s)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_hex_internal(s: &str) -> Result<Self, ParseIntError> {
|
||||||
|
let (high, low) = if s.len() < 32 {
|
||||||
|
let low = parse::hex_u128(s)?;
|
||||||
|
(0, low)
|
||||||
|
} else {
|
||||||
|
let high_len = s.len() - 32;
|
||||||
|
let high_s = &s[..high_len];
|
||||||
|
let low_s = &s[high_len..];
|
||||||
|
|
||||||
|
let high = parse::hex_u128(high_s)?;
|
||||||
|
let low = parse::hex_u128(low_s)?;
|
||||||
|
(high, low)
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(U256(high, low))
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates [`U256`] from a big-endian array of `u8`s.
|
/// Creates [`U256`] from a big-endian array of `u8`s.
|
||||||
#[cfg_attr(all(test, mutate), mutate)]
|
#[cfg_attr(all(test, mutate), mutate)]
|
||||||
fn from_be_bytes(a: [u8; 32]) -> U256 {
|
fn from_be_bytes(a: [u8; 32]) -> U256 {
|
||||||
|
@ -1507,6 +1554,28 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn u256_to_from_hex_roundtrips() {
|
||||||
|
let val = U256(
|
||||||
|
0xDEAD_BEEA_A69B_455C_D41B_B662_A69B_4550,
|
||||||
|
0xA69B_455C_D41B_B662_A69B_4555_DEAD_BEEF,
|
||||||
|
);
|
||||||
|
let hex = format!("0x{:x}", val);
|
||||||
|
let got = U256::from_hex(&hex).expect("failed to parse hex");
|
||||||
|
assert_eq!(got, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn u256_to_from_unprefixed_hex_roundtrips() {
|
||||||
|
let val = U256(
|
||||||
|
0xDEAD_BEEA_A69B_455C_D41B_B662_A69B_4550,
|
||||||
|
0xA69B_455C_D41B_B662_A69B_4555_DEAD_BEEF,
|
||||||
|
);
|
||||||
|
let hex = format!("{:x}", val);
|
||||||
|
let got = U256::from_unprefixed_hex(&hex).expect("failed to parse hex");
|
||||||
|
assert_eq!(got, val);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[test]
|
#[test]
|
||||||
fn u256_serde() {
|
fn u256_serde() {
|
||||||
|
|
Loading…
Reference in New Issue