secp256k1/
macros.rs

1// SPDX-License-Identifier: CC0-1.0
2
3/// Implement methods and traits for types that contain an inner array.
4#[macro_export]
5macro_rules! impl_array_newtype {
6    ($thing:ident, $ty:ty, $len:expr) => {
7        impl AsRef<[$ty; $len]> for $thing {
8            #[inline]
9            /// Gets a reference to the underlying array
10            fn as_ref(&self) -> &[$ty; $len] {
11                let &$thing(ref dat) = self;
12                dat
13            }
14        }
15
16        impl<I> core::ops::Index<I> for $thing
17        where
18            [$ty]: core::ops::Index<I>,
19        {
20            type Output = <[$ty] as core::ops::Index<I>>::Output;
21
22            #[inline]
23            fn index(&self, index: I) -> &Self::Output { &self.0[index] }
24        }
25
26        impl $crate::ffi::CPtr for $thing {
27            type Target = $ty;
28
29            fn as_c_ptr(&self) -> *const Self::Target {
30                let &$thing(ref dat) = self;
31                dat.as_ptr()
32            }
33
34            fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
35                let &mut $thing(ref mut dat) = self;
36                dat.as_mut_ptr()
37            }
38        }
39    };
40}
41
42macro_rules! impl_pretty_debug {
43    ($thing:ident) => {
44        impl core::fmt::Debug for $thing {
45            fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
46                write!(f, "{}(", stringify!($thing))?;
47                for i in &self[..] {
48                    write!(f, "{:02x}", i)?;
49                }
50                f.write_str(")")
51            }
52        }
53    };
54}
55
56macro_rules! impl_non_secure_erase {
57    ($thing:ident, $target:tt, $value:expr) => {
58        impl $thing {
59            /// Attempts to erase the contents of the underlying array.
60            ///
61            /// Note, however, that the compiler is allowed to freely copy or move the
62            /// contents of this array to other places in memory. Preventing this behavior
63            /// is very subtle. For more discussion on this, please see the documentation
64            /// of the [`zeroize`](https://docs.rs/zeroize) crate.
65            #[inline]
66            pub fn non_secure_erase(&mut self) {
67                secp256k1_sys::non_secure_erase_impl(&mut self.$target, $value);
68            }
69        }
70    };
71}
72
73/// Formats error. If `std` feature is OFF appends error source (delimited by `: `). We do this
74/// because `e.source()` is only available in std builds, without this macro the error source is
75/// lost for no-std builds.
76macro_rules! write_err {
77    ($writer:expr, $string:literal $(, $args:expr),*; $source:expr) => {
78        {
79            #[cfg(feature = "std")]
80            {
81                let _ = &$source;   // Prevents clippy warnings.
82                write!($writer, $string $(, $args)*)
83            }
84            #[cfg(not(feature = "std"))]
85            {
86                write!($writer, concat!($string, ": {}") $(, $args)*, $source)
87            }
88        }
89    }
90}
91
92/// Implements fast unstable comparison methods for `$ty`.
93macro_rules! impl_fast_comparisons {
94    ($ty:ident) => {
95        impl $ty {
96            /// Like `cmp::Cmp` but faster and with no guarantees across library versions.
97            ///
98            /// The `Cmp` implementation for FFI types is stable but slow because it first
99            /// serializes `self` and `other` before comparing them. This function provides a faster
100            /// comparison if you know that your types come from the same library version.
101            pub fn cmp_fast_unstable(&self, other: &Self) -> core::cmp::Ordering {
102                self.0.cmp_fast_unstable(&other.0)
103            }
104
105            /// Like `cmp::Eq` but faster and with no guarantees across library versions.
106            ///
107            /// The `Eq` implementation for FFI types is stable but slow because it first serializes
108            /// `self` and `other` before comparing them. This function provides a faster equality
109            /// check if you know that your types come from the same library version.
110            pub fn eq_fast_unstable(&self, other: &Self) -> bool {
111                self.0.eq_fast_unstable(&other.0)
112            }
113        }
114    };
115}