From a0f11d0f9201b42d893ae2fc0be6525e26ba8ca8 Mon Sep 17 00:00:00 2001 From: Andrew Poelstra Date: Wed, 27 Aug 2014 10:19:10 -0700 Subject: [PATCH] Travis speaks rust now :D --- .travis.yml | 9 +---- src/key.rs | 54 ++++----------------------- src/macros.rs | 95 ++++++++++++++++++++++++++++++++++++++++++++++++ src/secp256k1.rs | 2 + 4 files changed, 105 insertions(+), 55 deletions(-) create mode 100644 src/macros.rs diff --git a/.travis.yml b/.travis.yml index a2a567d..4f2898a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,8 @@ +language: rust -before_install: - - sudo add-apt-repository --yes ppa:hansjorg/rust - - sudo add-apt-repository --yes ppa:cmrx64/cargo - - sudo apt-get update -qq install: - - sudo apt-get install -qq rust-nightly cargo - git clone https://github.com/sipa/secp256k1.git - cd secp256k1 - ./autogen.sh && ./configure && make && sudo make install - sudo ldconfig /usr/local/lib -script: - - cargo build - - cargo test diff --git a/src/key.rs b/src/key.rs index 1edf8fe..14a1129 100644 --- a/src/key.rs +++ b/src/key.rs @@ -25,12 +25,14 @@ use super::{Result, InvalidNonce, InvalidPublicKey, InvalidSecretKey}; /// Secret 256-bit nonce used as `k` in an ECDSA signature pub struct Nonce([u8, ..constants::NONCE_SIZE]); +impl_array_newtype!(Nonce, u8, constants::NONCE_SIZE) /// Secret 256-bit key used as `x` in an ECDSA signature pub struct SecretKey([u8, ..constants::SECRET_KEY_SIZE]); +impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE) /// Public key -#[deriving(PartialEq, Eq, Show)] +#[deriving(Clone, PartialEq, Eq, Show)] pub struct PublicKey(PublicKeyData); enum PublicKeyData { @@ -67,21 +69,6 @@ impl Nonce { _ => Err(InvalidNonce) } } - - /// Converts the nonce into a byte slice - #[inline] - pub fn as_slice<'a>(&'a self) -> &'a [u8] { - let &Nonce(ref data) = self; - data.as_slice() - } - - /// Converts the nonce to a raw pointer suitable for use with - /// the FFI functions - #[inline] - pub fn as_ptr(&self) -> *const u8 { - let &Nonce(ref data) = self; - data.as_ptr() - } } impl SecretKey { @@ -110,21 +97,6 @@ impl SecretKey { _ => Err(InvalidSecretKey) } } - - /// Converts the secret key into a byte slice - #[inline] - pub fn as_slice<'a>(&'a self) -> &'a [u8] { - let &SecretKey(ref data) = self; - data.as_slice() - } - - /// Converts the secret key to a raw pointer suitable for use with - /// the FFI functions - #[inline] - pub fn as_ptr(&self) -> *const u8 { - let &SecretKey(ref data) = self; - data.as_ptr() - } } impl PublicKey { @@ -244,20 +216,16 @@ impl PublicKeyData { // We have to do all these impls ourselves as Rust can't derive // them for arrays -impl PartialEq for Nonce { - fn eq(&self, other: &Nonce) -> bool { - self.as_slice() == other.as_slice() - } -} - -impl Eq for Nonce {} - impl fmt::Show for Nonce { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.as_slice().fmt(f) } } +impl Clone for PublicKeyData { + fn clone(&self) -> PublicKeyData { *self } +} + impl PartialEq for PublicKeyData { fn eq(&self, other: &PublicKeyData) -> bool { self.as_slice() == other.as_slice() @@ -272,14 +240,6 @@ impl fmt::Show for PublicKeyData { } } -impl PartialEq for SecretKey { - fn eq(&self, other: &SecretKey) -> bool { - self.as_slice() == other.as_slice() - } -} - -impl Eq for SecretKey {} - impl fmt::Show for SecretKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.as_slice().fmt(f) diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..29c437c --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,95 @@ +// Bitcoin secp256k1 bindings +// Written in 2014 by +// Dawid Ciężarkiewicz +// Andrew Poelstra +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to +// the public domain worldwide. This software is distributed without +// any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication +// along with this software. +// If not, see . +// + +#![macro_escape] + +// This is a macro that routinely comes in handy +macro_rules! impl_array_newtype( + ($thing:ident, $ty:ty, $len:expr) => { + impl $thing { + #[inline] + /// Provides an immutable view into the object + pub fn as_slice<'a>(&'a self) -> &'a [$ty] { + let &$thing(ref dat) = self; + dat.as_slice() + } + + #[inline] + /// Provides an immutable view into the object from index `s` inclusive to `e` exclusive + pub fn slice<'a>(&'a self, s: uint, e: uint) -> &'a [$ty] { + let &$thing(ref dat) = self; + dat.slice(s, e) + } + + #[inline] + /// Provides an immutable view into the object, up to index `n` exclusive + pub fn slice_to<'a>(&'a self, n: uint) -> &'a [$ty] { + let &$thing(ref dat) = self; + dat.slice_to(n) + } + + #[inline] + /// Provides an immutable view into the object, starting from index `n` + pub fn slice_from<'a>(&'a self, n: uint) -> &'a [$ty] { + let &$thing(ref dat) = self; + dat.slice_from(n) + } + + #[inline] + /// Converts the object to a raw pointer for FFI interfacing + pub fn as_ptr(&self) -> *const $ty { + let &$thing(ref dat) = self; + dat.as_ptr() + } + + #[inline] + /// Converts the object to a mutable raw pointer for FFI interfacing + pub fn as_mut_ptr(&mut self) -> *mut $ty { + let &$thing(ref mut dat) = self; + dat.as_mut_ptr() + } + + #[inline] + /// Returns the length of the object as an array + pub fn len(&self) -> uint { $len } + } + + impl PartialEq for $thing { + #[inline] + fn eq(&self, other: &$thing) -> bool { + self.as_slice() == other.as_slice() + } + } + + impl Eq for $thing {} + + impl Clone for $thing { + #[inline] + fn clone(&self) -> $thing { + unsafe { + use std::intrinsics::copy_nonoverlapping_memory; + use std::mem; + let mut ret: $thing = mem::uninitialized(); + copy_nonoverlapping_memory(ret.as_mut_ptr(), + self.as_ptr(), + mem::size_of::<$thing>()); + ret + } + } + } + } +) + + diff --git a/src/secp256k1.rs b/src/secp256k1.rs index 2e7393d..d8f8ed5 100644 --- a/src/secp256k1.rs +++ b/src/secp256k1.rs @@ -26,6 +26,7 @@ #![crate_name = "bitcoin-secp256k1-rs"] #![comment = "Bindings and wrapper functions for bitcoin secp256k1 library."] #![feature(phase)] +#![feature(macro_rules)] #![feature(globs)] // for tests only // Coding conventions @@ -44,6 +45,7 @@ use std::rand::OsRng; use libc::c_int; use sync::one::{Once, ONCE_INIT}; +mod macros; pub mod constants; pub mod ffi; pub mod key;