diff --git a/bitcoin/src/blockdata/script/mod.rs b/bitcoin/src/blockdata/script/mod.rs index 7e1ac3442..57a4bae9f 100644 --- a/bitcoin/src/blockdata/script/mod.rs +++ b/bitcoin/src/blockdata/script/mod.rs @@ -65,6 +65,7 @@ use core::fmt; use core::ops::{Deref, DerefMut}; use hashes::{hash160, sha256}; +use internals::impl_to_hex_from_lower_hex; use io::{BufRead, Write}; use crate::consensus::{encode, Decodable, Encodable}; @@ -459,11 +460,13 @@ impl fmt::LowerHex for Script { fmt::LowerHex::fmt(&self.as_bytes().as_hex(), f) } } +impl_to_hex_from_lower_hex!(Script, |script: &Script| script.len() * 2); impl fmt::LowerHex for ScriptBuf { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self.as_script(), f) } } +impl_to_hex_from_lower_hex!(ScriptBuf, |script_buf: &ScriptBuf| script_buf.len() * 2); impl fmt::UpperHex for Script { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/bitcoin/src/crypto/ecdsa.rs b/bitcoin/src/crypto/ecdsa.rs index 9fa2d734c..646ccaf47 100644 --- a/bitcoin/src/crypto/ecdsa.rs +++ b/bitcoin/src/crypto/ecdsa.rs @@ -8,7 +8,7 @@ use core::str::FromStr; use core::{fmt, iter}; use hex::FromHex; -use internals::write_err; +use internals::{impl_to_hex_from_lower_hex, write_err}; use io::Write; use crate::prelude::{DisplayHex, Vec}; @@ -174,6 +174,7 @@ impl fmt::LowerHex for SerializedSignature { fmt::LowerHex::fmt(&(**self).as_hex(), f) } } +impl_to_hex_from_lower_hex!(SerializedSignature, |signature: &SerializedSignature| signature.len * 2); impl fmt::UpperHex for SerializedSignature { #[inline] diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs index d38c249d6..a0eb870dd 100644 --- a/bitcoin/src/crypto/key.rs +++ b/bitcoin/src/crypto/key.rs @@ -12,7 +12,7 @@ use core::str::FromStr; use hashes::hash160; use hex::{FromHex, HexToArrayError}; use internals::array_vec::ArrayVec; -use internals::write_err; +use internals::{impl_to_hex_from_lower_hex, write_err}; use io::{Read, Write}; use crate::crypto::ecdsa; @@ -705,6 +705,8 @@ pub struct TweakedPublicKey(XOnlyPublicKey); impl fmt::LowerHex for TweakedPublicKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } } +// Allocate for serialized size +impl_to_hex_from_lower_hex!(TweakedPublicKey, |_| constants::SCHNORR_PUBLIC_KEY_SIZE * 2); impl fmt::Display for TweakedPublicKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } diff --git a/bitcoin/src/p2p/mod.rs b/bitcoin/src/p2p/mod.rs index f7323815d..b64fc36e0 100644 --- a/bitcoin/src/p2p/mod.rs +++ b/bitcoin/src/p2p/mod.rs @@ -22,9 +22,8 @@ pub mod message_network; use core::str::FromStr; use core::{fmt, ops}; - use hex::FromHex; -use internals::{debug_from_display, write_err}; +use internals::{debug_from_display, impl_to_hex_from_lower_hex, write_err}; use io::{BufRead, Write}; use crate::consensus::encode::{self, Decodable, Encodable}; @@ -123,6 +122,7 @@ impl ServiceFlags { impl fmt::LowerHex for ServiceFlags { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } } +impl_to_hex_from_lower_hex!(ServiceFlags, |service_flags: &ServiceFlags| 16 - service_flags.0.leading_zeros() as usize / 4); impl fmt::UpperHex for ServiceFlags { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) } @@ -290,6 +290,7 @@ impl fmt::LowerHex for Magic { Ok(()) } } +impl_to_hex_from_lower_hex!(Magic, |_| 8); impl fmt::UpperHex for Magic { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs index 52440d726..637ba939b 100644 --- a/bitcoin/src/pow.rs +++ b/bitcoin/src/pow.rs @@ -7,7 +7,7 @@ use core::ops::{Add, Div, Mul, Not, Rem, Shl, Shr, Sub}; use core::{cmp, fmt}; - +use internals::impl_to_hex_from_lower_hex; use io::{BufRead, Write}; #[cfg(all(test, mutate))] use mutagen::mutate; @@ -108,6 +108,7 @@ impl Work { pub fn log2(self) -> f64 { self.0.to_f64().log2() } } do_impl!(Work); +impl_to_hex_from_lower_hex!(Work, |_| 64); impl Add for Work { type Output = Work; @@ -333,6 +334,7 @@ impl Target { pub fn max_transition_threshold_unchecked(&self) -> Self { Self(self.0 << 2) } } do_impl!(Target); +impl_to_hex_from_lower_hex!(Target, |_| 64); define_extension_trait! { /// Extension functionality for the [`CompactTarget`] type. diff --git a/bitcoin/src/taproot/mod.rs b/bitcoin/src/taproot/mod.rs index d236649a4..3227159d9 100644 --- a/bitcoin/src/taproot/mod.rs +++ b/bitcoin/src/taproot/mod.rs @@ -12,7 +12,7 @@ use core::fmt; use core::iter::FusedIterator; use hashes::{hash_newtype, sha256t, sha256t_tag, HashEngine}; -use internals::write_err; +use internals::{impl_to_hex_from_lower_hex, write_err}; use io::Write; use secp256k1::{Scalar, Secp256k1}; @@ -1221,6 +1221,7 @@ impl fmt::LowerHex for FutureLeafVersion { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } } +impl_to_hex_from_lower_hex!(FutureLeafVersion, |_| 2); impl fmt::UpperHex for FutureLeafVersion { #[inline] @@ -1277,6 +1278,7 @@ impl fmt::LowerHex for LeafVersion { fmt::LowerHex::fmt(&self.to_consensus(), f) } } +impl_to_hex_from_lower_hex!(LeafVersion, |_| 2); impl fmt::UpperHex for LeafVersion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/internals/src/macros.rs b/internals/src/macros.rs index a12802e8d..e1ff3a96c 100644 --- a/internals/src/macros.rs +++ b/internals/src/macros.rs @@ -204,3 +204,30 @@ macro_rules! impl_from_infallible { } } } + +/// Implements `to_hex` for functions that have implemented [`core::fmt::LowerHex`] +#[macro_export] +#[cfg(feature = "alloc")] +macro_rules! impl_to_hex_from_lower_hex { + ($t:ident, $hex_len_fn:expr) => { + impl $t { + /// Gets the hex representation of this type + pub fn to_hex(&self) -> alloc::string::String { + use core::fmt::Write; + + let mut hex_string = alloc::string::String::with_capacity($hex_len_fn(self)); + write!(&mut hex_string, "{:x}", self).expect("writing to string shouldn't fail"); + + hex_string + } + } + }; +} + +#[macro_export] +#[cfg(not(feature = "alloc"))] +macro_rules! impl_to_hex_from_lower_hex { + ($t:ident, $hex_len_fn:expr) => { + + }; +} diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 3b90a8507..304e86bae 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -47,5 +47,5 @@ pub use self::{pow::CompactTarget, sequence::Sequence}; #[allow(unused_imports)] mod prelude { #[cfg(feature = "alloc")] - pub use alloc::string::ToString; + pub use alloc::string::{String, ToString}; } diff --git a/primitives/src/pow.rs b/primitives/src/pow.rs index b1e8aaa7f..18bd549a4 100644 --- a/primitives/src/pow.rs +++ b/primitives/src/pow.rs @@ -3,6 +3,7 @@ //! Proof-of-work related integer types. use core::fmt; +use internals::impl_to_hex_from_lower_hex; /// Encoding of 256-bit target as 32-bit float. /// @@ -34,6 +35,7 @@ impl fmt::LowerHex for CompactTarget { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } } +impl_to_hex_from_lower_hex!(CompactTarget, |compact_target: &CompactTarget| 8 - compact_target.0.leading_zeros() as usize / 4); impl fmt::UpperHex for CompactTarget { #[inline] diff --git a/primitives/src/sequence.rs b/primitives/src/sequence.rs index 4d0ddca5c..5e7de3f09 100644 --- a/primitives/src/sequence.rs +++ b/primitives/src/sequence.rs @@ -16,14 +16,13 @@ //! [BIP-125]: use core::fmt; - +use internals::impl_to_hex_from_lower_hex; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; #[cfg(feature = "alloc")] use units::locktime::relative::TimeOverflowError; #[cfg(feature = "alloc")] use units::parse::{self, PrefixedHexError, UnprefixedHexError}; - #[cfg(feature = "alloc")] use crate::locktime::relative; @@ -220,6 +219,7 @@ impl fmt::Display for Sequence { impl fmt::LowerHex for Sequence { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } } +impl_to_hex_from_lower_hex!(Sequence, |sequence: &Sequence| 8 - sequence.0.leading_zeros() as usize / 4); impl fmt::UpperHex for Sequence { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }