Skip to content

Commit

Permalink
Implement string parsing for Sequence
Browse files Browse the repository at this point in the history
`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`.
  • Loading branch information
Kixunil committed Jul 27, 2022
1 parent c39bc39 commit 071a1c0
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 33 deletions.
36 changes: 3 additions & 33 deletions src/blockdata/locktime.rs
Expand Up @@ -28,6 +28,7 @@ use crate::consensus::encode::{self, Decodable, Encodable};
use crate::io::{self, Read, Write};
use crate::prelude::*;
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]).
///
Expand Down Expand Up @@ -135,38 +136,7 @@ impl From<PackedLockTime> for u32 {
}
}

/// Implements `TryFrom<$from> for $to` using `parse::int`, mapping the output using `fn`
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_parse_str_through_int!(PackedLockTime);

impl fmt::LowerHex for PackedLockTime {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand Down Expand Up @@ -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 {
fn from(h: Height) -> Self {
Expand Down
3 changes: 3 additions & 0 deletions src/blockdata/transaction.rs
Expand Up @@ -32,6 +32,7 @@ use crate::hash_types::{Sighash, Txid, Wtxid};
use crate::VarInt;
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::impl_parse_str_through_int;

#[cfg(doc)]
use crate::util::sighash::SchnorrSighashType;
Expand Down Expand Up @@ -422,6 +423,8 @@ impl fmt::Display for RelativeLockTimeError {
}
}

impl_parse_str_through_int!(Sequence);

#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for RelativeLockTimeError {
Expand Down
35 changes: 35 additions & 0 deletions src/parse.rs
Expand Up @@ -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);

/// 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)?)
}
}

}
}

0 comments on commit 071a1c0

Please sign in to comment.