diff --git a/openssl/src/bn.rs b/openssl/src/bn.rs index 78684d0a..ab5f7769 100644 --- a/openssl/src/bn.rs +++ b/openssl/src/bn.rs @@ -23,16 +23,7 @@ pub enum RNGProperty { TwoMsbOne = 1, } -/// A context object for `BigNum` operations. -pub struct BnCtx(*mut ffi::BN_CTX); - -impl Drop for BnCtx { - fn drop(&mut self) { - unsafe { - ffi::BN_CTX_free(self.0); - } - } -} +type_!(BnCtx, ffi::BN_CTX, ffi::BN_CTX_free); impl BnCtx { /// Returns a new `BnCtx`. @@ -40,10 +31,6 @@ impl BnCtx { unsafe { cvt_p(ffi::BN_CTX_new()).map(BnCtx) } } - pub fn as_ptr(&self) -> *mut ffi::BN_CTX { - self.0 - } - /// Places the result of `a * b` in `r`. pub fn mul(&mut self, r: &mut BigNumRef, diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index f335c097..8fa53f3b 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -20,6 +20,44 @@ use libc::c_int; use error::ErrorStack; +macro_rules! type_ { + ($n:ident, $c:path, $d:path) => { + pub struct $n(*mut $c); + + unsafe impl ::types::OpenSslType for $n { + type CType = $c; + + unsafe fn from_ptr(ptr: *mut $c) -> $n { + $n(ptr) + } + + fn as_ptr(&self) -> *mut $c { + self.0 + } + } + + impl Drop for $n { + fn drop(&mut self) { + unsafe { $d(self.0) } + } + } + + impl ::std::ops::Deref for $n { + type Target = ::types::Ref<$n>; + + fn deref(&self) -> &::types::Ref<$n> { + unsafe { ::types::Ref::from_ptr(self.0) } + } + } + + impl ::std::ops::DerefMut for $n { + fn deref_mut(&mut self) -> &mut ::types::Ref<$n> { + unsafe { ::types::Ref::from_ptr_mut(self.0) } + } + } + } +} + mod bio; mod opaque; mod util; @@ -37,6 +75,7 @@ pub mod pkcs12; pub mod pkcs5; pub mod pkey; pub mod rand; +pub mod types; pub mod rsa; pub mod sign; pub mod ssl; diff --git a/openssl/src/types.rs b/openssl/src/types.rs new file mode 100644 index 00000000..16829ea4 --- /dev/null +++ b/openssl/src/types.rs @@ -0,0 +1,27 @@ +use std::marker::PhantomData; + +use opaque::Opaque; + +pub unsafe trait OpenSslType { + type CType; + + unsafe fn from_ptr(ptr: *mut Self::CType) -> Self; + + fn as_ptr(&self) -> *mut Self::CType; +} + +pub struct Ref(Opaque, PhantomData); + +impl Ref { + pub unsafe fn from_ptr<'a>(ptr: *mut T::CType) -> &'a Ref { + &*(ptr as *mut _) + } + + pub unsafe fn from_ptr_mut<'a>(ptr: *mut T::CType) -> &'a mut Ref { + &mut *(ptr as *mut _) + } + + pub fn as_ptr(&self) -> *mut T::CType { + self as *const _ as *mut _ + } +}