6ba7758b30 Improve array macros (Tobin C. Harding)

Pull request description:

  Currently we have two macros used when creating array wrapper types, one is in `internals` and the other in `bitcoin::internal_macros`. It is not immediately obvious what is what and why there are two.

  Improve the macros by:

  - Move the inherent functions to `impl_array_newtype`
  - Use `*_byte_array` for the names instead of `*_bytes`
  - Re-name the other macro to match what it now does

ACKs for top commit:
  apoelstra:
    ACK 6ba7758b30

Tree-SHA512: 36ed0fae0d28f24d29287062eb05bbc1e9e8b565f4ff41fd893503a25404ed8e185a34d75e398a8a660923ffda3b832b6157011598d5a75a5c4aafdffc74af2a
This commit is contained in:
Andrew Poelstra 2024-05-28 15:47:08 +00:00
commit 65a5dfcd6b
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
6 changed files with 46 additions and 31 deletions

View File

@ -13,7 +13,7 @@ use internals::impl_array_newtype;
use io::{BufRead, Write}; use io::{BufRead, Write};
use crate::consensus::encode::{self, Decodable, Encodable, VarInt}; use crate::consensus::encode::{self, Decodable, Encodable, VarInt};
use crate::internal_macros::{impl_bytes_newtype, impl_consensus_encoding}; use crate::internal_macros::{impl_array_newtype_stringify, impl_consensus_encoding};
use crate::prelude::*; use crate::prelude::*;
use crate::{block, Block, BlockHash, Transaction}; use crate::{block, Block, BlockHash, Transaction};
@ -94,7 +94,7 @@ impl Decodable for PrefilledTransaction {
#[derive(PartialEq, Eq, Clone, Copy, Hash, Default, PartialOrd, Ord)] #[derive(PartialEq, Eq, Clone, Copy, Hash, Default, PartialOrd, Ord)]
pub struct ShortId([u8; 6]); pub struct ShortId([u8; 6]);
impl_array_newtype!(ShortId, u8, 6); impl_array_newtype!(ShortId, u8, 6);
impl_bytes_newtype!(ShortId, 6); impl_array_newtype_stringify!(ShortId, 6);
impl ShortId { impl ShortId {
/// Calculate the SipHash24 keys used to calculate short IDs. /// Calculate the SipHash24 keys used to calculate short IDs.

View File

@ -15,7 +15,7 @@ use io::Write;
use secp256k1::{Secp256k1, XOnlyPublicKey}; use secp256k1::{Secp256k1, XOnlyPublicKey};
use crate::crypto::key::{CompressedPublicKey, Keypair, PrivateKey}; use crate::crypto::key::{CompressedPublicKey, Keypair, PrivateKey};
use crate::internal_macros::impl_bytes_newtype; use crate::internal_macros::impl_array_newtype_stringify;
use crate::network::NetworkKind; use crate::network::NetworkKind;
use crate::prelude::*; use crate::prelude::*;
@ -40,7 +40,7 @@ pub type ExtendedPrivKey = Xpriv;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ChainCode([u8; 32]); pub struct ChainCode([u8; 32]);
impl_array_newtype!(ChainCode, u8, 32); impl_array_newtype!(ChainCode, u8, 32);
impl_bytes_newtype!(ChainCode, 32); impl_array_newtype_stringify!(ChainCode, 32);
impl ChainCode { impl ChainCode {
fn from_hmac(hmac: Hmac<sha512::Hash>) -> Self { fn from_hmac(hmac: Hmac<sha512::Hash>) -> Self {
@ -52,7 +52,7 @@ impl ChainCode {
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Fingerprint([u8; 4]); pub struct Fingerprint([u8; 4]);
impl_array_newtype!(Fingerprint, u8, 4); impl_array_newtype!(Fingerprint, u8, 4);
impl_bytes_newtype!(Fingerprint, 4); impl_array_newtype_stringify!(Fingerprint, 4);
hash_newtype! { hash_newtype! {
/// Extended key identifier as defined in BIP-32. /// Extended key identifier as defined in BIP-32.

View File

@ -16,7 +16,7 @@ use crate::blockdata::script;
use crate::blockdata::transaction::{self, OutPoint, Sequence, Transaction, TxIn, TxOut}; use crate::blockdata::transaction::{self, OutPoint, Sequence, Transaction, TxIn, TxOut};
use crate::blockdata::witness::Witness; use crate::blockdata::witness::Witness;
use crate::consensus::Params; use crate::consensus::Params;
use crate::internal_macros::impl_bytes_newtype; use crate::internal_macros::impl_array_newtype_stringify;
use crate::network::Network; use crate::network::Network;
use crate::pow::CompactTarget; use crate::pow::CompactTarget;
use crate::{Amount, BlockHash}; use crate::{Amount, BlockHash};
@ -155,7 +155,7 @@ pub fn genesis_block(params: impl AsRef<Params>) -> Block {
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ChainHash([u8; 32]); pub struct ChainHash([u8; 32]);
impl_array_newtype!(ChainHash, u8, 32); impl_array_newtype!(ChainHash, u8, 32);
impl_bytes_newtype!(ChainHash, 32); impl_array_newtype_stringify!(ChainHash, 32);
impl ChainHash { impl ChainHash {
// Mainnet value can be verified at https://github.com/lightning/bolts/blob/master/00-introduction.md // Mainnet value can be verified at https://github.com/lightning/bolts/blob/master/00-introduction.md

View File

@ -43,30 +43,17 @@ macro_rules! impl_consensus_encoding {
} }
pub(crate) use impl_consensus_encoding; pub(crate) use impl_consensus_encoding;
/// Implements several traits for byte-based newtypes. /// Implements several string-ish traits for byte-based newtypes.
/// Implements: ///
/// - core::fmt::LowerHex /// - `fmt::Display` and `str::FromStr` (using lowercase hex)
/// - core::fmt::UpperHex /// - `fmt::LowerHex` and `UpperHex`
/// - core::fmt::Display /// - `fmt::Debug` (using `LowerHex`)
/// - core::str::FromStr /// - `serde::Serialize` and `Deserialize` (using lowercase hex)
macro_rules! impl_bytes_newtype { ///
/// As well as an inherent `from_hex` method.
macro_rules! impl_array_newtype_stringify {
($t:ident, $len:literal) => { ($t:ident, $len:literal) => {
impl $t { impl $t {
/// Returns a reference the underlying bytes.
#[inline]
pub fn as_bytes(&self) -> &[u8; $len] { &self.0 }
/// Returns the underlying bytes.
#[inline]
pub fn to_bytes(self) -> [u8; $len] {
// We rely on `Copy` being implemented for $t so conversion
// methods use the correct Rust naming conventions.
fn check_copy<T: Copy>() {}
check_copy::<$t>();
self.0
}
/// Creates `Self` from a hex string. /// Creates `Self` from a hex string.
pub fn from_hex(s: &str) -> Result<Self, hex::HexToArrayError> { pub fn from_hex(s: &str) -> Result<Self, hex::HexToArrayError> {
Ok($t($crate::hex::FromHex::from_hex(s)?)) Ok($t($crate::hex::FromHex::from_hex(s)?))
@ -185,7 +172,7 @@ macro_rules! impl_bytes_newtype {
} }
}; };
} }
pub(crate) use impl_bytes_newtype; pub(crate) use impl_array_newtype_stringify;
#[rustfmt::skip] #[rustfmt::skip]
macro_rules! impl_hashencode { macro_rules! impl_hashencode {

View File

@ -184,7 +184,7 @@ impl Serialize for KeySource {
fn serialize(&self) -> Vec<u8> { fn serialize(&self) -> Vec<u8> {
let mut rv: Vec<u8> = Vec::with_capacity(key_source_len(self)); let mut rv: Vec<u8> = Vec::with_capacity(key_source_len(self));
rv.append(&mut self.0.to_bytes().to_vec()); rv.append(&mut self.0.to_byte_array().to_vec());
for cnum in self.1.into_iter() { for cnum in self.1.into_iter() {
rv.append(&mut serialize(&u32::from(*cnum))) rv.append(&mut serialize(&u32::from(*cnum)))

View File

@ -7,6 +7,34 @@
macro_rules! impl_array_newtype { macro_rules! impl_array_newtype {
($thing:ident, $ty:ty, $len:literal) => { ($thing:ident, $ty:ty, $len:literal) => {
impl $thing { impl $thing {
/// Creates `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
}
/// Returns a slice of the underlying bytes.
#[inline]
pub fn as_bytes(&self) -> &[u8] { &self.0 }
/// Copies the underlying bytes into a new `Vec`.
#[cfg(feature = "alloc")]
#[inline]
pub fn to_bytes(&self) -> alloc::vec::Vec<u8> { self.0.to_vec() }
/// Converts the object to a raw pointer. /// Converts the object to a raw pointer.
#[inline] #[inline]
pub fn as_ptr(&self) -> *const $ty { pub fn as_ptr(&self) -> *const $ty {