Add a consuming iterator for Stacks
This commit is contained in:
parent
f15c817c2d
commit
398ab2fbc4
|
|
@ -11,6 +11,7 @@ use pkey::PKey;
|
||||||
use error::ErrorStack;
|
use error::ErrorStack;
|
||||||
use x509::X509;
|
use x509::X509;
|
||||||
use types::OpenSslType;
|
use types::OpenSslType;
|
||||||
|
use stack::Stack;
|
||||||
|
|
||||||
/// A PKCS #12 archive.
|
/// A PKCS #12 archive.
|
||||||
pub struct Pkcs12(*mut ffi::PKCS12);
|
pub struct Pkcs12(*mut ffi::PKCS12);
|
||||||
|
|
@ -48,19 +49,12 @@ impl Pkcs12 {
|
||||||
|
|
||||||
let pkey = PKey::from_ptr(pkey);
|
let pkey = PKey::from_ptr(pkey);
|
||||||
let cert = X509::from_ptr(cert);
|
let cert = X509::from_ptr(cert);
|
||||||
let chain = chain as *mut _;
|
let chain = Stack::from_ptr(chain).into_iter().collect();
|
||||||
|
|
||||||
let mut chain_out = vec![];
|
|
||||||
for i in 0..compat::OPENSSL_sk_num(chain) {
|
|
||||||
let x509 = compat::OPENSSL_sk_value(chain, i);
|
|
||||||
chain_out.push(X509::from_ptr(x509 as *mut _));
|
|
||||||
}
|
|
||||||
compat::OPENSSL_sk_free(chain as *mut _);
|
|
||||||
|
|
||||||
Ok(ParsedPkcs12 {
|
Ok(ParsedPkcs12 {
|
||||||
pkey: pkey,
|
pkey: pkey,
|
||||||
cert: cert,
|
cert: cert,
|
||||||
chain: chain_out,
|
chain: chain,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -72,30 +66,6 @@ pub struct ParsedPkcs12 {
|
||||||
pub chain: Vec<X509>,
|
pub chain: Vec<X509>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(ossl110)]
|
|
||||||
mod compat {
|
|
||||||
pub use ffi::OPENSSL_sk_free;
|
|
||||||
pub use ffi::OPENSSL_sk_num;
|
|
||||||
pub use ffi::OPENSSL_sk_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(ossl10x)]
|
|
||||||
#[allow(bad_style)]
|
|
||||||
mod compat {
|
|
||||||
use libc::{c_int, c_void};
|
|
||||||
use ffi;
|
|
||||||
|
|
||||||
pub use ffi::sk_free as OPENSSL_sk_free;
|
|
||||||
|
|
||||||
pub unsafe fn OPENSSL_sk_num(stack: *mut ffi::_STACK) -> c_int {
|
|
||||||
(*stack).num
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn OPENSSL_sk_value(stack: *const ffi::_STACK, idx: c_int) -> *mut c_void {
|
|
||||||
*(*stack).data.offset(idx as isize) as *mut c_void
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use hash::MessageDigest;
|
use hash::MessageDigest;
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,16 @@ use std::borrow::Borrow;
|
||||||
use std::convert::AsRef;
|
use std::convert::AsRef;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
use ffi;
|
|
||||||
use types::{OpenSslType, OpenSslTypeRef};
|
use types::{OpenSslType, OpenSslTypeRef};
|
||||||
use util::Opaque;
|
use util::Opaque;
|
||||||
|
|
||||||
#[cfg(ossl10x)]
|
#[cfg(ossl10x)]
|
||||||
use ffi::{sk_pop as OPENSSL_sk_pop, sk_free as OPENSSL_sk_free, sk_num as OPENSSL_sk_num,
|
use ffi::{sk_pop as OPENSSL_sk_pop, sk_free as OPENSSL_sk_free, sk_num as OPENSSL_sk_num,
|
||||||
sk_value as OPENSSL_sk_value};
|
sk_value as OPENSSL_sk_value, _STACK as OPENSSL_STACK};
|
||||||
#[cfg(ossl110)]
|
#[cfg(ossl110)]
|
||||||
use ffi::{OPENSSL_sk_pop, OPENSSL_sk_free, OPENSSL_sk_num, OPENSSL_sk_value};
|
use ffi::{OPENSSL_sk_pop, OPENSSL_sk_free, OPENSSL_sk_num, OPENSSL_sk_value, OPENSSL_STACK};
|
||||||
|
|
||||||
/// Trait implemented by types which can be placed in a stack.
|
/// Trait implemented by types which can be placed in a stack.
|
||||||
///
|
///
|
||||||
|
|
@ -57,6 +57,20 @@ impl<T: Stackable> Drop for Stack<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Stackable> iter::IntoIterator for Stack<T> {
|
||||||
|
type IntoIter = IntoIter<T>;
|
||||||
|
type Item = T;
|
||||||
|
|
||||||
|
fn into_iter(self) -> IntoIter<T> {
|
||||||
|
let it = IntoIter {
|
||||||
|
stack: self.0,
|
||||||
|
idx: 0,
|
||||||
|
};
|
||||||
|
mem::forget(self);
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Stackable> AsRef<StackRef<T>> for Stack<T> {
|
impl<T: Stackable> AsRef<StackRef<T>> for Stack<T> {
|
||||||
fn as_ref(&self) -> &StackRef<T> {
|
fn as_ref(&self) -> &StackRef<T> {
|
||||||
&*self
|
&*self
|
||||||
|
|
@ -92,31 +106,66 @@ impl<T: Stackable> DerefMut for Stack<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct IntoIter<T: Stackable> {
|
||||||
|
stack: *mut T::StackType,
|
||||||
|
idx: c_int,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Stackable> IntoIter<T> {
|
||||||
|
fn stack_len(&self) -> c_int {
|
||||||
|
unsafe { OPENSSL_sk_num(self.stack as *mut _) }
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn get(&mut self, i: c_int) -> T {
|
||||||
|
let ptr = OPENSSL_sk_value(self.stack as *mut _, i);
|
||||||
|
T::from_ptr(ptr as *mut _)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Stackable> Drop for IntoIter<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
for i in self.idx..self.stack_len() {
|
||||||
|
self.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
OPENSSL_sk_free(self.stack as *mut _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Stackable> Iterator for IntoIter<T> {
|
||||||
|
type Item = T;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<T> {
|
||||||
|
unsafe {
|
||||||
|
if self.idx == self.stack_len() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let idx = self.idx;
|
||||||
|
self.idx += 1;
|
||||||
|
let v = self.get(idx);
|
||||||
|
Some(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
let size = (self.stack_len() - self.idx) as usize;
|
||||||
|
(size, Some(size))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Stackable> ExactSizeIterator for IntoIter<T> {}
|
||||||
|
|
||||||
pub struct StackRef<T: Stackable>(Opaque, PhantomData<T>);
|
pub struct StackRef<T: Stackable>(Opaque, PhantomData<T>);
|
||||||
|
|
||||||
impl<T: Stackable> OpenSslTypeRef for StackRef<T> {
|
impl<T: Stackable> OpenSslTypeRef for StackRef<T> {
|
||||||
type CType = T::StackType;
|
type CType = T::StackType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<T: Stackable> StackRef<T> {
|
impl<T: Stackable> StackRef<T> {
|
||||||
/// OpenSSL stack types are just a (kinda) typesafe wrapper around
|
fn as_stack(&self) -> *mut OPENSSL_STACK {
|
||||||
/// a `_STACK` object. We can therefore safely cast it and access
|
|
||||||
/// the `_STACK` members without having to worry about the real
|
|
||||||
/// layout of `T::StackType`.
|
|
||||||
///
|
|
||||||
/// If that sounds unsafe then keep in mind that's exactly how the
|
|
||||||
/// OpenSSL 1.1.0 new C stack code works.
|
|
||||||
#[cfg(ossl10x)]
|
|
||||||
fn as_stack(&self) -> *mut ffi::_STACK {
|
|
||||||
self.as_ptr() as *mut _
|
|
||||||
}
|
|
||||||
|
|
||||||
/// OpenSSL 1.1.0 replaced the stack macros with a functions and
|
|
||||||
/// only exposes an opaque OPENSSL_STACK struct
|
|
||||||
/// publicly.
|
|
||||||
#[cfg(ossl110)]
|
|
||||||
fn as_stack(&self) -> *mut ffi::OPENSSL_STACK {
|
|
||||||
self.as_ptr() as *mut _
|
self.as_ptr() as *mut _
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue