bitcoin_internals/
macros.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Various macros used by the Rust Bitcoin ecosystem.
4
5/// Asserts a boolean expression at compile time.
6#[macro_export]
7macro_rules! const_assert {
8    ($x:expr $(; $message:expr)?) => {
9        const _: () = {
10            if !$x {
11                // We can't use formatting in const, only concatenating literals.
12                panic!(concat!("assertion ", stringify!($x), " failed" $(, ": ", $message)?))
13            }
14        };
15    }
16}
17
18/// Adds an implementation of `pub fn to_hex(&self) -> String`.
19///
20/// The added function allocates a `String` then calls through to [`core::fmt::LowerHex`].
21#[macro_export]
22macro_rules! impl_to_hex_from_lower_hex {
23    ($t:ident, $hex_len_fn:expr) => {
24        impl $t {
25            /// Gets the hex representation of this type
26            pub fn to_hex(&self) -> alloc::string::String {
27                use core::fmt::Write;
28
29                let mut hex_string = alloc::string::String::with_capacity($hex_len_fn(self));
30                write!(&mut hex_string, "{:x}", self).expect("writing to string shouldn't fail");
31
32                hex_string
33            }
34        }
35    };
36}
37
38/// Constructs a transparent wrapper around an inner type and soundly implements reference casts.
39///
40/// This macro takes care of several issues related to newtypes that need to allow casting their
41/// inner types to themselves:
42///
43/// * It makes sure to put repr(transparent) on the type
44/// * It optionally implements conversions from `&`, `&mut`, `Box`, `Rc`, `Arc`
45/// * It makes sure to put `#[inline]` on all of these conversions since they are trivial
46/// * It makes sure the reference cast is const
47/// * It makes sure the `Arc` conversion is conditioned on `target_has_atomic = "ptr"`
48///
49/// Usage: just type the struct inside the macro as you would implementing it manually except leave
50/// `#[repr(transparent)]` out. Then add an impl block for the just-defined type containing function
51/// declarations that take a reference/smart pointer to `_` (use literal underscore; e.g. `&_` for
52/// shared references) and return `Self` behind the appropriate "pointer" type. Do not write the
53/// body, just semicolon.
54///
55/// The `alloc` types MUST NOT have import paths and don't need imports.
56#[macro_export]
57macro_rules! transparent_newtype {
58    (
59        $(#[$($struct_attr:tt)*])*
60        $vis:vis struct $newtype:tt$(<$gen:ident $(= $default:ty)?>)?($($fields:tt)+) $(where $($where_ty:ty: $bound:path),* $(,)?)?;
61
62        impl$(<$gen2:tt>)? $newtype2:ident$(<$gen3:tt>)? {
63            $(
64                $(#[$($fn_attr:tt)*])*
65                $fn_vis:vis $(const)? fn $fn:ident($fn_arg_name:ident: $($fn_arg_ty:tt)+) -> $fn_ret_ty:ty;
66            )*
67        }
68    ) => {
69        $crate::_check_tts_eq!($newtype2, $newtype, "the type name in the impl block doesn't match the struct name");
70        $(
71            // WARNING: renaming has to be disabled for soundness!
72            // If it weren't it'd be possible to make the type inside struct not match the one passed
73            // to functions. In principle we could also omit the generics but that'd be confusing for
74            // readers.
75            $crate::_check_tts_eq!($gen2, $gen, "the name of the left generic parameter in impl block doesn't match the one on struct");
76            $crate::_check_tts_eq!($gen3, $gen, "the name of the right generic parameter in impl block doesn't match the one on struct");
77        )?
78        $(#[$($struct_attr)*])*
79        #[repr(transparent)]
80        $vis struct $newtype$(<$gen $(= $default)?>)?($($fields)+) $(where $($where_ty: $bound),*)?;
81
82        impl$(<$gen2>)? $newtype$(<$gen3>)? $(where $($where_ty: $bound),*)? {
83            $crate::_transparent_ref_conversions! {
84                $crate::_transparent_newtype_inner_type!($($fields)+);
85                $(
86                    $(#[$($fn_attr)*])*
87                    $fn_vis fn $fn($fn_arg_name: $($fn_arg_ty)+) -> $fn_ret_ty;
88                )+
89            }
90        }
91    };
92}
93
94#[doc(hidden)]
95#[macro_export]
96macro_rules! _transparent_ref_conversions {
97    (
98        $inner:ty;
99        $(
100            $(#[$($fn_attr:tt)*])*
101            $fn_vis:vis $(const)? fn $fn:ident($fn_arg_name:ident: $($fn_arg_ty:tt)+) -> $fn_ret_ty:ty;
102        )+
103    ) => {
104        $(
105            $crate::_transparent_ref_conversion! {
106                $inner;
107                $(#[$($fn_attr)*])*
108                $fn_vis fn $fn($fn_arg_name: $($fn_arg_ty)+) -> $fn_ret_ty;
109            }
110        )+
111    }
112}
113
114#[doc(hidden)]
115#[macro_export]
116macro_rules! _transparent_ref_conversion {
117    (
118        $inner:ty;
119        $(#[$($from_ref_attr:tt)*])*
120        $from_ref_vis:vis fn $from_ref:ident($from_ref_arg_name:ident: &_) -> $fn_ret_ty:ty;
121    ) => {
122        #[inline]
123        $(#[$($from_ref_attr)*])*
124        $from_ref_vis const fn $from_ref($from_ref_arg_name: &$inner) -> &Self {
125            // SAFETY: the pointer is created by casting a pointer that is pointing to an object
126            // with the same layout and validity invariants and the previous pointer was created
127            // directly from a reference. (Notice repr(transparent).)
128            // The lifetime of the input reference matches the lifetime of the returned reference.
129            unsafe { &*($from_ref_arg_name as *const $inner as *const Self) }
130        }
131    };
132    (
133        $inner:ty;
134        $(#[$($from_mut_attr:tt)*])*
135        $from_mut_vis:vis fn $from_mut:ident($from_mut_arg_name:ident: &mut _) -> $fn_ret_ty:ty;
136    ) => {
137        #[inline]
138        $(#[$($from_mut_attr)*])*
139        $from_mut_vis fn $from_mut($from_mut_arg_name: &mut $inner) -> &mut Self {
140            // SAFETY: the pointer is created by casting a pointer that is pointing to an object
141            // with the same layout and validity invariants and the previous pointer was created
142            // directly from a reference. (Notice repr(transparent).)
143            // The lifetime of the input reference matches the lifetime of the returned reference.
144            unsafe { &mut *($from_mut_arg_name as *mut $inner as *mut Self) }
145        }
146    };
147    (
148        $inner:ty;
149        $(#[$($from_box_attr:tt)*])*
150        $from_box_vis:vis fn $from_box:ident($from_box_arg_name:ident: Box<_>) -> $fn_ret_ty:ty;
151    ) => {
152        $crate::_emit_alloc! {
153            $(#[$($from_box_attr)*])*
154            #[inline]
155            $from_box_vis fn $from_box($from_box_arg_name: $crate::_export::alloc::boxed::Box<$inner>) -> $crate::_export::alloc::boxed::Box<Self> {
156                let ptr = $crate::_export::alloc::boxed::Box::into_raw($from_box_arg_name);
157                // SAFETY: the pointer is created by casting a pointer that is pointing to an object
158                // with the same layout and validity invariants and the previous pointer was created
159                // directly from box. (Notice repr(transparent).)
160                unsafe { $crate::_export::alloc::boxed::Box::from_raw(ptr as *mut Self) }
161            }
162        }
163    };
164
165    (
166        $inner:ty;
167        $(#[$($from_rc_attr:tt)*])*
168        $from_rc_vis:vis fn $from_rc:ident($from_rc_arg_name:ident: Rc<_>) -> $fn_ret_ty:ty;
169    ) => {
170        $crate::_emit_alloc! {
171            $(#[$($from_rc_attr)*])*
172            #[inline]
173            $from_rc_vis fn $from_rc($from_rc_arg_name: $crate::_export::alloc::rc::Rc<$inner>) -> $crate::_export::alloc::rc::Rc<Self> {
174                let ptr = $crate::_export::alloc::rc::Rc::into_raw($from_rc_arg_name);
175                // SAFETY: the pointer is created by casting a pointer that is pointing to an object
176                // with the same layout and validity invariants and the previous pointer was created
177                // directly from box. (Notice repr(transparent).)
178                unsafe { $crate::_export::alloc::rc::Rc::from_raw(ptr as *mut Self) }
179            }
180        }
181    };
182
183    (
184        $inner:ty;
185        $(#[$($from_arc_attr:tt)*])*
186        $from_arc_vis:vis fn $from_arc:ident($from_arc_arg_name:ident: Arc<_>) -> $fn_ret_ty:ty;
187    ) => {
188        $crate::_emit_alloc! {
189            $(#[$($from_arc_attr)*])*
190            #[cfg(target_has_atomic = "ptr")]
191            #[inline]
192            $from_arc_vis fn $from_arc($from_arc_arg_name: $crate::_export::alloc::sync::Arc<$inner>) -> $crate::_export::alloc::sync::Arc<Self> {
193                let ptr = $crate::_export::alloc::sync::Arc::into_raw($from_arc_arg_name);
194                // SAFETY: the pointer is created by casting a pointer that is pointing to an object
195                // with the same layout and validity invariants and the previous pointer was created
196                // directly from box. (Notice repr(transparent).)
197                unsafe { $crate::_export::alloc::sync::Arc::from_raw(ptr as *mut Self) }
198            }
199        }
200    }
201}
202
203#[doc(hidden)]
204#[macro_export]
205macro_rules! _check_tts_eq {
206    ($left:tt, $right:tt, $message:literal) => {
207        macro_rules! token_eq {
208            ($right) => {};
209            ($any:tt) => {
210                compile_error!($message)
211            };
212        }
213        token_eq!($left);
214    };
215}
216
217#[doc(hidden)]
218#[macro_export]
219macro_rules! _transparent_newtype_inner_type {
220    ($(#[$($field_attr:tt)*])* $inner:ty) => {
221        $inner
222    };
223    ($(#[$($phantom_attr:tt)*])* PhantomData<$phantom:ty>, $(#[$($field_attr:tt)*])* $inner:ty) => {
224        $inner
225    };
226}
227
228/// Emits given tokens only if the `alloc` feature **in this crate** is enabled.
229///
230/// (The feature is currently enabled.)
231#[cfg(feature = "alloc")]
232#[doc(hidden)]
233#[macro_export]
234macro_rules! _emit_alloc {
235    ($($tokens:tt)*) => { $($tokens)* };
236}
237
238/// Emits given tokens only if the `alloc` feature **in this crate** is enabled.
239///
240/// (The feature is currently disabled.)
241#[cfg(not(feature = "alloc"))]
242#[doc(hidden)]
243#[macro_export]
244macro_rules! _emit_alloc {
245    ($($tokens:tt)*) => {};
246}
247
248/// Implements standard array methods for a given wrapper type.
249#[macro_export]
250macro_rules! impl_array_newtype {
251    ($thing:ident, $ty:ty, $len:literal) => {
252        impl $thing {
253            /// Constructs a new `Self` by wrapping `bytes`.
254            #[inline]
255            pub fn from_byte_array(bytes: [u8; $len]) -> Self { Self(bytes) }
256
257            /// Returns a reference the underlying byte array.
258            #[inline]
259            pub fn as_byte_array(&self) -> &[u8; $len] { &self.0 }
260
261            /// Returns the underlying byte array.
262            #[inline]
263            pub fn to_byte_array(self) -> [u8; $len] {
264                // We rely on `Copy` being implemented for $thing so conversion
265                // methods use the correct Rust naming conventions.
266                fn check_copy<T: Copy>() {}
267                check_copy::<$thing>();
268
269                self.0
270            }
271
272            /// Copies the underlying bytes into a new `Vec`.
273            #[inline]
274            pub fn to_vec(self) -> alloc::vec::Vec<u8> { self.0.to_vec() }
275
276            /// Returns a slice of the underlying bytes.
277            #[inline]
278            pub fn as_bytes(&self) -> &[u8] { &self.0 }
279
280            /// Converts the object to a raw pointer.
281            #[inline]
282            pub fn as_ptr(&self) -> *const $ty {
283                let &$thing(ref dat) = self;
284                dat.as_ptr()
285            }
286
287            /// Converts the object to a mutable raw pointer.
288            #[inline]
289            pub fn as_mut_ptr(&mut self) -> *mut $ty {
290                let &mut $thing(ref mut dat) = self;
291                dat.as_mut_ptr()
292            }
293
294            /// Returns the length of the object as an array.
295            #[inline]
296            pub fn len(&self) -> usize { $len }
297
298            /// Returns whether the object, as an array, is empty. Always false.
299            #[inline]
300            pub fn is_empty(&self) -> bool { false }
301        }
302
303        impl<'a> core::convert::From<[$ty; $len]> for $thing {
304            fn from(data: [$ty; $len]) -> Self { $thing(data) }
305        }
306
307        impl<'a> core::convert::From<&'a [$ty; $len]> for $thing {
308            fn from(data: &'a [$ty; $len]) -> Self { $thing(*data) }
309        }
310
311        impl<'a> core::convert::TryFrom<&'a [$ty]> for $thing {
312            type Error = core::array::TryFromSliceError;
313
314            fn try_from(data: &'a [$ty]) -> core::result::Result<Self, Self::Error> {
315                use core::convert::TryInto;
316
317                Ok($thing(data.try_into()?))
318            }
319        }
320
321        impl AsRef<[$ty; $len]> for $thing {
322            fn as_ref(&self) -> &[$ty; $len] { &self.0 }
323        }
324
325        impl AsMut<[$ty; $len]> for $thing {
326            fn as_mut(&mut self) -> &mut [$ty; $len] { &mut self.0 }
327        }
328
329        impl AsRef<[$ty]> for $thing {
330            fn as_ref(&self) -> &[$ty] { &self.0 }
331        }
332
333        impl AsMut<[$ty]> for $thing {
334            fn as_mut(&mut self) -> &mut [$ty] { &mut self.0 }
335        }
336
337        impl core::borrow::Borrow<[$ty; $len]> for $thing {
338            fn borrow(&self) -> &[$ty; $len] { &self.0 }
339        }
340
341        impl core::borrow::BorrowMut<[$ty; $len]> for $thing {
342            fn borrow_mut(&mut self) -> &mut [$ty; $len] { &mut self.0 }
343        }
344
345        // The following two are valid because `[T; N]: Borrow<[T]>`
346        impl core::borrow::Borrow<[$ty]> for $thing {
347            fn borrow(&self) -> &[$ty] { &self.0 }
348        }
349
350        impl core::borrow::BorrowMut<[$ty]> for $thing {
351            fn borrow_mut(&mut self) -> &mut [$ty] { &mut self.0 }
352        }
353
354        impl<I> core::ops::Index<I> for $thing
355        where
356            [$ty]: core::ops::Index<I>,
357        {
358            type Output = <[$ty] as core::ops::Index<I>>::Output;
359
360            #[inline]
361            fn index(&self, index: I) -> &Self::Output { &self.0[index] }
362        }
363    };
364}