Skip to content

Commit ab4320f

Browse files
Merge pull request #100 from elichai/master
Add no-std support
2 parents 90faf43 + dfcf74f commit ab4320f

File tree

8 files changed

+150
-42
lines changed

8 files changed

+150
-42
lines changed

.travis.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ script:
2424
- cargo build --verbose --features=rand
2525
- cargo test --verbose --features=rand
2626
- cargo test --verbose --features="rand serde"
27+
- cargo build --verbose --no-default-features
28+
- cargo build --verbose --no-default-features --features="serde"
29+
- cargo build --verbose --no-default-features --features="rand"
30+
- cargo build --verbose --no-default-features --features="rand serde"
2731
- cargo build --verbose
2832
- cargo test --verbose
2933
- cargo build --release

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ path = "src/lib.rs"
2727

2828
[features]
2929
unstable = []
30-
default = []
30+
default = ["std"]
3131
fuzztarget = []
32+
std = []
3233

3334
[dev-dependencies]
3435
rand = "0.6"
@@ -38,7 +39,9 @@ serde_test = "1.0"
3839
[dependencies.rand]
3940
version = "0.6"
4041
optional = true
42+
default-features = false
4143

4244
[dependencies.serde]
4345
version = "1.0"
4446
optional = true
47+
default-features = false

src/ecdh.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
//! Support for shared secret computations
1717
//!
1818
19-
use std::{ops, ptr};
19+
use core::{ops, ptr};
2020

2121
use key::{SecretKey, PublicKey};
2222
use ffi;

src/ffi.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616
//! # FFI bindings
1717
//! Direct bindings to the underlying C library functions. These should
1818
//! not be needed for most users.
19-
use std::mem;
20-
use std::hash;
21-
use std::os::raw::{c_int, c_uchar, c_uint, c_void};
19+
use core::{mem, hash};
20+
use types::*;
21+
// use std::os::raw::{c_int, c_uchar, c_uint, c_void};
22+
2223

2324
/// Flag for context to enable no precomputation
2425
pub const SECP256K1_START_NONE: c_uint = 1;

src/key.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
1818
#[cfg(any(test, feature = "rand"))] use rand::Rng;
1919

20-
use std::{fmt, mem, str};
20+
use core::{fmt, mem, str};
2121

2222
use super::{from_hex, Secp256k1};
2323
use super::Error::{self, InvalidPublicKey, InvalidSecretKey};

src/lib.rs

Lines changed: 97 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -133,26 +133,30 @@
133133
#![cfg_attr(feature = "dev", feature(plugin))]
134134
#![cfg_attr(feature = "dev", plugin(clippy))]
135135

136+
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
136137
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
137138
#[cfg(all(test, feature = "unstable"))] extern crate test;
138139
#[cfg(any(test, feature = "rand"))] pub extern crate rand;
139140
#[cfg(any(test))] extern crate rand_core;
140141
#[cfg(feature = "serde")] pub extern crate serde;
141142
#[cfg(all(test, feature = "serde"))] extern crate serde_test;
142-
143-
use std::{error, fmt, ptr, str};
144143
#[cfg(any(test, feature = "rand"))] use rand::Rng;
144+
#[cfg(any(test, feature = "std"))] extern crate core;
145+
146+
use core::{fmt, ptr, str};
145147

146148
#[macro_use]
147149
mod macros;
150+
mod types;
148151
pub mod constants;
149152
pub mod ecdh;
150153
pub mod ffi;
151154
pub mod key;
152155

153156
pub use key::SecretKey;
154157
pub use key::PublicKey;
155-
use std::marker::PhantomData;
158+
use core::marker::PhantomData;
159+
use core::ops::Deref;
156160

157161
/// A tag used for recovering the public key from a compact signature
158162
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -162,6 +166,13 @@ pub struct RecoveryId(i32);
162166
#[derive(Copy, Clone, PartialEq, Eq)]
163167
pub struct Signature(ffi::Signature);
164168

169+
/// A DER serialized Signature
170+
#[derive(Copy, Clone)]
171+
pub struct SerializedSignature {
172+
data: [u8; 72],
173+
len: usize,
174+
}
175+
165176
impl fmt::Debug for Signature {
166177
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
167178
fmt::Display::fmt(self, f)
@@ -228,6 +239,40 @@ pub fn to_i32(self) -> i32 {
228239
}
229240
}
230241

242+
impl SerializedSignature {
243+
/// Get a pointer to the underlying data with the specified capacity.
244+
pub(crate) fn get_data_mut_ptr(&mut self) -> *mut u8 {
245+
self.data.as_mut_ptr()
246+
}
247+
248+
/// Get the capacity of the underlying data buffer.
249+
pub fn capacity(&self) -> usize {
250+
self.data.len()
251+
}
252+
253+
/// Get the len of the used data.
254+
pub fn len(&self) -> usize {
255+
self.len
256+
}
257+
258+
/// Set the length of the object.
259+
pub(crate) fn set_len(&mut self, len: usize) {
260+
self.len = len;
261+
}
262+
263+
/// Convert the serialized signature into the Signature struct.
264+
/// (This DER deserializes it)
265+
pub fn to_signature(&self) -> Result<Signature, Error> {
266+
Signature::from_der(&self)
267+
}
268+
269+
/// Create a SerializedSignature from a Signature.
270+
/// (this DER serializes it)
271+
pub fn from_signature(sig: &Signature) -> SerializedSignature {
272+
sig.serialize_der()
273+
}
274+
}
275+
231276
impl Signature {
232277
#[inline]
233278
/// Converts a DER-encoded byte slice to a signature
@@ -334,18 +379,18 @@ impl Signature {
334379

335380
#[inline]
336381
/// Serializes the signature in DER format
337-
pub fn serialize_der(&self) -> Vec<u8> {
338-
let mut ret = Vec::with_capacity(72);
339-
let mut len: usize = ret.capacity() as usize;
382+
pub fn serialize_der(&self) -> SerializedSignature {
383+
let mut ret = SerializedSignature::default();
384+
let mut len: usize = ret.capacity();
340385
unsafe {
341386
let err = ffi::secp256k1_ecdsa_signature_serialize_der(
342387
ffi::secp256k1_context_no_precomp,
343-
ret.as_mut_ptr(),
388+
ret.get_data_mut_ptr(),
344389
&mut len,
345390
self.as_ptr(),
346391
);
347392
debug_assert!(err == 1);
348-
ret.set_len(len as usize);
393+
ret.set_len(len);
349394
}
350395
ret
351396
}
@@ -516,17 +561,8 @@ pub enum Error {
516561
InvalidTweak,
517562
}
518563

519-
// Passthrough Debug to Display, since errors should be user-visible
520-
impl fmt::Display for Error {
521-
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
522-
f.write_str(error::Error::description(self))
523-
}
524-
}
525-
526-
impl error::Error for Error {
527-
fn cause(&self) -> Option<&error::Error> { None }
528-
529-
fn description(&self) -> &str {
564+
impl Error {
565+
fn as_str(&self) -> &str {
530566
match *self {
531567
Error::IncorrectSignature => "secp: signature failed verification",
532568
Error::InvalidMessage => "secp: message was not 32 bytes (do you need to hash?)",
@@ -539,6 +575,18 @@ impl error::Error for Error {
539575
}
540576
}
541577

578+
// Passthrough Debug to Display, since errors should be user-visible
579+
impl fmt::Display for Error {
580+
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
581+
f.write_str(self.as_str())
582+
}
583+
}
584+
585+
#[cfg(feature = "std")]
586+
impl std::error::Error for Error {
587+
fn description(&self) -> &str { self.as_str() }
588+
}
589+
542590
/// Marker trait for indicating that an instance of `Secp256k1` can be used for signing.
543591
pub trait Signing {}
544592

@@ -584,6 +632,36 @@ impl<C> PartialEq for Secp256k1<C> {
584632
fn eq(&self, _other: &Secp256k1<C>) -> bool { true }
585633
}
586634

635+
impl Default for SerializedSignature {
636+
fn default() -> SerializedSignature {
637+
SerializedSignature {
638+
data: [0u8; 72],
639+
len: 0,
640+
}
641+
}
642+
}
643+
644+
impl PartialEq for SerializedSignature {
645+
fn eq(&self, other: &SerializedSignature) -> bool {
646+
&self.data[..self.len] == &other.data[..other.len]
647+
}
648+
}
649+
650+
impl AsRef<[u8]> for SerializedSignature {
651+
fn as_ref(&self) -> &[u8] {
652+
&self.data[..self.len]
653+
}
654+
}
655+
656+
impl Deref for SerializedSignature {
657+
type Target = [u8];
658+
fn deref(&self) -> &[u8] {
659+
&self.data[..self.len]
660+
}
661+
}
662+
663+
impl Eq for SerializedSignature {}
664+
587665
impl<C> Eq for Secp256k1<C> { }
588666

589667
impl<C> Drop for Secp256k1<C> {

src/macros.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,14 @@ macro_rules! impl_array_newtype {
5353

5454
impl PartialOrd for $thing {
5555
#[inline]
56-
fn partial_cmp(&self, other: &$thing) -> Option<::std::cmp::Ordering> {
56+
fn partial_cmp(&self, other: &$thing) -> Option<::core::cmp::Ordering> {
5757
self[..].partial_cmp(&other[..])
5858
}
5959
}
6060

6161
impl Ord for $thing {
6262
#[inline]
63-
fn cmp(&self, other: &$thing) -> ::std::cmp::Ordering {
63+
fn cmp(&self, other: &$thing) -> ::core::cmp::Ordering {
6464
self[..].cmp(&other[..])
6565
}
6666
}
@@ -69,8 +69,8 @@ macro_rules! impl_array_newtype {
6969
#[inline]
7070
fn clone(&self) -> $thing {
7171
unsafe {
72-
use std::intrinsics::copy_nonoverlapping;
73-
use std::mem;
72+
use core::intrinsics::copy_nonoverlapping;
73+
use core::mem;
7474
let mut ret: $thing = mem::uninitialized();
7575
copy_nonoverlapping(self.as_ptr(),
7676
ret.as_mut_ptr(),
@@ -80,7 +80,7 @@ macro_rules! impl_array_newtype {
8080
}
8181
}
8282

83-
impl ::std::ops::Index<usize> for $thing {
83+
impl ::core::ops::Index<usize> for $thing {
8484
type Output = $ty;
8585

8686
#[inline]
@@ -90,41 +90,41 @@ macro_rules! impl_array_newtype {
9090
}
9191
}
9292

93-
impl ::std::ops::Index<::std::ops::Range<usize>> for $thing {
93+
impl ::core::ops::Index<::core::ops::Range<usize>> for $thing {
9494
type Output = [$ty];
9595

9696
#[inline]
97-
fn index(&self, index: ::std::ops::Range<usize>) -> &[$ty] {
97+
fn index(&self, index: ::core::ops::Range<usize>) -> &[$ty] {
9898
let &$thing(ref dat) = self;
9999
&dat[index]
100100
}
101101
}
102102

103-
impl ::std::ops::Index<::std::ops::RangeTo<usize>> for $thing {
103+
impl ::core::ops::Index<::core::ops::RangeTo<usize>> for $thing {
104104
type Output = [$ty];
105105

106106
#[inline]
107-
fn index(&self, index: ::std::ops::RangeTo<usize>) -> &[$ty] {
107+
fn index(&self, index: ::core::ops::RangeTo<usize>) -> &[$ty] {
108108
let &$thing(ref dat) = self;
109109
&dat[index]
110110
}
111111
}
112112

113-
impl ::std::ops::Index<::std::ops::RangeFrom<usize>> for $thing {
113+
impl ::core::ops::Index<::core::ops::RangeFrom<usize>> for $thing {
114114
type Output = [$ty];
115115

116116
#[inline]
117-
fn index(&self, index: ::std::ops::RangeFrom<usize>) -> &[$ty] {
117+
fn index(&self, index: ::core::ops::RangeFrom<usize>) -> &[$ty] {
118118
let &$thing(ref dat) = self;
119119
&dat[index]
120120
}
121121
}
122122

123-
impl ::std::ops::Index<::std::ops::RangeFull> for $thing {
123+
impl ::core::ops::Index<::core::ops::RangeFull> for $thing {
124124
type Output = [$ty];
125125

126126
#[inline]
127-
fn index(&self, _: ::std::ops::RangeFull) -> &[$ty] {
127+
fn index(&self, _: ::core::ops::RangeFull) -> &[$ty] {
128128
let &$thing(ref dat) = self;
129129
&dat[..]
130130
}
@@ -134,8 +134,8 @@ macro_rules! impl_array_newtype {
134134

135135
macro_rules! impl_pretty_debug {
136136
($thing:ident) => {
137-
impl ::std::fmt::Debug for $thing {
138-
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
137+
impl ::core::fmt::Debug for $thing {
138+
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
139139
try!(write!(f, "{}(", stringify!($thing)));
140140
for i in self[..].iter().cloned() {
141141
try!(write!(f, "{:02x}", i));
@@ -148,8 +148,8 @@ macro_rules! impl_pretty_debug {
148148

149149
macro_rules! impl_raw_debug {
150150
($thing:ident) => {
151-
impl ::std::fmt::Debug for $thing {
152-
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
151+
impl ::core::fmt::Debug for $thing {
152+
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
153153
for i in self[..].iter().cloned() {
154154
try!(write!(f, "{:02x}", i));
155155
}

src/types.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#![allow(non_camel_case_types)]
2+
use core::fmt;
3+
4+
pub type c_int = i32;
5+
pub type c_uchar = u8;
6+
pub type c_uint = u32;
7+
8+
/// This is an exact copy of https://doc.rust-lang.org/core/ffi/enum.c_void.html
9+
/// It should be Equivalent to C's void type when used as a pointer.
10+
///
11+
/// We can replace this with `core::ffi::c_void` once we update the rustc version to >=1.30.0.
12+
#[repr(u8)]
13+
pub enum c_void {
14+
#[doc(hidden)] __variant1,
15+
#[doc(hidden)] __variant2,
16+
}
17+
18+
impl fmt::Debug for c_void {
19+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
20+
f.pad("c_void")
21+
}
22+
}

0 commit comments

Comments
 (0)