Put `#[inline]` on most `Script{Buf}` methods

These methods are either newtype casts that should compile to no-ops or
directly calling into some other function with at most some pointer
adjustments. As such making them `#[inline]` is definitely benefitial.
There are also methods that check length and then call some other
function. These are also worth inlining since the length could be known
at compile time and the check could be eliminated.
This commit is contained in:
Martin Habovstiak 2025-02-20 16:18:21 +01:00
parent b7e2af1b6b
commit 0567e6fe1d
3 changed files with 52 additions and 0 deletions

View File

@ -67,6 +67,7 @@ impl Default for &Script {
impl ToOwned for Script { impl ToOwned for Script {
type Owned = ScriptBuf; type Owned = ScriptBuf;
#[inline]
fn to_owned(&self) -> Self::Owned { ScriptBuf::from_bytes(self.to_vec()) } fn to_owned(&self) -> Self::Owned { ScriptBuf::from_bytes(self.to_vec()) }
} }
@ -124,6 +125,7 @@ impl Script {
/// Converts a [`Box<Script>`](Box) into a [`ScriptBuf`] without copying or allocating. /// Converts a [`Box<Script>`](Box) into a [`ScriptBuf`] without copying or allocating.
#[must_use] #[must_use]
#[inline]
pub fn into_script_buf(self: Box<Self>) -> ScriptBuf { pub fn into_script_buf(self: Box<Self>) -> ScriptBuf {
let rw = Box::into_raw(self) as *mut [u8]; let rw = Box::into_raw(self) as *mut [u8];
// SAFETY: copied from `std` // SAFETY: copied from `std`
@ -137,6 +139,7 @@ impl Script {
#[cfg(feature = "arbitrary")] #[cfg(feature = "arbitrary")]
impl<'a> Arbitrary<'a> for &'a Script { impl<'a> Arbitrary<'a> for &'a Script {
#[inline]
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> { fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
let v = <&'a [u8]>::arbitrary(u)?; let v = <&'a [u8]>::arbitrary(u)?;
Ok(Script::from_bytes(v)) Ok(Script::from_bytes(v))

View File

@ -56,6 +56,7 @@ impl ScriptHash {
/// > spend a P2SH output if the redemption script it refers to is >520 bytes in length. /// > spend a P2SH output if the redemption script it refers to is >520 bytes in length.
/// ///
/// ref: [BIP-16](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki#user-content-520byte_limitation_on_serialized_script_size) /// ref: [BIP-16](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki#user-content-520byte_limitation_on_serialized_script_size)
#[inline]
pub fn from_script(redeem_script: &Script) -> Result<Self, RedeemScriptSizeError> { pub fn from_script(redeem_script: &Script) -> Result<Self, RedeemScriptSizeError> {
if redeem_script.len() > MAX_REDEEM_SCRIPT_SIZE { if redeem_script.len() > MAX_REDEEM_SCRIPT_SIZE {
return Err(RedeemScriptSizeError { size: redeem_script.len() }); return Err(RedeemScriptSizeError { size: redeem_script.len() });
@ -70,6 +71,7 @@ impl ScriptHash {
/// then the output will be unspendable (see [BIP-16]). /// then the output will be unspendable (see [BIP-16]).
/// ///
/// [BIP-16]: <https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki#user-content-520byte_limitation_on_serialized_script_size> /// [BIP-16]: <https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki#user-content-520byte_limitation_on_serialized_script_size>
#[inline]
pub fn from_script_unchecked(script: &Script) -> Self { pub fn from_script_unchecked(script: &Script) -> Self {
ScriptHash(hash160::Hash::hash(script.as_bytes())) ScriptHash(hash160::Hash::hash(script.as_bytes()))
} }
@ -84,6 +86,7 @@ impl WScriptHash {
/// > witnessScript must match the 32-byte witness program. /// > witnessScript must match the 32-byte witness program.
/// ///
/// ref: [BIP-141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki) /// ref: [BIP-141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki)
#[inline]
pub fn from_script(witness_script: &Script) -> Result<Self, WitnessScriptSizeError> { pub fn from_script(witness_script: &Script) -> Result<Self, WitnessScriptSizeError> {
if witness_script.len() > MAX_WITNESS_SCRIPT_SIZE { if witness_script.len() > MAX_WITNESS_SCRIPT_SIZE {
return Err(WitnessScriptSizeError { size: witness_script.len() }); return Err(WitnessScriptSizeError { size: witness_script.len() });
@ -98,6 +101,7 @@ impl WScriptHash {
/// output then the output will be unspendable (see [BIP-141]). /// output then the output will be unspendable (see [BIP-141]).
/// ///
/// ref: [BIP-141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki) /// ref: [BIP-141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki)
#[inline]
pub fn from_script_unchecked(script: &Script) -> Self { pub fn from_script_unchecked(script: &Script) -> Self {
WScriptHash(sha256::Hash::hash(script.as_bytes())) WScriptHash(sha256::Hash::hash(script.as_bytes()))
} }
@ -106,6 +110,7 @@ impl WScriptHash {
impl TryFrom<ScriptBuf> for ScriptHash { impl TryFrom<ScriptBuf> for ScriptHash {
type Error = RedeemScriptSizeError; type Error = RedeemScriptSizeError;
#[inline]
fn try_from(redeem_script: ScriptBuf) -> Result<Self, Self::Error> { fn try_from(redeem_script: ScriptBuf) -> Result<Self, Self::Error> {
Self::from_script(&redeem_script) Self::from_script(&redeem_script)
} }
@ -114,6 +119,7 @@ impl TryFrom<ScriptBuf> for ScriptHash {
impl TryFrom<&ScriptBuf> for ScriptHash { impl TryFrom<&ScriptBuf> for ScriptHash {
type Error = RedeemScriptSizeError; type Error = RedeemScriptSizeError;
#[inline]
fn try_from(redeem_script: &ScriptBuf) -> Result<Self, Self::Error> { fn try_from(redeem_script: &ScriptBuf) -> Result<Self, Self::Error> {
Self::from_script(redeem_script) Self::from_script(redeem_script)
} }
@ -122,6 +128,7 @@ impl TryFrom<&ScriptBuf> for ScriptHash {
impl TryFrom<&Script> for ScriptHash { impl TryFrom<&Script> for ScriptHash {
type Error = RedeemScriptSizeError; type Error = RedeemScriptSizeError;
#[inline]
fn try_from(redeem_script: &Script) -> Result<Self, Self::Error> { fn try_from(redeem_script: &Script) -> Result<Self, Self::Error> {
Self::from_script(redeem_script) Self::from_script(redeem_script)
} }
@ -130,6 +137,7 @@ impl TryFrom<&Script> for ScriptHash {
impl TryFrom<ScriptBuf> for WScriptHash { impl TryFrom<ScriptBuf> for WScriptHash {
type Error = WitnessScriptSizeError; type Error = WitnessScriptSizeError;
#[inline]
fn try_from(witness_script: ScriptBuf) -> Result<Self, Self::Error> { fn try_from(witness_script: ScriptBuf) -> Result<Self, Self::Error> {
Self::from_script(&witness_script) Self::from_script(&witness_script)
} }
@ -138,6 +146,7 @@ impl TryFrom<ScriptBuf> for WScriptHash {
impl TryFrom<&ScriptBuf> for WScriptHash { impl TryFrom<&ScriptBuf> for WScriptHash {
type Error = WitnessScriptSizeError; type Error = WitnessScriptSizeError;
#[inline]
fn try_from(witness_script: &ScriptBuf) -> Result<Self, Self::Error> { fn try_from(witness_script: &ScriptBuf) -> Result<Self, Self::Error> {
Self::from_script(witness_script) Self::from_script(witness_script)
} }
@ -146,6 +155,7 @@ impl TryFrom<&ScriptBuf> for WScriptHash {
impl TryFrom<&Script> for WScriptHash { impl TryFrom<&Script> for WScriptHash {
type Error = WitnessScriptSizeError; type Error = WitnessScriptSizeError;
#[inline]
fn try_from(witness_script: &Script) -> Result<Self, Self::Error> { fn try_from(witness_script: &Script) -> Result<Self, Self::Error> {
Self::from_script(witness_script) Self::from_script(witness_script)
} }
@ -159,10 +169,12 @@ pub struct RedeemScriptSizeError {
} }
impl From<Infallible> for RedeemScriptSizeError { impl From<Infallible> for RedeemScriptSizeError {
#[inline]
fn from(never: Infallible) -> Self { match never {} } fn from(never: Infallible) -> Self { match never {} }
} }
impl fmt::Display for RedeemScriptSizeError { impl fmt::Display for RedeemScriptSizeError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "redeem script size exceeds {} bytes: {}", MAX_REDEEM_SCRIPT_SIZE, self.size) write!(f, "redeem script size exceeds {} bytes: {}", MAX_REDEEM_SCRIPT_SIZE, self.size)
} }
@ -179,10 +191,12 @@ pub struct WitnessScriptSizeError {
} }
impl From<Infallible> for WitnessScriptSizeError { impl From<Infallible> for WitnessScriptSizeError {
#[inline]
fn from(never: Infallible) -> Self { match never {} } fn from(never: Infallible) -> Self { match never {} }
} }
impl fmt::Display for WitnessScriptSizeError { impl fmt::Display for WitnessScriptSizeError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "witness script size exceeds {} bytes: {}", MAX_WITNESS_SCRIPT_SIZE, self.size) write!(f, "witness script size exceeds {} bytes: {}", MAX_WITNESS_SCRIPT_SIZE, self.size)
} }
@ -194,14 +208,17 @@ impl std::error::Error for WitnessScriptSizeError {}
// We keep all the `Script` and `ScriptBuf` impls together since its easier to see side-by-side. // We keep all the `Script` and `ScriptBuf` impls together since its easier to see side-by-side.
impl From<ScriptBuf> for Box<Script> { impl From<ScriptBuf> for Box<Script> {
#[inline]
fn from(v: ScriptBuf) -> Self { v.into_boxed_script() } fn from(v: ScriptBuf) -> Self { v.into_boxed_script() }
} }
impl From<ScriptBuf> for Cow<'_, Script> { impl From<ScriptBuf> for Cow<'_, Script> {
#[inline]
fn from(value: ScriptBuf) -> Self { Cow::Owned(value) } fn from(value: ScriptBuf) -> Self { Cow::Owned(value) }
} }
impl<'a> From<Cow<'a, Script>> for ScriptBuf { impl<'a> From<Cow<'a, Script>> for ScriptBuf {
#[inline]
fn from(value: Cow<'a, Script>) -> Self { fn from(value: Cow<'a, Script>) -> Self {
match value { match value {
Cow::Owned(owned) => owned, Cow::Owned(owned) => owned,
@ -211,6 +228,7 @@ impl<'a> From<Cow<'a, Script>> for ScriptBuf {
} }
impl<'a> From<Cow<'a, Script>> for Box<Script> { impl<'a> From<Cow<'a, Script>> for Box<Script> {
#[inline]
fn from(value: Cow<'a, Script>) -> Self { fn from(value: Cow<'a, Script>) -> Self {
match value { match value {
Cow::Owned(owned) => owned.into(), Cow::Owned(owned) => owned.into(),
@ -220,20 +238,24 @@ impl<'a> From<Cow<'a, Script>> for Box<Script> {
} }
impl<'a> From<&'a Script> for Box<Script> { impl<'a> From<&'a Script> for Box<Script> {
#[inline]
fn from(value: &'a Script) -> Self { value.to_owned().into() } fn from(value: &'a Script) -> Self { value.to_owned().into() }
} }
impl<'a> From<&'a Script> for ScriptBuf { impl<'a> From<&'a Script> for ScriptBuf {
#[inline]
fn from(value: &'a Script) -> Self { value.to_owned() } fn from(value: &'a Script) -> Self { value.to_owned() }
} }
impl<'a> From<&'a Script> for Cow<'a, Script> { impl<'a> From<&'a Script> for Cow<'a, Script> {
#[inline]
fn from(value: &'a Script) -> Self { Cow::Borrowed(value) } fn from(value: &'a Script) -> Self { Cow::Borrowed(value) }
} }
/// Note: This will fail to compile on old Rust for targets that don't support atomics /// Note: This will fail to compile on old Rust for targets that don't support atomics
#[cfg(target_has_atomic = "ptr")] #[cfg(target_has_atomic = "ptr")]
impl<'a> From<&'a Script> for Arc<Script> { impl<'a> From<&'a Script> for Arc<Script> {
#[inline]
fn from(value: &'a Script) -> Self { fn from(value: &'a Script) -> Self {
let rw: *const [u8] = Arc::into_raw(Arc::from(value.as_bytes())); let rw: *const [u8] = Arc::into_raw(Arc::from(value.as_bytes()));
// SAFETY: copied from `std` // SAFETY: copied from `std`
@ -245,6 +267,7 @@ impl<'a> From<&'a Script> for Arc<Script> {
} }
impl<'a> From<&'a Script> for Rc<Script> { impl<'a> From<&'a Script> for Rc<Script> {
#[inline]
fn from(value: &'a Script) -> Self { fn from(value: &'a Script) -> Self {
let rw: *const [u8] = Rc::into_raw(Rc::from(value.as_bytes())); let rw: *const [u8] = Rc::into_raw(Rc::from(value.as_bytes()));
// SAFETY: copied from `std` // SAFETY: copied from `std`
@ -256,10 +279,12 @@ impl<'a> From<&'a Script> for Rc<Script> {
} }
impl From<Vec<u8>> for ScriptBuf { impl From<Vec<u8>> for ScriptBuf {
#[inline]
fn from(v: Vec<u8>) -> Self { ScriptBuf::from_bytes(v) } fn from(v: Vec<u8>) -> Self { ScriptBuf::from_bytes(v) }
} }
impl From<ScriptBuf> for Vec<u8> { impl From<ScriptBuf> for Vec<u8> {
#[inline]
fn from(v: ScriptBuf) -> Self { v.into_bytes() } fn from(v: ScriptBuf) -> Self { v.into_bytes() }
} }
@ -269,6 +294,7 @@ impl AsRef<Script> for Script {
} }
impl AsRef<Script> for ScriptBuf { impl AsRef<Script> for ScriptBuf {
#[inline]
fn as_ref(&self) -> &Script { self } fn as_ref(&self) -> &Script { self }
} }
@ -278,14 +304,17 @@ impl AsRef<[u8]> for Script {
} }
impl AsRef<[u8]> for ScriptBuf { impl AsRef<[u8]> for ScriptBuf {
#[inline]
fn as_ref(&self) -> &[u8] { self.as_bytes() } fn as_ref(&self) -> &[u8] { self.as_bytes() }
} }
impl AsMut<Script> for Script { impl AsMut<Script> for Script {
#[inline]
fn as_mut(&mut self) -> &mut Script { self } fn as_mut(&mut self) -> &mut Script { self }
} }
impl AsMut<Script> for ScriptBuf { impl AsMut<Script> for ScriptBuf {
#[inline]
fn as_mut(&mut self) -> &mut Script { self } fn as_mut(&mut self) -> &mut Script { self }
} }
@ -295,6 +324,7 @@ impl AsMut<[u8]> for Script {
} }
impl AsMut<[u8]> for ScriptBuf { impl AsMut<[u8]> for ScriptBuf {
#[inline]
fn as_mut(&mut self) -> &mut [u8] { self.as_mut_bytes() } fn as_mut(&mut self) -> &mut [u8] { self.as_mut_bytes() }
} }
@ -307,6 +337,7 @@ impl fmt::Debug for Script {
} }
impl fmt::Debug for ScriptBuf { impl fmt::Debug for ScriptBuf {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self.as_script(), f) } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self.as_script(), f) }
} }
@ -389,6 +420,7 @@ impl fmt::Display for ScriptBuf {
} }
impl fmt::LowerHex for Script { impl fmt::LowerHex for Script {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::LowerHex::fmt(&self.as_bytes().as_hex(), f) fmt::LowerHex::fmt(&self.as_bytes().as_hex(), f)
} }
@ -404,6 +436,7 @@ impl fmt::LowerHex for ScriptBuf {
internals::impl_to_hex_from_lower_hex!(ScriptBuf, |script_buf: &ScriptBuf| script_buf.len() * 2); internals::impl_to_hex_from_lower_hex!(ScriptBuf, |script_buf: &ScriptBuf| script_buf.len() * 2);
impl fmt::UpperHex for Script { impl fmt::UpperHex for Script {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::UpperHex::fmt(&self.as_bytes().as_hex(), f) fmt::UpperHex::fmt(&self.as_bytes().as_hex(), f)
} }
@ -415,28 +448,34 @@ impl fmt::UpperHex for ScriptBuf {
} }
impl Borrow<Script> for ScriptBuf { impl Borrow<Script> for ScriptBuf {
#[inline]
fn borrow(&self) -> &Script { self } fn borrow(&self) -> &Script { self }
} }
impl BorrowMut<Script> for ScriptBuf { impl BorrowMut<Script> for ScriptBuf {
#[inline]
fn borrow_mut(&mut self) -> &mut Script { self } fn borrow_mut(&mut self) -> &mut Script { self }
} }
impl PartialEq<ScriptBuf> for Script { impl PartialEq<ScriptBuf> for Script {
#[inline]
fn eq(&self, other: &ScriptBuf) -> bool { self.eq(other.as_script()) } fn eq(&self, other: &ScriptBuf) -> bool { self.eq(other.as_script()) }
} }
impl PartialEq<Script> for ScriptBuf { impl PartialEq<Script> for ScriptBuf {
#[inline]
fn eq(&self, other: &Script) -> bool { self.as_script().eq(other) } fn eq(&self, other: &Script) -> bool { self.as_script().eq(other) }
} }
impl PartialOrd<Script> for ScriptBuf { impl PartialOrd<Script> for ScriptBuf {
#[inline]
fn partial_cmp(&self, other: &Script) -> Option<Ordering> { fn partial_cmp(&self, other: &Script) -> Option<Ordering> {
self.as_script().partial_cmp(other) self.as_script().partial_cmp(other)
} }
} }
impl PartialOrd<ScriptBuf> for Script { impl PartialOrd<ScriptBuf> for Script {
#[inline]
fn partial_cmp(&self, other: &ScriptBuf) -> Option<Ordering> { fn partial_cmp(&self, other: &ScriptBuf) -> Option<Ordering> {
self.partial_cmp(other.as_script()) self.partial_cmp(other.as_script())
} }

View File

@ -28,17 +28,21 @@ impl ScriptBuf {
/// Converts byte vector into script. /// Converts byte vector into script.
/// ///
/// This method doesn't (re)allocate. /// This method doesn't (re)allocate.
#[inline]
pub const fn from_bytes(bytes: Vec<u8>) -> Self { ScriptBuf(bytes) } pub const fn from_bytes(bytes: Vec<u8>) -> Self { ScriptBuf(bytes) }
/// Returns a reference to unsized script. /// Returns a reference to unsized script.
#[inline]
pub fn as_script(&self) -> &Script { Script::from_bytes(&self.0) } pub fn as_script(&self) -> &Script { Script::from_bytes(&self.0) }
/// Returns a mutable reference to unsized script. /// Returns a mutable reference to unsized script.
#[inline]
pub fn as_mut_script(&mut self) -> &mut Script { Script::from_bytes_mut(&mut self.0) } pub fn as_mut_script(&mut self) -> &mut Script { Script::from_bytes_mut(&mut self.0) }
/// Converts the script into a byte vector. /// Converts the script into a byte vector.
/// ///
/// This method doesn't (re)allocate. /// This method doesn't (re)allocate.
#[inline]
pub fn into_bytes(self) -> Vec<u8> { self.0 } pub fn into_bytes(self) -> Vec<u8> { self.0 }
/// Converts this `ScriptBuf` into a [boxed](Box) [`Script`]. /// Converts this `ScriptBuf` into a [boxed](Box) [`Script`].
@ -56,6 +60,7 @@ impl ScriptBuf {
} }
/// Constructs a new empty script with pre-allocated capacity. /// Constructs a new empty script with pre-allocated capacity.
#[inline]
pub fn with_capacity(capacity: usize) -> Self { ScriptBuf::from_bytes(Vec::with_capacity(capacity)) } pub fn with_capacity(capacity: usize) -> Self { ScriptBuf::from_bytes(Vec::with_capacity(capacity)) }
/// Pre-allocates at least `additional_len` bytes if needed. /// Pre-allocates at least `additional_len` bytes if needed.
@ -68,6 +73,7 @@ impl ScriptBuf {
/// # Panics /// # Panics
/// ///
/// Panics if the new capacity exceeds `isize::MAX bytes`. /// Panics if the new capacity exceeds `isize::MAX bytes`.
#[inline]
pub fn reserve(&mut self, additional_len: usize) { self.0.reserve(additional_len); } pub fn reserve(&mut self, additional_len: usize) { self.0.reserve(additional_len); }
/// Pre-allocates exactly `additional_len` bytes if needed. /// Pre-allocates exactly `additional_len` bytes if needed.
@ -83,21 +89,25 @@ impl ScriptBuf {
/// # Panics /// # Panics
/// ///
/// Panics if the new capacity exceeds `isize::MAX bytes`. /// Panics if the new capacity exceeds `isize::MAX bytes`.
#[inline]
pub fn reserve_exact(&mut self, additional_len: usize) { self.0.reserve_exact(additional_len); } pub fn reserve_exact(&mut self, additional_len: usize) { self.0.reserve_exact(additional_len); }
} }
impl Deref for ScriptBuf { impl Deref for ScriptBuf {
type Target = Script; type Target = Script;
#[inline]
fn deref(&self) -> &Self::Target { self.as_script() } fn deref(&self) -> &Self::Target { self.as_script() }
} }
impl DerefMut for ScriptBuf { impl DerefMut for ScriptBuf {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_script() } fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_script() }
} }
#[cfg(feature = "arbitrary")] #[cfg(feature = "arbitrary")]
impl<'a> Arbitrary<'a> for ScriptBuf { impl<'a> Arbitrary<'a> for ScriptBuf {
#[inline]
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> { fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
let v = Vec::<u8>::arbitrary(u)?; let v = Vec::<u8>::arbitrary(u)?;
Ok(ScriptBuf::from_bytes(v)) Ok(ScriptBuf::from_bytes(v))