Flesh out hex unit parsing API
Add to `units::parse` the complete suit of hex unit parsing functions: - remove prefix - assert without prefix - parse with or without prefix - parse with prefix - parse without prefix - parse prefix unchecked Refactor `bitcoin` to use the exact function we need, removing code duplication. This is a breaking change to `units`, it does however keep the current re-exports from the public, now empty, `bitcoin::error` module.
This commit is contained in:
parent
1142d16192
commit
a5b93cb159
|
@ -11,12 +11,11 @@ use core::fmt;
|
|||
use io::{BufRead, Write};
|
||||
#[cfg(all(test, mutate))]
|
||||
use mutagen::mutate;
|
||||
use units::parse;
|
||||
use units::parse::{self, PrefixedHexError, UnprefixedHexError};
|
||||
|
||||
#[cfg(doc)]
|
||||
use crate::absolute;
|
||||
use crate::consensus::encode::{self, Decodable, Encodable};
|
||||
use crate::error::{ContainsPrefixError, MissingPrefixError, PrefixedHexError, UnprefixedHexError};
|
||||
|
||||
#[rustfmt::skip] // Keep public re-exports separate.
|
||||
#[doc(inline)]
|
||||
|
@ -92,26 +91,15 @@ impl LockTime {
|
|||
/// The number of bytes that the locktime contributes to the size of a transaction.
|
||||
pub const SIZE: usize = 4; // Serialized length of a u32.
|
||||
|
||||
/// Creates a `LockTime` from an prefixed hex string.
|
||||
/// Creates a `LockTime` from a prefixed hex string.
|
||||
pub 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());
|
||||
};
|
||||
|
||||
let lock_time = parse::hex_u32(stripped)?;
|
||||
let lock_time = parse::hex_u32_prefixed(s)?;
|
||||
Ok(Self::from_consensus(lock_time))
|
||||
}
|
||||
|
||||
/// Creates a `LockTime` from an unprefixed hex string.
|
||||
pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
|
||||
if s.starts_with("0x") || s.starts_with("0X") {
|
||||
return Err(ContainsPrefixError::new(s).into());
|
||||
}
|
||||
let lock_time = parse::hex_u32(s)?;
|
||||
let lock_time = parse::hex_u32_unprefixed(s)?;
|
||||
Ok(Self::from_consensus(lock_time))
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ use core::{cmp, fmt, str};
|
|||
use hashes::{sha256d, Hash};
|
||||
use internals::write_err;
|
||||
use io::{BufRead, Write};
|
||||
use units::parse;
|
||||
use units::parse::{self, PrefixedHexError, UnprefixedHexError};
|
||||
|
||||
use super::Weight;
|
||||
use crate::blockdata::locktime::absolute::{self, Height, Time};
|
||||
|
@ -24,7 +24,6 @@ use crate::blockdata::script::{Script, ScriptBuf};
|
|||
use crate::blockdata::witness::Witness;
|
||||
use crate::blockdata::FeeRate;
|
||||
use crate::consensus::{encode, Decodable, Encodable};
|
||||
use crate::error::{ContainsPrefixError, MissingPrefixError, PrefixedHexError, UnprefixedHexError};
|
||||
use crate::internal_macros::{impl_consensus_encoding, impl_hashencode};
|
||||
use crate::prelude::*;
|
||||
#[cfg(doc)]
|
||||
|
@ -404,26 +403,15 @@ impl Sequence {
|
|||
self.is_relative_lock_time() & (self.0 & Sequence::LOCK_TYPE_MASK > 0)
|
||||
}
|
||||
|
||||
/// Creates a `Sequence` from an prefixed hex string.
|
||||
/// Creates a `Sequence` from a prefixed hex string.
|
||||
pub 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());
|
||||
};
|
||||
|
||||
let sequence = parse::hex_u32(stripped)?;
|
||||
Ok(Self::from_consensus(sequence))
|
||||
let lock_time = parse::hex_u32_prefixed(s)?;
|
||||
Ok(Self::from_consensus(lock_time))
|
||||
}
|
||||
|
||||
/// Creates a `Sequence` from an unprefixed hex string.
|
||||
pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
|
||||
if s.starts_with("0x") || s.starts_with("0X") {
|
||||
return Err(ContainsPrefixError::new(s).into());
|
||||
}
|
||||
let lock_time = parse::hex_u32(s)?;
|
||||
let lock_time = parse::hex_u32_unprefixed(s)?;
|
||||
Ok(Self::from_consensus(lock_time))
|
||||
}
|
||||
|
||||
|
|
|
@ -2,131 +2,8 @@
|
|||
|
||||
//! Contains error types and other error handling tools.
|
||||
|
||||
use core::fmt;
|
||||
|
||||
use internals::write_err;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
#[rustfmt::skip] // Keep public re-exports separate.
|
||||
#[doc(inline)]
|
||||
pub use crate::parse::ParseIntError;
|
||||
|
||||
/// Error returned when parsing integer from an supposedly prefixed hex string for
|
||||
/// a type that can be created infallibly from an integer.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum PrefixedHexError {
|
||||
/// Hex string is missing prefix.
|
||||
MissingPrefix(MissingPrefixError),
|
||||
/// Error parsing integer from hex string.
|
||||
ParseInt(ParseIntError),
|
||||
}
|
||||
|
||||
impl fmt::Display for PrefixedHexError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use PrefixedHexError::*;
|
||||
|
||||
match *self {
|
||||
MissingPrefix(ref e) => write_err!(f, "hex string is missing prefix"; e),
|
||||
ParseInt(ref e) => write_err!(f, "prefixed hex string invalid int"; e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for PrefixedHexError {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
use PrefixedHexError::*;
|
||||
|
||||
match *self {
|
||||
MissingPrefix(ref e) => Some(e),
|
||||
ParseInt(ref e) => Some(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MissingPrefixError> for PrefixedHexError {
|
||||
fn from(e: MissingPrefixError) -> Self { Self::MissingPrefix(e) }
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for PrefixedHexError {
|
||||
fn from(e: ParseIntError) -> Self { Self::ParseInt(e) }
|
||||
}
|
||||
|
||||
/// Error returned when parsing integer from an supposedly un-prefixed hex string.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum UnprefixedHexError {
|
||||
/// Hex string contains prefix.
|
||||
ContainsPrefix(ContainsPrefixError),
|
||||
/// Error parsing integer from string.
|
||||
ParseInt(ParseIntError),
|
||||
}
|
||||
|
||||
impl fmt::Display for UnprefixedHexError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use UnprefixedHexError::*;
|
||||
|
||||
match *self {
|
||||
ContainsPrefix(ref e) => write_err!(f, "hex string is contains prefix"; e),
|
||||
ParseInt(ref e) => write_err!(f, "hex string parse int"; e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for UnprefixedHexError {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
use UnprefixedHexError::*;
|
||||
|
||||
match *self {
|
||||
ContainsPrefix(ref e) => Some(e),
|
||||
ParseInt(ref e) => Some(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ContainsPrefixError> for UnprefixedHexError {
|
||||
fn from(e: ContainsPrefixError) -> Self { Self::ContainsPrefix(e) }
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for UnprefixedHexError {
|
||||
fn from(e: ParseIntError) -> Self { Self::ParseInt(e) }
|
||||
}
|
||||
|
||||
/// Error when hex string is missing a prefix (e.g. 0x).
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct MissingPrefixError {
|
||||
hex: String,
|
||||
}
|
||||
|
||||
impl MissingPrefixError {
|
||||
pub(crate) fn new(s: &str) -> Self { Self { hex: s.into() } }
|
||||
}
|
||||
|
||||
impl fmt::Display for MissingPrefixError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "hex string is missing a prefix (e.g. 0x): {}", self.hex)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for MissingPrefixError {}
|
||||
|
||||
/// Error when hex string contains a prefix (e.g. 0x).
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct ContainsPrefixError {
|
||||
hex: String,
|
||||
}
|
||||
|
||||
impl ContainsPrefixError {
|
||||
pub(crate) fn new(s: &str) -> Self { Self { hex: s.into() } }
|
||||
}
|
||||
|
||||
impl fmt::Display for ContainsPrefixError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "hex string contains a prefix: {}", self.hex)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for ContainsPrefixError {}
|
||||
pub use units::parse::{
|
||||
ContainsPrefixError, MissingPrefixError, ParseIntError, PrefixedHexError, UnprefixedHexError,
|
||||
};
|
||||
|
|
|
@ -18,9 +18,7 @@ use crate::block::Header;
|
|||
use crate::blockdata::block::BlockHash;
|
||||
use crate::consensus::encode::{self, Decodable, Encodable};
|
||||
use crate::consensus::Params;
|
||||
use crate::error::{
|
||||
ContainsPrefixError, MissingPrefixError, ParseIntError, PrefixedHexError, UnprefixedHexError,
|
||||
};
|
||||
use crate::error::{ParseIntError, PrefixedHexError, UnprefixedHexError};
|
||||
|
||||
/// Implement traits and methods shared by `Target` and `Work`.
|
||||
macro_rules! do_impl {
|
||||
|
@ -350,27 +348,16 @@ do_impl!(Target);
|
|||
pub struct CompactTarget(u32);
|
||||
|
||||
impl CompactTarget {
|
||||
/// Creates a `CompactTarget` from an prefixed hex string.
|
||||
/// Creates a `CompactTarget` from a prefixed hex string.
|
||||
pub 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());
|
||||
};
|
||||
|
||||
let target = parse::hex_u32(stripped)?;
|
||||
let target = parse::hex_u32_prefixed(s)?;
|
||||
Ok(Self::from_consensus(target))
|
||||
}
|
||||
|
||||
/// Creates a `CompactTarget` from an unprefixed hex string.
|
||||
pub fn from_unprefixed_hex(s: &str) -> Result<Self, UnprefixedHexError> {
|
||||
if s.starts_with("0x") || s.starts_with("0X") {
|
||||
return Err(ContainsPrefixError::new(s).into());
|
||||
}
|
||||
let lock_time = parse::hex_u32(s)?;
|
||||
Ok(Self::from_consensus(lock_time))
|
||||
let target = parse::hex_u32_unprefixed(s)?;
|
||||
Ok(Self::from_consensus(target))
|
||||
}
|
||||
|
||||
/// Computes the [`CompactTarget`] from a difficulty adjustment.
|
||||
|
@ -499,36 +486,28 @@ impl U256 {
|
|||
|
||||
/// Creates a `U256` from a 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)?)
|
||||
let checked = parse::hex_remove_prefix(s)?;
|
||||
Ok(U256::from_hex_internal(checked)?)
|
||||
}
|
||||
|
||||
/// Creates a `U256` 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)?)
|
||||
let checked = parse::hex_check_unprefixed(s)?;
|
||||
Ok(U256::from_hex_internal(checked)?)
|
||||
}
|
||||
|
||||
// Caller to ensure `s` does not contain a prefix.
|
||||
fn from_hex_internal(s: &str) -> Result<Self, ParseIntError> {
|
||||
let (high, low) = if s.len() < 32 {
|
||||
let low = parse::hex_u128(s)?;
|
||||
let low = parse::hex_u128_unchecked(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)?;
|
||||
let high = parse::hex_u128_unchecked(high_s)?;
|
||||
let low = parse::hex_u128_unchecked(low_s)?;
|
||||
(high, low)
|
||||
};
|
||||
|
||||
|
|
|
@ -6,7 +6,9 @@ use core::fmt;
|
|||
|
||||
use internals::write_err;
|
||||
|
||||
use crate::parse::{self, ParseIntError};
|
||||
use crate::parse::ParseIntError;
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::parse;
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::prelude::*;
|
||||
|
||||
|
@ -233,7 +235,7 @@ where
|
|||
S: AsRef<str> + Into<String>,
|
||||
F: FnOnce(u32) -> Result<T, ConversionError>,
|
||||
{
|
||||
let n = i64::from_str_radix(parse::strip_hex_prefix(s.as_ref()), 16)
|
||||
let n = i64::from_str_radix(parse::hex_remove_optional_prefix(s.as_ref()), 16)
|
||||
.map_err(ParseError::invalid_int(s))?;
|
||||
let n = u32::try_from(n).map_err(|_| ParseError::Conversion(n))?;
|
||||
f(n).map_err(ParseError::from).map_err(Into::into)
|
||||
|
|
|
@ -88,43 +88,6 @@ pub fn int<T: Integer, S: AsRef<str> + Into<String>>(s: S) -> Result<T, ParseInt
|
|||
})
|
||||
}
|
||||
|
||||
/// Parses a `u32` from a hex string.
|
||||
///
|
||||
/// Input string may or may not contain a `0x` prefix.
|
||||
pub fn hex_u32<S: AsRef<str> + Into<String>>(s: S) -> Result<u32, ParseIntError> {
|
||||
let stripped = strip_hex_prefix(s.as_ref());
|
||||
u32::from_str_radix(stripped, 16).map_err(|error| ParseIntError {
|
||||
input: s.into(),
|
||||
bits: 32,
|
||||
is_signed: false,
|
||||
source: error,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses a `u128` from a hex string.
|
||||
///
|
||||
/// Input string may or may not contain a `0x` prefix.
|
||||
pub fn hex_u128<S: AsRef<str> + Into<String>>(s: S) -> Result<u128, ParseIntError> {
|
||||
let stripped = strip_hex_prefix(s.as_ref());
|
||||
u128::from_str_radix(stripped, 16).map_err(|error| ParseIntError {
|
||||
input: s.into(),
|
||||
bits: 128,
|
||||
is_signed: false,
|
||||
source: error,
|
||||
})
|
||||
}
|
||||
|
||||
/// Strips the hex prefix off `s` if one is present.
|
||||
pub(crate) fn strip_hex_prefix(s: &str) -> &str {
|
||||
if let Some(stripped) = s.strip_prefix("0x") {
|
||||
stripped
|
||||
} else if let Some(stripped) = s.strip_prefix("0X") {
|
||||
stripped
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
/// Implements `TryFrom<$from> for $to` using `parse::int`, mapping the output using infallible
|
||||
/// conversion function `fn`.
|
||||
#[macro_export]
|
||||
|
@ -197,6 +160,263 @@ macro_rules! impl_parse_str {
|
|||
}
|
||||
}
|
||||
|
||||
/// Removes the prefix `0x` (or `0X`) from hex string.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If input string does not contain a prefix.
|
||||
pub fn hex_remove_prefix(s: &str) -> Result<&str, PrefixedHexError> {
|
||||
if let Some(checked) = s.strip_prefix("0x") {
|
||||
Ok(checked)
|
||||
} else if let Some(checked) = s.strip_prefix("0X") {
|
||||
Ok(checked)
|
||||
} else {
|
||||
Err(MissingPrefixError::new(s.into()).into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks hex string does not have a prefix `0x` (or `0X`).
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If input string contains a prefix.
|
||||
pub fn hex_check_unprefixed(s: &str) -> Result<&str, UnprefixedHexError> {
|
||||
if s.starts_with("0x") || s.starts_with("0X") {
|
||||
return Err(ContainsPrefixError::new(s.into()).into());
|
||||
}
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
/// Parses a `u32` from a hex string.
|
||||
///
|
||||
/// Input string may or may not contain a `0x` (or `0X`) prefix.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If the input string is not a valid hex encoding of a `u32`.
|
||||
pub fn hex_u32(s: &str) -> Result<u32, ParseIntError> {
|
||||
let unchecked = hex_remove_optional_prefix(s);
|
||||
Ok(hex_u32_unchecked(unchecked)?)
|
||||
}
|
||||
|
||||
/// Parses a `u32` from a prefixed hex string.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - If input string does not contain a `0x` (or `0X`) prefix.
|
||||
/// - If input string is not a valid hex encoding of a `u32`.
|
||||
pub fn hex_u32_prefixed(s: &str) -> Result<u32, PrefixedHexError> {
|
||||
let checked = hex_remove_prefix(s)?;
|
||||
Ok(hex_u32_unchecked(checked)?)
|
||||
}
|
||||
|
||||
/// Parses a `u32` from an unprefixed hex string.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - If input string contains a `0x` (or `0X`) prefix.
|
||||
/// - If input string is not a valid hex encoding of a `u32`.
|
||||
pub fn hex_u32_unprefixed(s: &str) -> Result<u32, UnprefixedHexError> {
|
||||
let checked = hex_check_unprefixed(s)?;
|
||||
Ok(hex_u32_unchecked(checked)?)
|
||||
}
|
||||
|
||||
/// Parses a `u32` from a hex string.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - If input string is not a valid hex encoding of a `u32`.
|
||||
/// - With `InvalidDigit` due to the `x` if there is a prefix.
|
||||
pub fn hex_u32_unchecked(s: &str) -> Result<u32, ParseIntError> {
|
||||
u32::from_str_radix(s, 16).map_err(|error| ParseIntError {
|
||||
input: s.into(),
|
||||
bits: 32,
|
||||
is_signed: false,
|
||||
source: error,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses a `u128` from a hex string.
|
||||
///
|
||||
/// Input string may or may not contain a `0x` (or `0X`) prefix.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If the input string is not a valid hex encoding of a `u128`.
|
||||
pub fn hex_u128(s: &str) -> Result<u128, ParseIntError> {
|
||||
let unchecked = hex_remove_optional_prefix(s);
|
||||
Ok(hex_u128_unchecked(unchecked)?)
|
||||
}
|
||||
|
||||
/// Parses a `u128` from a hex string.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - If input string does not contain a `0x` (or `0X`) prefix.
|
||||
/// - If input string is not a valid hex encoding of a `u128`.
|
||||
pub fn hex_u128_prefixed(s: &str) -> Result<u128, PrefixedHexError> {
|
||||
let checked = hex_remove_prefix(s)?;
|
||||
Ok(hex_u128_unchecked(checked)?)
|
||||
}
|
||||
|
||||
/// Parses a `u128` from a hex string.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - If input string contains a `0x` (or `0X`) prefix.
|
||||
/// - If input string is not a valid hex encoding of a `u128`.
|
||||
pub fn hex_u128_unprefixed(s: &str) -> Result<u128, UnprefixedHexError> {
|
||||
let checked = hex_check_unprefixed(s)?;
|
||||
Ok(hex_u128_unchecked(checked)?)
|
||||
}
|
||||
|
||||
/// Parses a `u128` from a hex string.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - If input string is not a valid hex encoding of a `u128`.
|
||||
/// - With `InvalidDigit` due to the `x` if there is a prefix.
|
||||
pub fn hex_u128_unchecked(s: &str) -> Result<u128, ParseIntError> {
|
||||
u128::from_str_radix(s, 16).map_err(|error| ParseIntError {
|
||||
input: s.into(),
|
||||
bits: 128,
|
||||
is_signed: false,
|
||||
source: error,
|
||||
})
|
||||
}
|
||||
|
||||
/// Strips the hex prefix off `s` if one is present.
|
||||
pub(crate) fn hex_remove_optional_prefix(s: &str) -> &str {
|
||||
if let Some(stripped) = s.strip_prefix("0x") {
|
||||
stripped
|
||||
} else if let Some(stripped) = s.strip_prefix("0X") {
|
||||
stripped
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
/// Error returned when parsing integer from an supposedly prefixed hex string for
|
||||
/// a type that can be created infallibly from an integer.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum PrefixedHexError {
|
||||
/// Hex string is missing prefix.
|
||||
MissingPrefix(MissingPrefixError),
|
||||
/// Error parsing integer from hex string.
|
||||
ParseInt(ParseIntError),
|
||||
}
|
||||
|
||||
impl fmt::Display for PrefixedHexError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use PrefixedHexError::*;
|
||||
|
||||
match *self {
|
||||
MissingPrefix(ref e) => write_err!(f, "hex string is missing prefix"; e),
|
||||
ParseInt(ref e) => write_err!(f, "prefixed hex string invalid int"; e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for PrefixedHexError {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
use PrefixedHexError::*;
|
||||
|
||||
match *self {
|
||||
MissingPrefix(ref e) => Some(e),
|
||||
ParseInt(ref e) => Some(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MissingPrefixError> for PrefixedHexError {
|
||||
fn from(e: MissingPrefixError) -> Self { Self::MissingPrefix(e) }
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for PrefixedHexError {
|
||||
fn from(e: ParseIntError) -> Self { Self::ParseInt(e) }
|
||||
}
|
||||
|
||||
/// Error returned when parsing integer from an supposedly un-prefixed hex string.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum UnprefixedHexError {
|
||||
/// Hex string contains prefix.
|
||||
ContainsPrefix(ContainsPrefixError),
|
||||
/// Error parsing integer from string.
|
||||
ParseInt(ParseIntError),
|
||||
}
|
||||
|
||||
impl fmt::Display for UnprefixedHexError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use UnprefixedHexError::*;
|
||||
|
||||
match *self {
|
||||
ContainsPrefix(ref e) => write_err!(f, "hex string is contains prefix"; e),
|
||||
ParseInt(ref e) => write_err!(f, "hex string parse int"; e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for UnprefixedHexError {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
use UnprefixedHexError::*;
|
||||
|
||||
match *self {
|
||||
ContainsPrefix(ref e) => Some(e),
|
||||
ParseInt(ref e) => Some(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ContainsPrefixError> for UnprefixedHexError {
|
||||
fn from(e: ContainsPrefixError) -> Self { Self::ContainsPrefix(e) }
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for UnprefixedHexError {
|
||||
fn from(e: ParseIntError) -> Self { Self::ParseInt(e) }
|
||||
}
|
||||
|
||||
/// Error when hex string is missing a prefix (e.g. 0x).
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct MissingPrefixError {
|
||||
hex: String,
|
||||
}
|
||||
|
||||
impl MissingPrefixError {
|
||||
/// Creates an error from the string with the missing prefix.
|
||||
pub(crate) fn new(hex: String) -> Self { Self { hex } }
|
||||
}
|
||||
|
||||
impl fmt::Display for MissingPrefixError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "hex string is missing a prefix (e.g. 0x): {}", self.hex)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for MissingPrefixError {}
|
||||
|
||||
/// Error when hex string contains a prefix (e.g. 0x).
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct ContainsPrefixError {
|
||||
hex: String,
|
||||
}
|
||||
|
||||
impl ContainsPrefixError {
|
||||
/// Creates an error from the string that contains the prefix.
|
||||
pub(crate) fn new(hex: String) -> Self { Self { hex } }
|
||||
}
|
||||
|
||||
impl fmt::Display for ContainsPrefixError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "hex string contains a prefix: {}", self.hex)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for ContainsPrefixError {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -228,4 +448,9 @@ mod tests {
|
|||
let got = hex_u128("deadbeef").expect("failed to parse non-prefixed hex");
|
||||
assert_eq!(got, want);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_u32_from_hex_unchecked_errors_on_prefix() {
|
||||
assert!(hex_u32_unchecked("0xab").is_err());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue