Move impl_array_newtype_stringify to include
What changed, and why it matters
This commit simply moves an existing internal Rust macro from one file to another shared location. The code itself is unchanged; it is a pure refactoring to prepare for splitting a crate. There is no security-relevant change.
No security action needed. Treat as routine refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit relocates the impl_array_newtype_stringify macro from bitcoin/src/internal_macros.rs to a new shared file include/array_newtype.rs, then pulls it back in with include!. The macro body, including its hex encoding/decoding and serde trait implementations, is byte-for-byte identical. No logic, parsing rules, error handling, or visibility was modified.
Changed components
bitcoin/src/internal_macros.rsinclude/array_newtype.rsInspect captured patch +134 / −130
diff --git a/bitcoin/src/internal_macros.rs b/bitcoin/src/internal_macros.rs
index 211d2ec8..7d4471f3 100644
--- a/bitcoin/src/internal_macros.rs
+++ b/bitcoin/src/internal_macros.rs
@@ -43,136 +43,8 @@ macro_rules! impl_consensus_encoding {
}
pub(crate) use impl_consensus_encoding;
-/// Implements several string-ish traits for byte-based newtypes.
-///
-/// - `fmt::Display` and `str::FromStr` (using lowercase hex)
-/// - `fmt::LowerHex` and `UpperHex`
-/// - `fmt::Debug` (using `LowerHex`)
-/// - `serde::Serialize` and `Deserialize` (using lowercase hex)
-///
-/// As well as an inherent `from_hex` method.
-macro_rules! impl_array_newtype_stringify {
- ($t:ident, $len:literal) => {
- impl $t {
- /// Constructs a new `Self` from a hex string.
- pub fn from_hex(s: &str) -> Result<Self, $crate::hex::DecodeFixedLengthBytesError> {
- Ok($t($crate::hex::decode_to_array(s)?))
- }
- }
-
- impl core::fmt::LowerHex for $t {
- fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
- use hex_unstable::{display, Case};
- display::fmt_hex_exact!(f, $len, &self.0, Case::Lower)
- }
- }
-
- impl core::fmt::UpperHex for $t {
- fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
- use hex_unstable::{display, Case};
- display::fmt_hex_exact!(f, $len, &self.0, Case::Upper)
- }
- }
-
- impl core::fmt::Display for $t {
- fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
- core::fmt::LowerHex::fmt(self, f)
- }
- }
-
- impl core::fmt::Debug for $t {
- fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
- core::fmt::LowerHex::fmt(self, f)
- }
- }
-
- impl core::str::FromStr for $t {
- type Err = $crate::hex::DecodeFixedLengthBytesError;
- fn from_str(s: &str) -> core::result::Result<Self, Self::Err> { Self::from_hex(s) }
- }
-
- #[cfg(feature = "serde")]
- impl $crate::serde::Serialize for $t {
- fn serialize<S: $crate::serde::Serializer>(
- &self,
- s: S,
- ) -> core::result::Result<S::Ok, S::Error> {
- if s.is_human_readable() {
- s.collect_str(self)
- } else {
- s.serialize_bytes(&self[..])
- }
- }
- }
-
- #[cfg(feature = "serde")]
- impl<'de> $crate::serde::Deserialize<'de> for $t {
- fn deserialize<D: $crate::serde::Deserializer<'de>>(
- d: D,
- ) -> core::result::Result<$t, D::Error> {
- if d.is_human_readable() {
- struct HexVisitor;
-
- impl<'de> $crate::serde::de::Visitor<'de> for HexVisitor {
- type Value = $t;
-
- fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
- f.write_str("an ASCII hex string")
- }
-
- fn visit_bytes<E>(self, v: &[u8]) -> core::result::Result<Self::Value, E>
- where
- E: $crate::serde::de::Error,
- {
- use $crate::serde::de::Unexpected;
-
- if let Ok(hex) = core::str::from_utf8(v) {
- core::str::FromStr::from_str(hex).map_err(E::custom)
- } else {
- return Err(E::invalid_value(Unexpected::Bytes(v), &self));
- }
- }
-
- fn visit_str<E>(self, hex: &str) -> core::result::Result<Self::Value, E>
- where
- E: $crate::serde::de::Error,
- {
- core::str::FromStr::from_str(hex).map_err(E::custom)
- }
- }
-
- d.deserialize_str(HexVisitor)
- } else {
- struct BytesVisitor;
-
- impl<'de> $crate::serde::de::Visitor<'de> for BytesVisitor {
- type Value = $t;
-
- fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
- f.write_str("a bytestring")
- }
-
- fn visit_bytes<E>(self, v: &[u8]) -> core::result::Result<Self::Value, E>
- where
- E: $crate::serde::de::Error,
- {
- if v.len() != $len {
- Err(E::invalid_length(v.len(), &stringify!($len)))
- } else {
- let mut ret = [0; $len];
- ret.copy_from_slice(v);
- Ok($t(ret))
- }
- }
- }
-
- d.deserialize_bytes(BytesVisitor)
- }
- }
- }
- };
-}
-pub(crate) use impl_array_newtype_stringify;
+// Pull in shared impl_array_newtype_stringify macro from include
+include!("../../include/array_newtype.rs");
#[rustfmt::skip]
macro_rules! impl_asref_push_bytes {
diff --git a/include/array_newtype.rs b/include/array_newtype.rs
new file mode 100644
index 00000000..984f3ae0
--- /dev/null
+++ b/include/array_newtype.rs
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: CC0-1.0
+
+/// Implements several string-ish traits for byte-based newtypes.
+///
+/// - `fmt::Display` and `str::FromStr` (using lowercase hex)
+/// - `fmt::LowerHex` and `UpperHex`
+/// - `fmt::Debug` (using `LowerHex`)
+/// - `serde::Serialize` and `Deserialize` (using lowercase hex)
+///
+/// As well as an inherent `from_hex` method.
+macro_rules! impl_array_newtype_stringify {
+ ($t:ident, $len:literal) => {
+ impl $t {
+ /// Constructs a new `Self` from a hex string.
+ pub fn from_hex(s: &str) -> Result<Self, $crate::hex::DecodeFixedLengthBytesError> {
+ Ok($t($crate::hex::decode_to_array(s)?))
+ }
+ }
+
+ impl core::fmt::LowerHex for $t {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ use hex_unstable::{display, Case};
+ display::fmt_hex_exact!(f, $len, &self.0, Case::Lower)
+ }
+ }
+
+ impl core::fmt::UpperHex for $t {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ use hex_unstable::{display, Case};
+ display::fmt_hex_exact!(f, $len, &self.0, Case::Upper)
+ }
+ }
+
+ impl core::fmt::Display for $t {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ core::fmt::LowerHex::fmt(self, f)
+ }
+ }
+
+ impl core::fmt::Debug for $t {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ core::fmt::LowerHex::fmt(self, f)
+ }
+ }
+
+ impl core::str::FromStr for $t {
+ type Err = $crate::hex::DecodeFixedLengthBytesError;
+ fn from_str(s: &str) -> core::result::Result<Self, Self::Err> { Self::from_hex(s) }
+ }
+
+ #[cfg(feature = "serde")]
+ impl $crate::serde::Serialize for $t {
+ fn serialize<S: $crate::serde::Serializer>(
+ &self,
+ s: S,
+ ) -> core::result::Result<S::Ok, S::Error> {
+ if s.is_human_readable() {
+ s.collect_str(self)
+ } else {
+ s.serialize_bytes(&self[..])
+ }
+ }
+ }
+
+ #[cfg(feature = "serde")]
+ impl<'de> $crate::serde::Deserialize<'de> for $t {
+ fn deserialize<D: $crate::serde::Deserializer<'de>>(
+ d: D,
+ ) -> core::result::Result<$t, D::Error> {
+ if d.is_human_readable() {
+ struct HexVisitor;
+
+ impl<'de> $crate::serde::de::Visitor<'de> for HexVisitor {
+ type Value = $t;
+
+ fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ f.write_str("an ASCII hex string")
+ }
+
+ fn visit_bytes<E>(self, v: &[u8]) -> core::result::Result<Self::Value, E>
+ where
+ E: $crate::serde::de::Error,
+ {
+ use $crate::serde::de::Unexpected;
+
+ if let Ok(hex) = core::str::from_utf8(v) {
+ core::str::FromStr::from_str(hex).map_err(E::custom)
+ } else {
+ return Err(E::invalid_value(Unexpected::Bytes(v), &self));
+ }
+ }
+
+ fn visit_str<E>(self, hex: &str) -> core::result::Result<Self::Value, E>
+ where
+ E: $crate::serde::de::Error,
+ {
+ core::str::FromStr::from_str(hex).map_err(E::custom)
+ }
+ }
+
+ d.deserialize_str(HexVisitor)
+ } else {
+ struct BytesVisitor;
+
+ impl<'de> $crate::serde::de::Visitor<'de> for BytesVisitor {
+ type Value = $t;
+
+ fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ f.write_str("a bytestring")
+ }
+
+ fn visit_bytes<E>(self, v: &[u8]) -> core::result::Result<Self::Value, E>
+ where
+ E: $crate::serde::de::Error,
+ {
+ if v.len() != $len {
+ Err(E::invalid_length(v.len(), &stringify!($len)))
+ } else {
+ let mut ret = [0; $len];
+ ret.copy_from_slice(v);
+ Ok($t(ret))
+ }
+ }
+ }
+
+ d.deserialize_bytes(BytesVisitor)
+ }
+ }
+ }
+ };
+}
+pub(crate) use impl_array_newtype_stringify;
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.