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}