Improve array macros

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` for functions
  that return arrays
- Add `as_bytes` to return a slice
- Add `to_bytes` to return a vector
- Re-name the other macro to match what it now does
This commit is contained in:
Tobin C. Harding 2024-05-07 14:30:08 +10:00
parent 2e8bd5f06a
commit 6ba7758b30
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
6 changed files with 46 additions and 31 deletions

View File

@ -14,7 +14,7 @@ use internals::impl_array_newtype;
use io::{BufRead, Write};
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::{block, Block, BlockHash, Transaction};
@ -95,7 +95,7 @@ impl Decodable for PrefilledTransaction {
#[derive(PartialEq, Eq, Clone, Copy, Hash, Default, PartialOrd, Ord)]
pub struct ShortId([u8; 6]);
impl_array_newtype!(ShortId, u8, 6);
impl_bytes_newtype!(ShortId, 6);
impl_array_newtype_stringify!(ShortId, 6);
impl ShortId {
/// Calculate the SipHash24 keys used to calculate short IDs.

View File

@ -16,7 +16,7 @@ use io::Write;
use secp256k1::{Secp256k1, XOnlyPublicKey};
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::prelude::*;
@ -41,7 +41,7 @@ pub type ExtendedPrivKey = Xpriv;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ChainCode([u8; 32]);
impl_array_newtype!(ChainCode, u8, 32);
impl_bytes_newtype!(ChainCode, 32);
impl_array_newtype_stringify!(ChainCode, 32);
impl ChainCode {
fn from_hmac(hmac: Hmac<sha512::Hash>) -> Self {
@ -53,7 +53,7 @@ impl ChainCode {
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Fingerprint([u8; 4]);
impl_array_newtype!(Fingerprint, u8, 4);
impl_bytes_newtype!(Fingerprint, 4);
impl_array_newtype_stringify!(Fingerprint, 4);
hash_newtype! {
/// Extended key identifier as defined in BIP-32.

View File

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

View File

@ -44,30 +44,17 @@ macro_rules! impl_consensus_encoding {
}
pub(crate) use impl_consensus_encoding;
/// Implements several traits for byte-based newtypes.
/// Implements:
/// - core::fmt::LowerHex
/// - core::fmt::UpperHex
/// - core::fmt::Display
/// - core::str::FromStr
macro_rules! impl_bytes_newtype {
/// 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 {
/// 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.
pub fn from_hex(s: &str) -> Result<Self, hex::HexToArrayError> {
Ok($t($crate::hex::FromHex::from_hex(s)?))
@ -186,7 +173,7 @@ macro_rules! impl_bytes_newtype {
}
};
}
pub(crate) use impl_bytes_newtype;
pub(crate) use impl_array_newtype_stringify;
#[rustfmt::skip]
macro_rules! impl_hashencode {

View File

@ -185,7 +185,7 @@ impl Serialize for KeySource {
fn serialize(&self) -> Vec<u8> {
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() {
rv.append(&mut serialize(&u32::from(*cnum)))

View File

@ -8,6 +8,34 @@
macro_rules! impl_array_newtype {
($thing:ident, $ty:ty, $len:literal) => {
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.
#[inline]
pub fn as_ptr(&self) -> *const $ty {