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}