diff --git a/bitcoin/src/blockdata/fee_rate.rs b/bitcoin/src/blockdata/fee_rate.rs index 223b88e2..d413bb66 100644 --- a/bitcoin/src/blockdata/fee_rate.rs +++ b/bitcoin/src/blockdata/fee_rate.rs @@ -2,6 +2,8 @@ use core::fmt; use core::ops::{Mul, Div}; + +use crate::prelude::*; use crate::Amount; use super::Weight; @@ -133,4 +135,4 @@ impl Div for Amount { } } -crate::parse::impl_parse_str_through_int!(FeeRate); +crate::parse::impl_parse_str_from_int_infallible!(FeeRate, u64, from_sat_per_kwu); diff --git a/bitcoin/src/blockdata/locktime/absolute.rs b/bitcoin/src/blockdata/locktime/absolute.rs index f2a69006..92b7c911 100644 --- a/bitcoin/src/blockdata/locktime/absolute.rs +++ b/bitcoin/src/blockdata/locktime/absolute.rs @@ -9,8 +9,6 @@ use core::{mem, fmt}; use core::cmp::{PartialOrd, Ordering}; -use core::convert::TryFrom; -use core::str::FromStr; use bitcoin_internals::write_err; @@ -20,8 +18,8 @@ use mutagen::mutate; use crate::consensus::encode::{self, Decodable, Encodable}; use crate::error::ParseIntError; use crate::io::{self, Read, Write}; +use crate::parse::{impl_parse_str_from_int_infallible, impl_parse_str_from_int_fallible}; use crate::prelude::*; -use crate::parse::{self, impl_parse_str_through_int}; use crate::string::FromHexStr; #[cfg(doc)] @@ -276,7 +274,7 @@ impl LockTime { } } -impl_parse_str_through_int!(LockTime, from_consensus); +impl_parse_str_from_int_infallible!(LockTime, u32, from_consensus); impl From for LockTime { #[inline] @@ -451,6 +449,8 @@ impl Height { } } +impl_parse_str_from_int_fallible!(Height, u32, from_consensus, Error); + impl fmt::Display for Height { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) @@ -467,37 +467,6 @@ impl FromHexStr for Height { } } - -impl FromStr for Height { - type Err = Error; - - #[inline] - fn from_str(s: &str) -> Result { - let n = parse::int(s)?; - Height::from_consensus(n) - } -} - -impl TryFrom<&str> for Height { - type Error = Error; - - #[inline] - fn try_from(s: &str) -> Result { - let n = parse::int(s)?; - Height::from_consensus(n) - } -} - -impl TryFrom for Height { - type Error = Error; - - #[inline] - fn try_from(s: String) -> Result { - let n = parse::int(s)?; - Height::from_consensus(n) - } -} - /// A UNIX timestamp, seconds since epoch, guaranteed to always contain a valid time value. /// /// Note that there is no manipulation of the inner value during construction or when using @@ -564,6 +533,8 @@ impl Time { } } +impl_parse_str_from_int_fallible!(Time, u32, from_consensus, Error); + impl fmt::Display for Time { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) @@ -580,36 +551,6 @@ impl FromHexStr for Time { } } -impl FromStr for Time { - type Err = Error; - - #[inline] - fn from_str(s: &str) -> Result { - let n = parse::int(s)?; - Time::from_consensus(n) - } -} - -impl TryFrom<&str> for Time { - type Error = Error; - - #[inline] - fn try_from(s: &str) -> Result { - let n = parse::int(s)?; - Time::from_consensus(n) - } -} - -impl TryFrom for Time { - type Error = Error; - - #[inline] - fn try_from(s: String) -> Result { - let n = parse::int(s)?; - Time::from_consensus(n) - } -} - /// Returns true if `n` is a block height i.e., less than 500,000,000. fn is_block_height(n: u32) -> bool { n < LOCK_TIME_THRESHOLD diff --git a/bitcoin/src/blockdata/locktime/relative.rs b/bitcoin/src/blockdata/locktime/relative.rs index c61519c4..0188a9b4 100644 --- a/bitcoin/src/blockdata/locktime/relative.rs +++ b/bitcoin/src/blockdata/locktime/relative.rs @@ -13,6 +13,9 @@ use core::convert::TryFrom; #[cfg(all(test, mutate))] use mutagen::mutate; +use crate::parse::impl_parse_str_from_int_infallible; +use crate::prelude::*; + #[cfg(doc)] use crate::relative; @@ -236,6 +239,8 @@ impl From for Height { } } +impl_parse_str_from_int_infallible!(Height, u16, from); + impl fmt::Display for Height { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) @@ -300,6 +305,8 @@ impl Time { } } +impl_parse_str_from_int_infallible!(Time, u16, from_512_second_intervals); + impl fmt::Display for Time { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index cc385066..8494a93f 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -33,7 +33,7 @@ use crate::consensus::{encode, Decodable, Encodable}; use crate::hash_types::{Sighash, Txid, Wtxid}; use crate::VarInt; use crate::internal_macros::impl_consensus_encoding; -use crate::parse::impl_parse_str_through_int; +use crate::parse::impl_parse_str_from_int_infallible; use super::Weight; #[cfg(doc)] @@ -499,7 +499,7 @@ impl fmt::UpperHex for Sequence { } } -impl_parse_str_through_int!(Sequence); +impl_parse_str_from_int_infallible!(Sequence, u32, from_consensus); /// Bitcoin transaction output. /// diff --git a/bitcoin/src/blockdata/weight.rs b/bitcoin/src/blockdata/weight.rs index ac529090..7bccaf2c 100644 --- a/bitcoin/src/blockdata/weight.rs +++ b/bitcoin/src/blockdata/weight.rs @@ -3,6 +3,8 @@ use core::fmt; use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Div, DivAssign}; +use crate::prelude::*; + /// Represents block weight - the weight of a transaction or block. /// /// This is an integer newtype representing weigth in `wu`. It provides protection against mixing @@ -195,4 +197,4 @@ impl<'a> core::iter::Sum<&'a Weight> for Weight { } } -crate::parse::impl_parse_str_through_int!(Weight); +crate::parse::impl_parse_str_from_int_infallible!(Weight, u64, from_wu); diff --git a/bitcoin/src/parse.rs b/bitcoin/src/parse.rs index 07ddae82..5c997562 100644 --- a/bitcoin/src/parse.rs +++ b/bitcoin/src/parse.rs @@ -95,37 +95,78 @@ pub(crate) fn hex_u32 + Into>(s: S) -> Result for $to` using `parse::int`, mapping the output using `fn` -macro_rules! impl_tryfrom_str_through_int_single { - ($($from:ty, $to:ident $(, $fn:ident)?);*) => { +/// Implements `TryFrom<$from> for $to` using `parse::int`, mapping the output using infallible +/// conversion function `fn`. +macro_rules! impl_tryfrom_str_from_int_infallible { + ($($from:ty, $to:ident, $inner:ident, $fn:ident);*) => { $( impl core::convert::TryFrom<$from> for $to { type Error = $crate::error::ParseIntError; fn try_from(s: $from) -> Result { - $crate::parse::int(s).map($to $(:: $fn)?) + $crate::parse::int::<$inner, $from>(s).map($to::$fn) } } )* } } -pub(crate) use impl_tryfrom_str_through_int_single; +pub(crate) use impl_tryfrom_str_from_int_infallible; -/// Implements `FromStr` and `TryFrom<{&str, String, Box}> for $to` using `parse::int`, mapping the output using `fn` +/// Implements `FromStr` and `TryFrom<{&str, String, Box}> for $to` using `parse::int`, mapping +/// the output using infallible conversion function `fn`. /// /// The `Error` type is `ParseIntError` -macro_rules! impl_parse_str_through_int { - ($to:ident $(, $fn:ident)?) => { - $crate::parse::impl_tryfrom_str_through_int_single!(&str, $to $(, $fn)?; alloc::string::String, $to $(, $fn)?; alloc::boxed::Box, $to $(, $fn)?); +macro_rules! impl_parse_str_from_int_infallible { + ($to:ident, $inner:ident, $fn:ident) => { + $crate::parse::impl_tryfrom_str_from_int_infallible!(&str, $to, $inner, $fn; String, $to, $inner, $fn; Box, $to, $inner, $fn); impl core::str::FromStr for $to { type Err = $crate::error::ParseIntError; fn from_str(s: &str) -> Result { - $crate::parse::int(s).map($to $(:: $fn)?) + $crate::parse::int::<$inner, &str>(s).map($to::$fn) } } } } -pub(crate) use impl_parse_str_through_int; +pub(crate) use impl_parse_str_from_int_infallible; + +/// Implements `TryFrom<$from> for $to` using `parse::int`, mapping the output using fallible +/// conversion function `fn`. +macro_rules! impl_tryfrom_str_from_int_fallible { + ($($from:ty, $to:ident, $inner:ident, $fn:ident, $err:ident);*) => { + $( + impl core::convert::TryFrom<$from> for $to { + type Error = $err; + + fn try_from(s: $from) -> Result { + let u = $crate::parse::int::<$inner, $from>(s)?; + $to::$fn(u) + } + } + )* + } +} +pub(crate) use impl_tryfrom_str_from_int_fallible; + +/// Implements `FromStr` and `TryFrom<{&str, String, Box}> for $to` using `parse::int`, mapping +/// the output using fallible conversion function `fn`. +/// +/// The `Error` type is `ParseIntError` +macro_rules! impl_parse_str_from_int_fallible { + ($to:ident, $inner:ident, $fn:ident, $err:ident) => { + $crate::parse::impl_tryfrom_str_from_int_fallible!(&str, $to, $inner, $fn, $err; String, $to, $inner, $fn, $err; Box, $to, $inner, $fn, $err); + + impl core::str::FromStr for $to { + type Err = $err; + + fn from_str(s: &str) -> Result { + let u = $crate::parse::int::<$inner, &str>(s)?; + $to::$fn(u) + } + } + + } +} +pub(crate) use impl_parse_str_from_int_fallible;