Move impl_array_newtype to include/array_newtype.rs
What changed, and why it matters
This commit is a routine code reorganization. It moves a Rust macro called impl_array_newtype from one internal location to a shared include file and updates call sites to use the new location. No behavior changes, bug fixes, or security fixes are visible in the diff.
No security action needed. Treat as normal maintenance/refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change relocates the impl_array_newtype macro from internals/src/macros.rs to include/array_newtype.rs, which already contained impl_array_newtype_stringify. Call sites in bitcoin/src/blockdata/constants.rs, key_expression/src/bip32.rs, and p2p/src/bip152.rs are updated from internals::impl_array_newtype! to the unqualified impl_array_newtype! after including the shared file. The macro body is identical; this is purely a refactor to consolidate related macros.
Changed components
include/array_newtype.rsinternals/src/macros.rsbitcoin/src/blockdata/constants.rsbitcoin/src/internal_macros.rsbitcoin/src/lib.rskey_expression/src/bip32.rskey_expression/src/lib.rsp2p/src/bip152.rsp2p/src/lib.rsInspect captured patch +130 / −127
diff --git a/bitcoin/src/blockdata/constants.rs b/bitcoin/src/blockdata/constants.rs
index e7458f8b..c5ee103b 100644
--- a/bitcoin/src/blockdata/constants.rs
+++ b/bitcoin/src/blockdata/constants.rs
@@ -7,7 +7,6 @@
//! single transaction.
use crate::block::{self, Block, Checked};
-use crate::internal_macros::impl_array_newtype_stringify;
use crate::locktime::absolute;
use crate::network::{Network, Params};
use crate::opcodes::all::*;
@@ -204,7 +203,7 @@ pub fn genesis_block(params: impl AsRef<Params>) -> Block<Checked> {
/// The uniquely identifying hash of the target blockchain.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ChainHash([u8; 32]);
-internals::impl_array_newtype!(ChainHash, u8, 32);
+impl_array_newtype!(ChainHash, u8, 32);
impl_array_newtype_stringify!(ChainHash, 32);
impl ChainHash {
diff --git a/bitcoin/src/internal_macros.rs b/bitcoin/src/internal_macros.rs
index c5f66d62..ba194195 100644
--- a/bitcoin/src/internal_macros.rs
+++ b/bitcoin/src/internal_macros.rs
@@ -43,9 +43,6 @@ macro_rules! impl_consensus_encoding {
}
pub(crate) use impl_consensus_encoding;
-// Pull in shared impl_array_newtype_stringify macro from include
-include!("../include/array_newtype.rs");
-
macro_rules! only_doc_attrs {
({}, {$($fun:tt)*}) => {
$($fun)*
diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs
index 7a93f2c0..dbef4541 100644
--- a/bitcoin/src/lib.rs
+++ b/bitcoin/src/lib.rs
@@ -79,6 +79,7 @@ pub extern crate serde;
mod internal_macros;
+include!("../include/array_newtype.rs");
include!("../include/newtype.rs"); // Explained in `REPO_DIR/docs/README.md`.
pub mod ext {
diff --git a/include/array_newtype.rs b/include/array_newtype.rs
index 7adba497..f09df395 100644
--- a/include/array_newtype.rs
+++ b/include/array_newtype.rs
@@ -8,6 +8,7 @@
/// - `serde::Serialize` and `Deserialize` (using lowercase hex)
///
/// As well as an inherent `from_hex` method.
+#[allow(unused_macros)]
macro_rules! impl_array_newtype_stringify {
($t:ident, $len:literal) => {
impl $t {
@@ -134,4 +135,125 @@ macro_rules! impl_array_newtype_stringify {
}
};
}
+#[allow(unused_imports)]
pub(crate) use impl_array_newtype_stringify;
+
+/// Implements standard array methods for a given wrapper type.
+#[allow(unused_macros)]
+macro_rules! impl_array_newtype {
+ ($thing:ident, $ty:ty, $len:literal) => {
+ impl $thing {
+ /// Constructs a new `Self` by wrapping `bytes`.
+ #[inline]
+ pub fn from_byte_array(bytes: [u8; $len]) -> Self { Self(bytes) }
+
+ /// Returns a reference the underlying byte array.
+ #[inline]
+ pub fn as_byte_array(&self) -> &[u8; $len] { &self.0 }
+
+ /// Returns the underlying byte array.
+ #[inline]
+ pub fn to_byte_array(self) -> [u8; $len] {
+ // We rely on `Copy` being implemented for $thing so conversion
+ // methods use the correct Rust naming conventions.
+ fn check_copy<T: Copy>() {}
+ check_copy::<$thing>();
+
+ self.0
+ }
+
+ /// Copies the underlying bytes into a new `Vec`.
+ #[inline]
+ pub fn to_vec(self) -> alloc::vec::Vec<u8> { self.0.to_vec() }
+
+ /// Returns a slice of the underlying bytes.
+ #[inline]
+ pub fn as_bytes(&self) -> &[u8] { &self.0 }
+
+ /// Converts the object to a raw pointer.
+ #[inline]
+ pub fn as_ptr(&self) -> *const $ty {
+ let &$thing(ref dat) = self;
+ dat.as_ptr()
+ }
+
+ /// Converts the object to a mutable raw pointer.
+ #[inline]
+ pub fn as_mut_ptr(&mut self) -> *mut $ty {
+ let &mut $thing(ref mut dat) = self;
+ dat.as_mut_ptr()
+ }
+
+ /// Returns the length of the object as an array.
+ #[inline]
+ pub fn len(&self) -> usize { $len }
+
+ /// Returns whether the object, as an array, is empty. Always false.
+ #[inline]
+ pub fn is_empty(&self) -> bool { false }
+ }
+
+ impl<'a> core::convert::From<[$ty; $len]> for $thing {
+ fn from(data: [$ty; $len]) -> Self { $thing(data) }
+ }
+
+ impl<'a> core::convert::From<&'a [$ty; $len]> for $thing {
+ fn from(data: &'a [$ty; $len]) -> Self { $thing(*data) }
+ }
+
+ impl<'a> core::convert::TryFrom<&'a [$ty]> for $thing {
+ type Error = core::array::TryFromSliceError;
+
+ fn try_from(data: &'a [$ty]) -> core::result::Result<Self, Self::Error> {
+ use core::convert::TryInto;
+
+ Ok($thing(data.try_into()?))
+ }
+ }
+
+ impl AsRef<[$ty; $len]> for $thing {
+ fn as_ref(&self) -> &[$ty; $len] { &self.0 }
+ }
+
+ impl AsMut<[$ty; $len]> for $thing {
+ fn as_mut(&mut self) -> &mut [$ty; $len] { &mut self.0 }
+ }
+
+ impl AsRef<[$ty]> for $thing {
+ fn as_ref(&self) -> &[$ty] { &self.0 }
+ }
+
+ impl AsMut<[$ty]> for $thing {
+ fn as_mut(&mut self) -> &mut [$ty] { &mut self.0 }
+ }
+
+ impl core::borrow::Borrow<[$ty; $len]> for $thing {
+ fn borrow(&self) -> &[$ty; $len] { &self.0 }
+ }
+
+ impl core::borrow::BorrowMut<[$ty; $len]> for $thing {
+ fn borrow_mut(&mut self) -> &mut [$ty; $len] { &mut self.0 }
+ }
+
+ // The following two are valid because `[T; N]: Borrow<[T]>`
+ impl core::borrow::Borrow<[$ty]> for $thing {
+ fn borrow(&self) -> &[$ty] { &self.0 }
+ }
+
+ impl core::borrow::BorrowMut<[$ty]> for $thing {
+ fn borrow_mut(&mut self) -> &mut [$ty] { &mut self.0 }
+ }
+
+ impl<I> core::ops::Index<I> for $thing
+ where
+ [$ty]: core::ops::Index<I>,
+ {
+ type Output = <[$ty] as core::ops::Index<I>>::Output;
+
+ #[inline]
+ fn index(&self, index: I) -> &Self::Output { &self.0[index] }
+ }
+ };
+}
+#[allow(unused_imports)]
+pub(crate) use impl_array_newtype;
diff --git a/internals/src/macros.rs b/internals/src/macros.rs
index f42786fe..1486ce53 100644
--- a/internals/src/macros.rs
+++ b/internals/src/macros.rs
@@ -245,121 +245,3 @@ macro_rules! _emit_alloc {
macro_rules! _emit_alloc {
($($tokens:tt)*) => {};
}
-
-/// Implements standard array methods for a given wrapper type.
-#[macro_export]
-macro_rules! impl_array_newtype {
- ($thing:ident, $ty:ty, $len:literal) => {
- impl $thing {
- /// Constructs a new `Self` by wrapping `bytes`.
- #[inline]
- pub fn from_byte_array(bytes: [u8; $len]) -> Self { Self(bytes) }
-
- /// Returns a reference the underlying byte array.
- #[inline]
- pub fn as_byte_array(&self) -> &[u8; $len] { &self.0 }
-
- /// Returns the underlying byte array.
- #[inline]
- pub fn to_byte_array(self) -> [u8; $len] {
- // We rely on `Copy` being implemented for $thing so conversion
- // methods use the correct Rust naming conventions.
- fn check_copy<T: Copy>() {}
- check_copy::<$thing>();
-
- self.0
- }
-
- /// Copies the underlying bytes into a new `Vec`.
- #[inline]
- pub fn to_vec(self) -> alloc::vec::Vec<u8> { self.0.to_vec() }
-
- /// Returns a slice of the underlying bytes.
- #[inline]
- pub fn as_bytes(&self) -> &[u8] { &self.0 }
-
- /// Converts the object to a raw pointer.
- #[inline]
- pub fn as_ptr(&self) -> *const $ty {
- let &$thing(ref dat) = self;
- dat.as_ptr()
- }
-
- /// Converts the object to a mutable raw pointer.
- #[inline]
- pub fn as_mut_ptr(&mut self) -> *mut $ty {
- let &mut $thing(ref mut dat) = self;
- dat.as_mut_ptr()
- }
-
- /// Returns the length of the object as an array.
- #[inline]
- pub fn len(&self) -> usize { $len }
-
- /// Returns whether the object, as an array, is empty. Always false.
- #[inline]
- pub fn is_empty(&self) -> bool { false }
- }
-
- impl<'a> core::convert::From<[$ty; $len]> for $thing {
- fn from(data: [$ty; $len]) -> Self { $thing(data) }
- }
-
- impl<'a> core::convert::From<&'a [$ty; $len]> for $thing {
- fn from(data: &'a [$ty; $len]) -> Self { $thing(*data) }
- }
-
- impl<'a> core::convert::TryFrom<&'a [$ty]> for $thing {
- type Error = core::array::TryFromSliceError;
-
- fn try_from(data: &'a [$ty]) -> core::result::Result<Self, Self::Error> {
- use core::convert::TryInto;
-
- Ok($thing(data.try_into()?))
- }
- }
-
- impl AsRef<[$ty; $len]> for $thing {
- fn as_ref(&self) -> &[$ty; $len] { &self.0 }
- }
-
- impl AsMut<[$ty; $len]> for $thing {
- fn as_mut(&mut self) -> &mut [$ty; $len] { &mut self.0 }
- }
-
- impl AsRef<[$ty]> for $thing {
- fn as_ref(&self) -> &[$ty] { &self.0 }
- }
-
- impl AsMut<[$ty]> for $thing {
- fn as_mut(&mut self) -> &mut [$ty] { &mut self.0 }
- }
-
- impl core::borrow::Borrow<[$ty; $len]> for $thing {
- fn borrow(&self) -> &[$ty; $len] { &self.0 }
- }
-
- impl core::borrow::BorrowMut<[$ty; $len]> for $thing {
- fn borrow_mut(&mut self) -> &mut [$ty; $len] { &mut self.0 }
- }
-
- // The following two are valid because `[T; N]: Borrow<[T]>`
- impl core::borrow::Borrow<[$ty]> for $thing {
- fn borrow(&self) -> &[$ty] { &self.0 }
- }
-
- impl core::borrow::BorrowMut<[$ty]> for $thing {
- fn borrow_mut(&mut self) -> &mut [$ty] { &mut self.0 }
- }
-
- impl<I> core::ops::Index<I> for $thing
- where
- [$ty]: core::ops::Index<I>,
- {
- type Output = <[$ty] as core::ops::Index<I>>::Output;
-
- #[inline]
- fn index(&self, index: I) -> &Self::Output { &self.0[index] }
- }
- };
-}
diff --git a/key_expression/src/bip32.rs b/key_expression/src/bip32.rs
index e911f0ac..2f26255a 100644
--- a/key_expression/src/bip32.rs
+++ b/key_expression/src/bip32.rs
@@ -45,7 +45,7 @@ pub type ExtendedPrivKey = Xpriv;
/// A chain code
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ChainCode([u8; 32]);
-internals::impl_array_newtype!(ChainCode, u8, 32);
+impl_array_newtype!(ChainCode, u8, 32);
crate::impl_array_newtype_stringify!(ChainCode, 32);
impl ChainCode {
@@ -62,7 +62,7 @@ impl ChainCode {
/// A fingerprint
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Fingerprint([u8; 4]);
-internals::impl_array_newtype!(Fingerprint, u8, 4);
+impl_array_newtype!(Fingerprint, u8, 4);
crate::impl_array_newtype_stringify!(Fingerprint, 4);
hash_newtype! {
diff --git a/key_expression/src/lib.rs b/key_expression/src/lib.rs
index 4b0a68b5..ddf542a4 100644
--- a/key_expression/src/lib.rs
+++ b/key_expression/src/lib.rs
@@ -25,7 +25,7 @@ extern crate hex;
#[cfg(feature = "serde")]
extern crate serde;
-// Pull in shared impl_array_newtype_stringify macro from include
+// Pull in shared macros from include
// The impl_array_newtype_stringify requires crate::serde, $crate::hex and
// crate::hashes to exist.
#[cfg(feature = "alloc")]
diff --git a/p2p/src/bip152.rs b/p2p/src/bip152.rs
index 228958f6..0e63e11d 100644
--- a/p2p/src/bip152.rs
+++ b/p2p/src/bip152.rs
@@ -112,7 +112,7 @@ mod sealed {
/// Short transaction IDs are used to represent a transaction without sending a full 256-bit hash.
#[derive(PartialEq, Eq, Clone, Copy, Hash, Default, PartialOrd, Ord)]
pub struct ShortId([u8; 6]);
-internals::impl_array_newtype!(ShortId, u8, 6);
+impl_array_newtype!(ShortId, u8, 6);
impl ShortId {
/// Calculates the `SipHash24` keys used to calculate short IDs.
diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs
index 10d0d892..a45b9561 100644
--- a/p2p/src/lib.rs
+++ b/p2p/src/lib.rs
@@ -8,6 +8,8 @@
#![warn(deprecated_in_future)]
#![doc(test(attr(warn(unused))))]
+include!("../include/array_newtype.rs");
+
mod network_ext;
#[cfg(feature = "std")]
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.