Improve string parsing
Currently we implement string parsing for height/time from the `absolute` module but not the `relative` module. Improve the macros used to implement string parsing and use the new versions to implement string parsing for the height and time types in `relative`.
This commit is contained in:
parent
b6387db47f
commit
090dad770f
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::ops::{Mul, Div};
|
use core::ops::{Mul, Div};
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
use crate::Amount;
|
use crate::Amount;
|
||||||
use super::Weight;
|
use super::Weight;
|
||||||
|
|
||||||
|
@ -133,4 +135,4 @@ impl Div<Weight> for Amount {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::parse::impl_parse_str_through_int!(FeeRate);
|
crate::parse::impl_parse_str_from_int_infallible!(FeeRate, u64, from_sat_per_kwu);
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
|
|
||||||
use core::{mem, fmt};
|
use core::{mem, fmt};
|
||||||
use core::cmp::{PartialOrd, Ordering};
|
use core::cmp::{PartialOrd, Ordering};
|
||||||
use core::convert::TryFrom;
|
|
||||||
use core::str::FromStr;
|
|
||||||
|
|
||||||
use bitcoin_internals::write_err;
|
use bitcoin_internals::write_err;
|
||||||
|
|
||||||
|
@ -20,8 +18,8 @@ use mutagen::mutate;
|
||||||
use crate::consensus::encode::{self, Decodable, Encodable};
|
use crate::consensus::encode::{self, Decodable, Encodable};
|
||||||
use crate::error::ParseIntError;
|
use crate::error::ParseIntError;
|
||||||
use crate::io::{self, Read, Write};
|
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::prelude::*;
|
||||||
use crate::parse::{self, impl_parse_str_through_int};
|
|
||||||
use crate::string::FromHexStr;
|
use crate::string::FromHexStr;
|
||||||
|
|
||||||
#[cfg(doc)]
|
#[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<Height> for LockTime {
|
impl From<Height> for LockTime {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -451,6 +449,8 @@ impl Height {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_parse_str_from_int_fallible!(Height, u32, from_consensus, Error);
|
||||||
|
|
||||||
impl fmt::Display for Height {
|
impl fmt::Display for Height {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Display::fmt(&self.0, f)
|
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<Self, Self::Err> {
|
|
||||||
let n = parse::int(s)?;
|
|
||||||
Height::from_consensus(n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<&str> for Height {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
|
||||||
let n = parse::int(s)?;
|
|
||||||
Height::from_consensus(n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<String> for Height {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
|
||||||
let n = parse::int(s)?;
|
|
||||||
Height::from_consensus(n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A UNIX timestamp, seconds since epoch, guaranteed to always contain a valid time value.
|
/// 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
|
/// 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 {
|
impl fmt::Display for Time {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Display::fmt(&self.0, f)
|
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<Self, Self::Err> {
|
|
||||||
let n = parse::int(s)?;
|
|
||||||
Time::from_consensus(n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<&str> for Time {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
|
||||||
let n = parse::int(s)?;
|
|
||||||
Time::from_consensus(n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<String> for Time {
|
|
||||||
type Error = Error;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
|
||||||
let n = parse::int(s)?;
|
|
||||||
Time::from_consensus(n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if `n` is a block height i.e., less than 500,000,000.
|
/// Returns true if `n` is a block height i.e., less than 500,000,000.
|
||||||
fn is_block_height(n: u32) -> bool {
|
fn is_block_height(n: u32) -> bool {
|
||||||
n < LOCK_TIME_THRESHOLD
|
n < LOCK_TIME_THRESHOLD
|
||||||
|
|
|
@ -13,6 +13,9 @@ use core::convert::TryFrom;
|
||||||
#[cfg(all(test, mutate))]
|
#[cfg(all(test, mutate))]
|
||||||
use mutagen::mutate;
|
use mutagen::mutate;
|
||||||
|
|
||||||
|
use crate::parse::impl_parse_str_from_int_infallible;
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
#[cfg(doc)]
|
#[cfg(doc)]
|
||||||
use crate::relative;
|
use crate::relative;
|
||||||
|
|
||||||
|
@ -236,6 +239,8 @@ impl From<u16> for Height {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_parse_str_from_int_infallible!(Height, u16, from);
|
||||||
|
|
||||||
impl fmt::Display for Height {
|
impl fmt::Display for Height {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Display::fmt(&self.0, f)
|
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 {
|
impl fmt::Display for Time {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Display::fmt(&self.0, f)
|
fmt::Display::fmt(&self.0, f)
|
||||||
|
|
|
@ -33,7 +33,7 @@ use crate::consensus::{encode, Decodable, Encodable};
|
||||||
use crate::hash_types::{Sighash, Txid, Wtxid};
|
use crate::hash_types::{Sighash, Txid, Wtxid};
|
||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
use crate::internal_macros::impl_consensus_encoding;
|
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;
|
use super::Weight;
|
||||||
|
|
||||||
#[cfg(doc)]
|
#[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.
|
/// Bitcoin transaction output.
|
||||||
///
|
///
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Div, DivAssign};
|
use core::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Div, DivAssign};
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
/// Represents block weight - the weight of a transaction or block.
|
/// Represents block weight - the weight of a transaction or block.
|
||||||
///
|
///
|
||||||
/// This is an integer newtype representing weigth in `wu`. It provides protection against mixing
|
/// 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);
|
||||||
|
|
|
@ -95,37 +95,78 @@ pub(crate) fn hex_u32<S: AsRef<str> + Into<String>>(s: S) -> Result<u32, ParseIn
|
||||||
|
|
||||||
impl_std_error!(ParseIntError, source);
|
impl_std_error!(ParseIntError, source);
|
||||||
|
|
||||||
/// Implements `TryFrom<$from> for $to` using `parse::int`, mapping the output using `fn`
|
/// Implements `TryFrom<$from> for $to` using `parse::int`, mapping the output using infallible
|
||||||
macro_rules! impl_tryfrom_str_through_int_single {
|
/// conversion function `fn`.
|
||||||
($($from:ty, $to:ident $(, $fn:ident)?);*) => {
|
macro_rules! impl_tryfrom_str_from_int_infallible {
|
||||||
|
($($from:ty, $to:ident, $inner:ident, $fn:ident);*) => {
|
||||||
$(
|
$(
|
||||||
impl core::convert::TryFrom<$from> for $to {
|
impl core::convert::TryFrom<$from> for $to {
|
||||||
type Error = $crate::error::ParseIntError;
|
type Error = $crate::error::ParseIntError;
|
||||||
|
|
||||||
fn try_from(s: $from) -> Result<Self, Self::Error> {
|
fn try_from(s: $from) -> Result<Self, Self::Error> {
|
||||||
$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<str>}> for $to` using `parse::int`, mapping the output using `fn`
|
/// Implements `FromStr` and `TryFrom<{&str, String, Box<str>}> for $to` using `parse::int`, mapping
|
||||||
|
/// the output using infallible conversion function `fn`.
|
||||||
///
|
///
|
||||||
/// The `Error` type is `ParseIntError`
|
/// The `Error` type is `ParseIntError`
|
||||||
macro_rules! impl_parse_str_through_int {
|
macro_rules! impl_parse_str_from_int_infallible {
|
||||||
($to:ident $(, $fn:ident)?) => {
|
($to:ident, $inner:ident, $fn:ident) => {
|
||||||
$crate::parse::impl_tryfrom_str_through_int_single!(&str, $to $(, $fn)?; alloc::string::String, $to $(, $fn)?; alloc::boxed::Box<str>, $to $(, $fn)?);
|
$crate::parse::impl_tryfrom_str_from_int_infallible!(&str, $to, $inner, $fn; String, $to, $inner, $fn; Box<str>, $to, $inner, $fn);
|
||||||
|
|
||||||
impl core::str::FromStr for $to {
|
impl core::str::FromStr for $to {
|
||||||
type Err = $crate::error::ParseIntError;
|
type Err = $crate::error::ParseIntError;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
$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<Self, Self::Error> {
|
||||||
|
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<str>}> 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<str>, $to, $inner, $fn, $err);
|
||||||
|
|
||||||
|
impl core::str::FromStr for $to {
|
||||||
|
type Err = $err;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let u = $crate::parse::int::<$inner, &str>(s)?;
|
||||||
|
$to::$fn(u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) use impl_parse_str_from_int_fallible;
|
||||||
|
|
Loading…
Reference in New Issue