diff --git a/api/units/all-features.txt b/api/units/all-features.txt index 0559a49bc..5698c7c89 100644 --- a/api/units/all-features.txt +++ b/api/units/all-features.txt @@ -1183,7 +1183,9 @@ pub fn bitcoin_units::parse::hex_u32(s: &str) -> core::result::Result core::result::Result pub fn bitcoin_units::parse::hex_u32_unchecked(s: &str) -> core::result::Result pub fn bitcoin_units::parse::hex_u32_unprefixed(s: &str) -> core::result::Result -pub fn bitcoin_units::parse::int + core::convert::Into>(s: S) -> core::result::Result +pub fn bitcoin_units::parse::int_from_box(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::parse::int_from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::parse::int_from_string(s: alloc::string::String) -> core::result::Result pub fn bitcoin_units::weight::Weight::add(self, rhs: &bitcoin_units::weight::Weight) -> Self::Output pub fn bitcoin_units::weight::Weight::add(self, rhs: bitcoin_units::weight::Weight) -> Self::Output pub fn bitcoin_units::weight::Weight::add_assign(&mut self, rhs: &bitcoin_units::weight::Weight) diff --git a/api/units/alloc-only.txt b/api/units/alloc-only.txt index a44702c7a..6274ad864 100644 --- a/api/units/alloc-only.txt +++ b/api/units/alloc-only.txt @@ -1030,7 +1030,9 @@ pub fn bitcoin_units::parse::hex_u32(s: &str) -> core::result::Result core::result::Result pub fn bitcoin_units::parse::hex_u32_unchecked(s: &str) -> core::result::Result pub fn bitcoin_units::parse::hex_u32_unprefixed(s: &str) -> core::result::Result -pub fn bitcoin_units::parse::int + core::convert::Into>(s: S) -> core::result::Result +pub fn bitcoin_units::parse::int_from_box(s: alloc::boxed::Box) -> core::result::Result +pub fn bitcoin_units::parse::int_from_str(s: &str) -> core::result::Result +pub fn bitcoin_units::parse::int_from_string(s: alloc::string::String) -> core::result::Result pub fn bitcoin_units::weight::Weight::add(self, rhs: &bitcoin_units::weight::Weight) -> Self::Output pub fn bitcoin_units::weight::Weight::add(self, rhs: bitcoin_units::weight::Weight) -> Self::Output pub fn bitcoin_units::weight::Weight::add_assign(&mut self, rhs: &bitcoin_units::weight::Weight) diff --git a/api/units/no-features.txt b/api/units/no-features.txt index 39e957f3e..5c448c09e 100644 --- a/api/units/no-features.txt +++ b/api/units/no-features.txt @@ -986,7 +986,7 @@ pub fn bitcoin_units::parse::hex_u32(s: &str) -> core::result::Result core::result::Result pub fn bitcoin_units::parse::hex_u32_unchecked(s: &str) -> core::result::Result pub fn bitcoin_units::parse::hex_u32_unprefixed(s: &str) -> core::result::Result -pub fn bitcoin_units::parse::int + core::convert::Into>(s: S) -> core::result::Result +pub fn bitcoin_units::parse::int_from_str(s: &str) -> core::result::Result pub fn bitcoin_units::weight::Weight::add(self, rhs: &bitcoin_units::weight::Weight) -> Self::Output pub fn bitcoin_units::weight::Weight::add(self, rhs: bitcoin_units::weight::Weight) -> Self::Output pub fn bitcoin_units::weight::Weight::add_assign(&mut self, rhs: &bitcoin_units::weight::Weight) diff --git a/bitcoin/src/blockdata/script/witness_version.rs b/bitcoin/src/blockdata/script/witness_version.rs index fa4f06d48..3c8f408db 100644 --- a/bitcoin/src/blockdata/script/witness_version.rs +++ b/bitcoin/src/blockdata/script/witness_version.rs @@ -82,7 +82,7 @@ impl FromStr for WitnessVersion { type Err = FromStrError; fn from_str(s: &str) -> Result { - let version: u8 = parse::int(s)?; + let version: u8 = parse::int_from_str(s)?; Ok(WitnessVersion::try_from(version)?) } } diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index 5dea49ba9..8a497ffd2 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -1214,7 +1214,7 @@ mod tests { assert_eq!( "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:lol" .parse::(), - Err(ParseOutPointError::Vout(parse::int::("lol").unwrap_err())) + Err(ParseOutPointError::Vout(parse::int_from_str::("lol").unwrap_err())) ); assert_eq!( diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs index 21c11b472..da1a714ac 100644 --- a/bitcoin/src/lib.rs +++ b/bitcoin/src/lib.rs @@ -239,8 +239,8 @@ pub mod parse { #[doc(inline)] pub use units::parse::{ hex_check_unprefixed, hex_remove_prefix, hex_u128, hex_u128_unchecked, hex_u128_unprefixed, - hex_u32, hex_u32_unchecked, hex_u32_unprefixed, int, ParseIntError, PrefixedHexError, - UnprefixedHexError, + hex_u32, hex_u32_unchecked, hex_u32_unprefixed, int_from_box, int_from_str, + int_from_string, ParseIntError, PrefixedHexError, UnprefixedHexError, }; } diff --git a/primitives/src/transaction.rs b/primitives/src/transaction.rs index 4424103f4..bb4005798 100644 --- a/primitives/src/transaction.rs +++ b/primitives/src/transaction.rs @@ -424,7 +424,7 @@ fn parse_vout(s: &str) -> Result { return Err(ParseOutPointError::VoutNotCanonical); } } - parse::int(s).map_err(ParseOutPointError::Vout) + parse::int_from_str(s).map_err(ParseOutPointError::Vout) } /// An error in parsing an [`OutPoint`]. diff --git a/units/src/parse.rs b/units/src/parse.rs index 08f0cf464..130a29462 100644 --- a/units/src/parse.rs +++ b/units/src/parse.rs @@ -76,9 +76,28 @@ mod sealed { /// Parses the input string as an integer returning an error carrying rich context. /// -/// If the caller owns `String` or `Box` which is not used later it's better to pass it as -/// owned since it avoids allocation in error case. -pub fn int + Into>(s: S) -> Result { +/// On error this function allocates to copy the input string into the error return. If the caller +/// has a `String` or `Box` which is not used later it's better to call +/// [`parse::int_from_string`] or [`parse::int_from_box`] respectively. +/// +/// [`parse::int_from_string`]: crate::parse::int_from_string +/// [`parse::int_from_box`]: crate::parse::int_from_box +pub fn int_from_str(s: &str) -> Result { int(s) } + +/// Parses the input string as an integer returning an error carrying rich context. +/// +/// On error the input string is moved into the error return without allocating. +#[cfg(feature = "alloc")] +pub fn int_from_string(s: alloc::string::String) -> Result { int(s) } + +/// Parses the input string as an integer returning an error carrying rich context. +/// +/// On error the input string is converted into the error return without allocating. +#[cfg(feature = "alloc")] +pub fn int_from_box(s: alloc::boxed::Box) -> Result { int(s) } + +// This must be private because we do not want `InputString` to appear in the public API. +fn int + Into>(s: S) -> Result { s.as_ref().parse().map_err(|error| { ParseIntError { input: s.into(), @@ -120,37 +139,44 @@ pub fn int + Into>(s: S) -> Result { - $crate::impl_tryfrom_str_from_int_infallible!(&str, $to, $inner, $fn); - #[cfg(feature = "alloc")] - $crate::impl_tryfrom_str_from_int_infallible!(alloc::string::String, $to, $inner, $fn; alloc::boxed::Box, $to, $inner, $fn); - impl $crate::_export::_core::str::FromStr for $to { type Err = $crate::parse::ParseIntError; fn from_str(s: &str) -> $crate::_export::_core::result::Result { - $crate::parse::int::<$inner, &str>(s).map($to::$fn) + $crate::_export::_core::convert::TryFrom::try_from(s) } } - } -} - -/// Implements `TryFrom<$from> for $to` using `parse::int`, mapping the output using infallible -/// conversion function `fn`. -#[macro_export] -#[doc(hidden)] // Helper macro called by `impl_parse_str_from_int_infallible`. -macro_rules! impl_tryfrom_str_from_int_infallible { - ($($from:ty, $to:ident, $inner:ident, $fn:ident);*) => { - $( - impl $crate::_export::_core::convert::TryFrom<$from> for $to { + impl $crate::_export::_core::convert::TryFrom<&str> for $to { type Error = $crate::parse::ParseIntError; - fn try_from(s: $from) -> $crate::_export::_core::result::Result { - $crate::parse::int::<$inner, $from>(s).map($to::$fn) + fn try_from(s: &str) -> $crate::_export::_core::result::Result { + $crate::parse::int_from_str::<$inner>(s).map($to::$fn) } } - )* - } + + #[cfg(feature = "alloc")] + impl $crate::_export::_core::convert::TryFrom for $to { + type Error = $crate::parse::ParseIntError; + + fn try_from( + s: alloc::string::String, + ) -> $crate::_export::_core::result::Result { + $crate::parse::int_from_string::<$inner>(s).map($to::$fn) + } + } + + #[cfg(feature = "alloc")] + impl $crate::_export::_core::convert::TryFrom> for $to { + type Error = $crate::parse::ParseIntError; + + fn try_from( + s: alloc::boxed::Box, + ) -> $crate::_export::_core::result::Result { + $crate::parse::int_from_box::<$inner>(s).map($to::$fn) + } + } + }; } /// Implements standard parsing traits for `$type` by calling through to `$inner_fn`. @@ -497,9 +523,9 @@ mod tests { #[test] fn parse_int() { - assert!(int::("1").is_ok()); - let _ = int::("not a number").map_err(|e| assert!(e.is_signed)); - let _ = int::("not a number").map_err(|e| assert!(!e.is_signed)); + assert!(int_from_str::("1").is_ok()); + let _ = int_from_str::("not a number").map_err(|e| assert!(e.is_signed)); + let _ = int_from_str::("not a number").map_err(|e| assert!(!e.is_signed)); } #[test] @@ -520,7 +546,7 @@ mod tests { fn from(_: i8) -> Self { TestTypeLargerThanU128(0, 0) } } - let result = panic::catch_unwind(|| int::("not a number")); + let result = panic::catch_unwind(|| int_from_str::("not a number")); assert!(result.is_err()); }