Skip to content

Commit 3e28070

Browse files
committed
Duplicate impl_array_newtype
The two crates `secp256k1` and `secp256k1-sys` serve very different purposes, having a macro defined in one that is used in both makes it hard to get nuanced things correct in the macro, for example the comparison implementations (`Ord`, `PartialEq` etc.) are semantically different in each crate. In an effort to decouple `secp256k1` and `secp256k1-sys` duplicate the `impl_array_newtype` macro.
1 parent 6358903 commit 3e28070

File tree

4 files changed

+112
-5
lines changed

4 files changed

+112
-5
lines changed

src/key.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ use core::{fmt, ptr, str};
2424
use serde::ser::SerializeTuple;
2525

2626
use crate::ffi::types::c_uint;
27-
use crate::ffi::{self, impl_array_newtype, CPtr};
27+
use crate::ffi::{self, CPtr};
2828
#[cfg(all(feature = "global-context", feature = "rand-std"))]
2929
use crate::schnorr;
3030
use crate::Error::{self, InvalidPublicKey, InvalidPublicKeySum, InvalidSecretKey};
31-
use crate::{constants, from_hex, Scalar, Secp256k1, Signing, Verification};
31+
use crate::{constants, from_hex, impl_array_newtype, Scalar, Secp256k1, Signing, Verification};
3232
#[cfg(feature = "global-context")]
3333
use crate::{ecdsa, Message, SECP256K1};
3434
#[cfg(feature = "bitcoin-hashes")]

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ pub use serde;
200200

201201
pub use crate::context::*;
202202
use crate::ffi::types::AlignedType;
203-
use crate::ffi::{impl_array_newtype, CPtr};
203+
use crate::ffi::CPtr;
204204
#[cfg(feature = "bitcoin-hashes")]
205205
use crate::hashes::Hash;
206206
pub use crate::key::{PublicKey, SecretKey, *};

src/macros.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,113 @@
1313
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
1414
//
1515

16+
/// Implement methods and traits for types that contain an inner array.
17+
#[macro_export]
18+
macro_rules! impl_array_newtype {
19+
($thing:ident, $ty:ty, $len:expr) => {
20+
impl Copy for $thing {}
21+
22+
impl $thing {
23+
/// Converts the object to a raw pointer for FFI interfacing.
24+
#[inline]
25+
pub fn as_ptr(&self) -> *const $ty {
26+
let &$thing(ref dat) = self;
27+
dat.as_ptr()
28+
}
29+
30+
/// Converts the object to a mutable raw pointer for FFI interfacing.
31+
#[inline]
32+
pub fn as_mut_ptr(&mut self) -> *mut $ty {
33+
let &mut $thing(ref mut dat) = self;
34+
dat.as_mut_ptr()
35+
}
36+
37+
/// Returns the length of the object as an array.
38+
#[inline]
39+
pub fn len(&self) -> usize { $len }
40+
41+
/// Returns whether the object as an array is empty.
42+
#[inline]
43+
pub fn is_empty(&self) -> bool { false }
44+
}
45+
46+
impl AsRef<[$ty; $len]> for $thing {
47+
#[inline]
48+
/// Gets a reference to the underlying array
49+
fn as_ref(&self) -> &[$ty; $len] {
50+
let &$thing(ref dat) = self;
51+
dat
52+
}
53+
}
54+
55+
impl PartialEq for $thing {
56+
#[inline]
57+
fn eq(&self, other: &$thing) -> bool {
58+
&self[..] == &other[..]
59+
}
60+
}
61+
62+
impl Eq for $thing {}
63+
64+
impl ::core::hash::Hash for $thing {
65+
fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
66+
(&self[..]).hash(state)
67+
}
68+
}
69+
70+
impl PartialOrd for $thing {
71+
#[inline]
72+
fn partial_cmp(&self, other: &$thing) -> Option<core::cmp::Ordering> {
73+
self[..].partial_cmp(&other[..])
74+
}
75+
}
76+
77+
impl Ord for $thing {
78+
#[inline]
79+
fn cmp(&self, other: &$thing) -> core::cmp::Ordering {
80+
self[..].cmp(&other[..])
81+
}
82+
}
83+
84+
impl Clone for $thing {
85+
#[inline]
86+
fn clone(&self) -> $thing {
87+
let &$thing(ref dat) = self;
88+
$thing(dat.clone())
89+
}
90+
}
91+
92+
impl<I> core::ops::Index<I> for $thing
93+
where
94+
[$ty]: core::ops::Index<I>,
95+
{
96+
type Output = <[$ty] as core::ops::Index<I>>::Output;
97+
98+
#[inline]
99+
fn index(&self, index: I) -> &Self::Output { &self.0[index] }
100+
}
101+
102+
impl $crate::CPtr for $thing {
103+
type Target = $ty;
104+
fn as_c_ptr(&self) -> *const Self::Target {
105+
if self.is_empty() {
106+
core::ptr::null()
107+
} else {
108+
self.as_ptr()
109+
}
110+
}
111+
112+
fn as_mut_c_ptr(&mut self) -> *mut Self::Target {
113+
if self.is_empty() {
114+
core::ptr::null::<Self::Target>() as *mut _
115+
} else {
116+
self.as_mut_ptr()
117+
}
118+
}
119+
}
120+
}
121+
}
122+
16123
macro_rules! impl_pretty_debug {
17124
($thing:ident) => {
18125
impl core::fmt::Debug for $thing {

src/schnorr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ use core::{fmt, ptr, str};
77
#[cfg(any(test, feature = "rand"))]
88
use rand::{CryptoRng, Rng};
99

10-
use crate::ffi::{self, impl_array_newtype, CPtr};
10+
use crate::ffi::{self, CPtr};
1111
use crate::key::{KeyPair, XOnlyPublicKey};
1212
#[cfg(all(feature = "global-context", feature = "rand-std"))]
1313
use crate::SECP256K1;
14-
use crate::{constants, from_hex, Error, Message, Secp256k1, Signing, Verification};
14+
use crate::{constants, from_hex, impl_array_newtype, Error, Message, Secp256k1, Signing, Verification};
1515

1616
/// Represents a Schnorr signature.
1717
pub struct Signature([u8; constants::SCHNORR_SIGNATURE_SIZE]);

0 commit comments

Comments
 (0)