Implement string parsing for `Sequence`

`Sequence` didn't have `FromStr` nor `TryFrom<{stringly type}>`
implemented by accident. This moves a macro for implementing them from
`locktime` module to the `parse` module, renames it for clarity and uses
it to implement parsing for `Sequence`.
This commit is contained in:
Martin Habovstiak 2022-07-27 19:18:00 +02:00
parent c39bc3909d
commit 071a1c02b7
3 changed files with 41 additions and 33 deletions

View File

@ -28,6 +28,7 @@ use crate::consensus::encode::{self, Decodable, Encodable};
use crate::io::{self, Read, Write}; use crate::io::{self, Read, Write};
use crate::prelude::*; use crate::prelude::*;
use crate::internal_macros::write_err; use crate::internal_macros::write_err;
use crate::impl_parse_str_through_int;
/// The Threshold for deciding whether a lock time value is a height or a time (see [Bitcoin Core]). /// The Threshold for deciding whether a lock time value is a height or a time (see [Bitcoin Core]).
/// ///
@ -135,38 +136,7 @@ impl From<PackedLockTime> for u32 {
} }
} }
/// Implements `TryFrom<$from> for $to` using `parse::int`, mapping the output using `fn` impl_parse_str_through_int!(PackedLockTime);
macro_rules! impl_tryfrom_str_single {
($($from:ty, $to:ident $(, $fn:ident)?);*) => {
$(
impl TryFrom<$from> for $to {
type Error = ParseIntError;
fn try_from(s: $from) -> Result<Self, Self::Error> {
parse::int(s).map($to $(:: $fn)?)
}
}
)*
}
}
/// Implements `TryFrom<{&str, String, Box<str>}> for $to` using `parse::int`, mapping the output using `fn`
macro_rules! impl_tryfrom_str {
($to:ident $(, $fn:ident)?) => {
impl_tryfrom_str_single!(&str, $to $(, $fn)?; String, $to $(, $fn)?; Box<str>, $to $(, $fn)?);
impl FromStr for $to {
type Err = ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
parse::int(s).map($to $(:: $fn)?)
}
}
}
}
impl_tryfrom_str!(PackedLockTime);
impl fmt::LowerHex for PackedLockTime { impl fmt::LowerHex for PackedLockTime {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@ -376,7 +346,7 @@ impl LockTime {
} }
} }
impl_tryfrom_str!(LockTime, from_consensus); impl_parse_str_through_int!(LockTime, from_consensus);
impl From<Height> for LockTime { impl From<Height> for LockTime {
fn from(h: Height) -> Self { fn from(h: Height) -> Self {

View File

@ -32,6 +32,7 @@ use crate::hash_types::{Sighash, Txid, Wtxid};
use crate::VarInt; use crate::VarInt;
use crate::util::sighash::UINT256_ONE; use crate::util::sighash::UINT256_ONE;
use crate::internal_macros::{impl_consensus_encoding, serde_string_impl, serde_struct_human_string_impl, write_err}; use crate::internal_macros::{impl_consensus_encoding, serde_string_impl, serde_struct_human_string_impl, write_err};
use crate::impl_parse_str_through_int;
#[cfg(doc)] #[cfg(doc)]
use crate::util::sighash::SchnorrSighashType; use crate::util::sighash::SchnorrSighashType;
@ -422,6 +423,8 @@ impl fmt::Display for RelativeLockTimeError {
} }
} }
impl_parse_str_through_int!(Sequence);
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for RelativeLockTimeError { impl std::error::Error for RelativeLockTimeError {

View File

@ -86,3 +86,38 @@ pub(crate) fn int<T: Integer, S: AsRef<str> + Into<String>>(s: S) -> Result<T, P
} }
impl_std_error!(ParseIntError, source); impl_std_error!(ParseIntError, source);
/// Implements `TryFrom<$from> for $to` using `parse::int`, mapping the output using `fn`
#[macro_export]
macro_rules! impl_tryfrom_str_through_int_single {
($($from:ty, $to: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)?)
}
}
)*
}
}
/// Implements `FromStr` and `TryFrom<{&str, String, Box<str>}> for $to` using `parse::int`, mapping the output using `fn`
///
/// The `Error` type is `ParseIntError`
#[macro_export]
macro_rules! impl_parse_str_through_int {
($to:ident $(, $fn:ident)?) => {
$crate::impl_tryfrom_str_through_int_single!(&str, $to $(, $fn)?; String, $to $(, $fn)?; Box<str>, $to $(, $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)?)
}
}
}
}