Merge rust-bitcoin/rust-bitcoin#1623: Improve string parsing
090dad770f
Improve string parsing (Tobin C. Harding) Pull request description: 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`. Done while reviewing data structures in relation to `serde`. ACKs for top commit: apoelstra: ACK090dad770f
Kixunil: ACK090dad770f
Tree-SHA512: bfa88efbaf5dc35755eb46df373a08e223f112860e8a65f58db9fdd77e2c01dc9377da735b33ef58940004fe5fe11690ac09be19591fded2c9fd04cd7d2bdf73
This commit is contained in:
commit
5a867821aa
|
@ -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<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::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<Height> 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<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.
|
||||
///
|
||||
/// 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<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.
|
||||
fn is_block_height(n: u32) -> bool {
|
||||
n < LOCK_TIME_THRESHOLD
|
||||
|
|
|
@ -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<u16> 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)
|
||||
|
|
|
@ -34,7 +34,7 @@ use crate::crypto::sighash::LegacySighash;
|
|||
use crate::hash_types::{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)]
|
||||
|
@ -500,7 +500,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.
|
||||
///
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -95,37 +95,78 @@ pub(crate) fn hex_u32<S: AsRef<str> + Into<String>>(s: S) -> Result<u32, ParseIn
|
|||
|
||||
impl_std_error!(ParseIntError, source);
|
||||
|
||||
/// Implements `TryFrom<$from> 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<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`
|
||||
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<str>, $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<str>, $to, $inner, $fn);
|
||||
|
||||
impl core::str::FromStr for $to {
|
||||
type Err = $crate::error::ParseIntError;
|
||||
|
||||
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