bitcoin_internals/
macros.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Various macros used by the Rust Bitcoin ecosystem.
4
5/// Implements standard array methods for a given wrapper type.
6#[macro_export]
7macro_rules! impl_array_newtype {
8    ($thing:ident, $ty:ty, $len:literal) => {
9        impl $thing {
10            /// Creates `Self` by wrapping `bytes`.
11            #[inline]
12            pub fn from_byte_array(bytes: [u8; $len]) -> Self { Self(bytes) }
13
14            /// Returns a reference the underlying byte array.
15            #[inline]
16            pub fn as_byte_array(&self) -> &[u8; $len] { &self.0 }
17
18            /// Returns the underlying byte array.
19            #[inline]
20            pub fn to_byte_array(self) -> [u8; $len] {
21                // We rely on `Copy` being implemented for $thing so conversion
22                // methods use the correct Rust naming conventions.
23                fn check_copy<T: Copy>() {}
24                check_copy::<$thing>();
25
26                self.0
27            }
28
29            /// Returns a slice of the underlying bytes.
30            #[inline]
31            pub fn as_bytes(&self) -> &[u8] { &self.0 }
32
33            /// Copies the underlying bytes into a new `Vec`.
34            #[cfg(feature = "alloc")]
35            #[inline]
36            pub fn to_bytes(&self) -> alloc::vec::Vec<u8> { self.0.to_vec() }
37
38            /// Converts the object to a raw pointer.
39            #[inline]
40            pub fn as_ptr(&self) -> *const $ty {
41                let &$thing(ref dat) = self;
42                dat.as_ptr()
43            }
44
45            /// Converts the object to a mutable raw pointer.
46            #[inline]
47            pub fn as_mut_ptr(&mut self) -> *mut $ty {
48                let &mut $thing(ref mut dat) = self;
49                dat.as_mut_ptr()
50            }
51
52            /// Returns the length of the object as an array.
53            #[inline]
54            pub fn len(&self) -> usize { $len }
55
56            /// Returns whether the object, as an array, is empty. Always false.
57            #[inline]
58            pub fn is_empty(&self) -> bool { false }
59        }
60
61        impl<'a> core::convert::From<[$ty; $len]> for $thing {
62            fn from(data: [$ty; $len]) -> Self { $thing(data) }
63        }
64
65        impl<'a> core::convert::From<&'a [$ty; $len]> for $thing {
66            fn from(data: &'a [$ty; $len]) -> Self { $thing(*data) }
67        }
68
69        impl<'a> core::convert::TryFrom<&'a [$ty]> for $thing {
70            type Error = core::array::TryFromSliceError;
71
72            fn try_from(data: &'a [$ty]) -> core::result::Result<Self, Self::Error> {
73                use core::convert::TryInto;
74
75                Ok($thing(data.try_into()?))
76            }
77        }
78
79        impl AsRef<[$ty; $len]> for $thing {
80            fn as_ref(&self) -> &[$ty; $len] { &self.0 }
81        }
82
83        impl AsMut<[$ty; $len]> for $thing {
84            fn as_mut(&mut self) -> &mut [$ty; $len] { &mut self.0 }
85        }
86
87        impl AsRef<[$ty]> for $thing {
88            fn as_ref(&self) -> &[$ty] { &self.0 }
89        }
90
91        impl AsMut<[$ty]> for $thing {
92            fn as_mut(&mut self) -> &mut [$ty] { &mut self.0 }
93        }
94
95        impl core::borrow::Borrow<[$ty; $len]> for $thing {
96            fn borrow(&self) -> &[$ty; $len] { &self.0 }
97        }
98
99        impl core::borrow::BorrowMut<[$ty; $len]> for $thing {
100            fn borrow_mut(&mut self) -> &mut [$ty; $len] { &mut self.0 }
101        }
102
103        // The following two are valid because `[T; N]: Borrow<[T]>`
104        impl core::borrow::Borrow<[$ty]> for $thing {
105            fn borrow(&self) -> &[$ty] { &self.0 }
106        }
107
108        impl core::borrow::BorrowMut<[$ty]> for $thing {
109            fn borrow_mut(&mut self) -> &mut [$ty] { &mut self.0 }
110        }
111
112        impl<I> core::ops::Index<I> for $thing
113        where
114            [$ty]: core::ops::Index<I>,
115        {
116            type Output = <[$ty] as core::ops::Index<I>>::Output;
117
118            #[inline]
119            fn index(&self, index: I) -> &Self::Output { &self.0[index] }
120        }
121    };
122}
123
124/// Implements `Debug` by calling through to `Display`.
125#[macro_export]
126macro_rules! debug_from_display {
127    ($thing:ident) => {
128        impl core::fmt::Debug for $thing {
129            fn fmt(
130                &self,
131                f: &mut core::fmt::Formatter,
132            ) -> core::result::Result<(), core::fmt::Error> {
133                core::fmt::Display::fmt(self, f)
134            }
135        }
136    };
137}
138
139/// Asserts a boolean expression at compile time.
140#[macro_export]
141macro_rules! const_assert {
142    ($x:expr $(; $message:expr)?) => {
143        const _: () = {
144            if !$x {
145                // We can't use formatting in const, only concating literals.
146                panic!(concat!("assertion ", stringify!($x), " failed" $(, ": ", $message)?))
147            }
148        };
149    }
150}
151
152/// Derives `From<core::convert::Infallible>` for the given type.
153///
154/// Supports types with arbitrary combinations of lifetimes and type parameters.
155///
156/// Note: Paths are not supported (for ex. impl_from_infallible!(Hello<D: std::fmt::Display>).
157///
158/// # Examples
159///
160/// ```rust
161/// # #[allow(unused)]
162/// # fn main() {
163/// # use core::fmt::{Display, Debug};
164/// use bitcoin_internals::impl_from_infallible;
165///
166/// enum AlphaEnum { Item }
167/// impl_from_infallible!(AlphaEnum);
168///
169/// enum BetaEnum<'b> { Item(&'b usize) }
170/// impl_from_infallible!(BetaEnum<'b>);
171///
172/// enum GammaEnum<T> { Item(T) }
173/// impl_from_infallible!(GammaEnum<T>);
174///
175/// enum DeltaEnum<'b, 'a: 'static + 'b, T: 'a, D: Debug + Display + 'a> {
176///     Item((&'b usize, &'a usize, T, D))
177/// }
178/// impl_from_infallible!(DeltaEnum<'b, 'a: 'static + 'b, T: 'a, D: Debug + Display + 'a>);
179///
180/// struct AlphaStruct;
181/// impl_from_infallible!(AlphaStruct);
182///
183/// struct BetaStruct<'b>(&'b usize);
184/// impl_from_infallible!(BetaStruct<'b>);
185///
186/// struct GammaStruct<T>(T);
187/// impl_from_infallible!(GammaStruct<T>);
188///
189/// struct DeltaStruct<'b, 'a: 'static + 'b, T: 'a, D: Debug + Display + 'a> {
190///     hello: &'a T,
191///     what: &'b D,
192/// }
193/// impl_from_infallible!(DeltaStruct<'b, 'a: 'static + 'b, T: 'a, D: Debug + Display + 'a>);
194/// # }
195/// ```
196///
197/// See <https://stackoverflow.com/a/61189128> for more information about this macro.
198#[macro_export]
199macro_rules! impl_from_infallible {
200    ( $name:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ) => {
201        impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)?
202            From<core::convert::Infallible>
203        for $name
204            $(< $( $lt ),+ >)?
205        {
206            fn from(never: core::convert::Infallible) -> Self { match never {} }
207        }
208    }
209}
210
211/// Adds an implementation of `pub fn to_hex(&self) -> String` if `alloc` feature is enabled.
212///
213/// The added function allocates a `String` then calls through to [`core::fmt::LowerHex`].
214///
215/// Note: Calling this macro assumes that the calling crate has an `alloc` feature that also activates the
216/// `alloc` crate. Calling this macro without the `alloc` feature enabled is a no-op.
217#[macro_export]
218macro_rules! impl_to_hex_from_lower_hex {
219    ($t:ident, $hex_len_fn:expr) => {
220        impl $t {
221            /// Gets the hex representation of this type
222            #[cfg(feature = "alloc")]
223            pub fn to_hex(&self) -> alloc::string::String {
224                use core::fmt::Write;
225
226                let mut hex_string = alloc::string::String::with_capacity($hex_len_fn(self));
227                write!(&mut hex_string, "{:x}", self).expect("writing to string shouldn't fail");
228
229                hex_string
230            }
231        }
232    };
233}