1 use cfg_if::cfg_if; 2 use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; 3 use libc::c_int; 4 use std::borrow::Borrow; 5 use std::convert::AsRef; 6 use std::fmt; 7 use std::iter; 8 use std::marker::PhantomData; 9 use std::mem; 10 use std::ops::{Deref, DerefMut, Index, IndexMut, Range}; 11 12 use crate::error::ErrorStack; 13 use crate::util::ForeignTypeExt; 14 use crate::{cvt, cvt_p, LenType}; 15 16 cfg_if! { 17 if #[cfg(ossl110)] { 18 use ffi::{ 19 OPENSSL_sk_pop, OPENSSL_sk_free, OPENSSL_sk_num, OPENSSL_sk_value, OPENSSL_STACK, 20 OPENSSL_sk_new_null, OPENSSL_sk_push, 21 }; 22 } else { 23 use ffi::{ 24 sk_pop as OPENSSL_sk_pop, sk_free as OPENSSL_sk_free, sk_num as OPENSSL_sk_num, 25 sk_value as OPENSSL_sk_value, _STACK as OPENSSL_STACK, 26 sk_new_null as OPENSSL_sk_new_null, sk_push as OPENSSL_sk_push, 27 }; 28 } 29 } 30 31 /// Trait implemented by types which can be placed in a stack. 32 /// 33 /// It should not be implemented for any type outside of this crate. 34 pub trait Stackable: ForeignType { 35 /// The C stack type for this element. 36 /// 37 /// Generally called `stack_st_{ELEMENT_TYPE}`, normally hidden by the 38 /// `STACK_OF(ELEMENT_TYPE)` macro in the OpenSSL API. 39 type StackType; 40 } 41 42 /// An owned stack of `T`. 43 pub struct Stack<T: Stackable>(*mut T::StackType); 44 45 unsafe impl<T: Stackable + Send> Send for Stack<T> {} 46 unsafe impl<T: Stackable + Sync> Sync for Stack<T> {} 47 48 impl<T> fmt::Debug for Stack<T> 49 where 50 T: Stackable, 51 T::Ref: fmt::Debug, 52 { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result53 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 54 fmt.debug_list().entries(self).finish() 55 } 56 } 57 impl<T: Stackable> Drop for Stack<T> { drop(&mut self)58 fn drop(&mut self) { 59 unsafe { 60 while self.pop().is_some() {} 61 OPENSSL_sk_free(self.0 as *mut _); 62 } 63 } 64 } 65 66 impl<T: Stackable> Stack<T> { new() -> Result<Stack<T>, ErrorStack>67 pub fn new() -> Result<Stack<T>, ErrorStack> { 68 unsafe { 69 ffi::init(); 70 let ptr = cvt_p(OPENSSL_sk_new_null())?; 71 Ok(Stack(ptr as *mut _)) 72 } 73 } 74 } 75 76 impl<T: Stackable> iter::IntoIterator for Stack<T> { 77 type IntoIter = IntoIter<T>; 78 type Item = T; 79 into_iter(self) -> IntoIter<T>80 fn into_iter(self) -> IntoIter<T> { 81 let it = IntoIter { 82 stack: self.0, 83 idxs: 0..self.len() as LenType, 84 }; 85 mem::forget(self); 86 it 87 } 88 } 89 90 impl<T: Stackable> AsRef<StackRef<T>> for Stack<T> { as_ref(&self) -> &StackRef<T>91 fn as_ref(&self) -> &StackRef<T> { 92 self 93 } 94 } 95 96 impl<T: Stackable> Borrow<StackRef<T>> for Stack<T> { borrow(&self) -> &StackRef<T>97 fn borrow(&self) -> &StackRef<T> { 98 self 99 } 100 } 101 102 impl<T: Stackable> ForeignType for Stack<T> { 103 type CType = T::StackType; 104 type Ref = StackRef<T>; 105 106 #[inline] from_ptr(ptr: *mut T::StackType) -> Stack<T>107 unsafe fn from_ptr(ptr: *mut T::StackType) -> Stack<T> { 108 assert!( 109 !ptr.is_null(), 110 "Must not instantiate a Stack from a null-ptr - use Stack::new() in \ 111 that case" 112 ); 113 Stack(ptr) 114 } 115 116 #[inline] as_ptr(&self) -> *mut T::StackType117 fn as_ptr(&self) -> *mut T::StackType { 118 self.0 119 } 120 } 121 122 impl<T: Stackable> Deref for Stack<T> { 123 type Target = StackRef<T>; 124 deref(&self) -> &StackRef<T>125 fn deref(&self) -> &StackRef<T> { 126 unsafe { StackRef::from_ptr(self.0) } 127 } 128 } 129 130 impl<T: Stackable> DerefMut for Stack<T> { deref_mut(&mut self) -> &mut StackRef<T>131 fn deref_mut(&mut self) -> &mut StackRef<T> { 132 unsafe { StackRef::from_ptr_mut(self.0) } 133 } 134 } 135 136 pub struct IntoIter<T: Stackable> { 137 stack: *mut T::StackType, 138 idxs: Range<LenType>, 139 } 140 141 impl<T: Stackable> Drop for IntoIter<T> { drop(&mut self)142 fn drop(&mut self) { 143 unsafe { 144 // https://github.com/rust-lang/rust-clippy/issues/7510 145 #[allow(clippy::while_let_on_iterator)] 146 while let Some(_) = self.next() {} 147 OPENSSL_sk_free(self.stack as *mut _); 148 } 149 } 150 } 151 152 impl<T: Stackable> Iterator for IntoIter<T> { 153 type Item = T; 154 next(&mut self) -> Option<T>155 fn next(&mut self) -> Option<T> { 156 unsafe { 157 self.idxs 158 .next() 159 .map(|i| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, i) as *mut _)) 160 } 161 } 162 size_hint(&self) -> (usize, Option<usize>)163 fn size_hint(&self) -> (usize, Option<usize>) { 164 self.idxs.size_hint() 165 } 166 } 167 168 impl<T: Stackable> DoubleEndedIterator for IntoIter<T> { next_back(&mut self) -> Option<T>169 fn next_back(&mut self) -> Option<T> { 170 unsafe { 171 self.idxs 172 .next_back() 173 .map(|i| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, i) as *mut _)) 174 } 175 } 176 } 177 178 impl<T: Stackable> ExactSizeIterator for IntoIter<T> {} 179 180 pub struct StackRef<T: Stackable>(Opaque, PhantomData<T>); 181 182 unsafe impl<T: Stackable + Send> Send for StackRef<T> {} 183 unsafe impl<T: Stackable + Sync> Sync for StackRef<T> {} 184 185 impl<T: Stackable> ForeignTypeRef for StackRef<T> { 186 type CType = T::StackType; 187 } 188 189 impl<T: Stackable> StackRef<T> { as_stack(&self) -> *mut OPENSSL_STACK190 fn as_stack(&self) -> *mut OPENSSL_STACK { 191 self.as_ptr() as *mut _ 192 } 193 194 /// Returns the number of items in the stack. len(&self) -> usize195 pub fn len(&self) -> usize { 196 unsafe { OPENSSL_sk_num(self.as_stack()) as usize } 197 } 198 199 /// Determines if the stack is empty. is_empty(&self) -> bool200 pub fn is_empty(&self) -> bool { 201 self.len() == 0 202 } 203 iter(&self) -> Iter<'_, T>204 pub fn iter(&self) -> Iter<'_, T> { 205 Iter { 206 stack: self, 207 idxs: 0..self.len() as LenType, 208 } 209 } 210 iter_mut(&mut self) -> IterMut<'_, T>211 pub fn iter_mut(&mut self) -> IterMut<'_, T> { 212 IterMut { 213 idxs: 0..self.len() as LenType, 214 stack: self, 215 } 216 } 217 218 /// Returns a reference to the element at the given index in the 219 /// stack or `None` if the index is out of bounds get(&self, idx: usize) -> Option<&T::Ref>220 pub fn get(&self, idx: usize) -> Option<&T::Ref> { 221 unsafe { 222 if idx >= self.len() { 223 return None; 224 } 225 226 Some(T::Ref::from_ptr(self._get(idx))) 227 } 228 } 229 230 /// Returns a mutable reference to the element at the given index in the 231 /// stack or `None` if the index is out of bounds get_mut(&mut self, idx: usize) -> Option<&mut T::Ref>232 pub fn get_mut(&mut self, idx: usize) -> Option<&mut T::Ref> { 233 unsafe { 234 if idx >= self.len() { 235 return None; 236 } 237 238 Some(T::Ref::from_ptr_mut(self._get(idx))) 239 } 240 } 241 242 /// Pushes a value onto the top of the stack. push(&mut self, data: T) -> Result<(), ErrorStack>243 pub fn push(&mut self, data: T) -> Result<(), ErrorStack> { 244 unsafe { 245 cvt(OPENSSL_sk_push(self.as_stack(), data.as_ptr() as *mut _) as c_int)?; 246 mem::forget(data); 247 Ok(()) 248 } 249 } 250 251 /// Removes the last element from the stack and returns it. pop(&mut self) -> Option<T>252 pub fn pop(&mut self) -> Option<T> { 253 unsafe { 254 let ptr = OPENSSL_sk_pop(self.as_stack()); 255 T::from_ptr_opt(ptr as *mut _) 256 } 257 } 258 _get(&self, idx: usize) -> *mut T::CType259 unsafe fn _get(&self, idx: usize) -> *mut T::CType { 260 OPENSSL_sk_value(self.as_stack(), idx as LenType) as *mut _ 261 } 262 } 263 264 impl<T: Stackable> Index<usize> for StackRef<T> { 265 type Output = T::Ref; 266 index(&self, index: usize) -> &T::Ref267 fn index(&self, index: usize) -> &T::Ref { 268 self.get(index).unwrap() 269 } 270 } 271 272 impl<T: Stackable> IndexMut<usize> for StackRef<T> { index_mut(&mut self, index: usize) -> &mut T::Ref273 fn index_mut(&mut self, index: usize) -> &mut T::Ref { 274 self.get_mut(index).unwrap() 275 } 276 } 277 278 impl<'a, T: Stackable> iter::IntoIterator for &'a StackRef<T> { 279 type Item = &'a T::Ref; 280 type IntoIter = Iter<'a, T>; 281 into_iter(self) -> Iter<'a, T>282 fn into_iter(self) -> Iter<'a, T> { 283 self.iter() 284 } 285 } 286 287 impl<'a, T: Stackable> iter::IntoIterator for &'a mut StackRef<T> { 288 type Item = &'a mut T::Ref; 289 type IntoIter = IterMut<'a, T>; 290 into_iter(self) -> IterMut<'a, T>291 fn into_iter(self) -> IterMut<'a, T> { 292 self.iter_mut() 293 } 294 } 295 296 impl<'a, T: Stackable> iter::IntoIterator for &'a Stack<T> { 297 type Item = &'a T::Ref; 298 type IntoIter = Iter<'a, T>; 299 into_iter(self) -> Iter<'a, T>300 fn into_iter(self) -> Iter<'a, T> { 301 self.iter() 302 } 303 } 304 305 impl<'a, T: Stackable> iter::IntoIterator for &'a mut Stack<T> { 306 type Item = &'a mut T::Ref; 307 type IntoIter = IterMut<'a, T>; 308 into_iter(self) -> IterMut<'a, T>309 fn into_iter(self) -> IterMut<'a, T> { 310 self.iter_mut() 311 } 312 } 313 314 /// An iterator over the stack's contents. 315 pub struct Iter<'a, T: Stackable> { 316 stack: &'a StackRef<T>, 317 idxs: Range<LenType>, 318 } 319 320 impl<'a, T: Stackable> Iterator for Iter<'a, T> { 321 type Item = &'a T::Ref; 322 next(&mut self) -> Option<&'a T::Ref>323 fn next(&mut self) -> Option<&'a T::Ref> { 324 unsafe { 325 self.idxs 326 .next() 327 .map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _)) 328 } 329 } 330 size_hint(&self) -> (usize, Option<usize>)331 fn size_hint(&self) -> (usize, Option<usize>) { 332 self.idxs.size_hint() 333 } 334 } 335 336 impl<'a, T: Stackable> DoubleEndedIterator for Iter<'a, T> { next_back(&mut self) -> Option<&'a T::Ref>337 fn next_back(&mut self) -> Option<&'a T::Ref> { 338 unsafe { 339 self.idxs 340 .next_back() 341 .map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _)) 342 } 343 } 344 } 345 346 impl<'a, T: Stackable> ExactSizeIterator for Iter<'a, T> {} 347 348 /// A mutable iterator over the stack's contents. 349 pub struct IterMut<'a, T: Stackable> { 350 stack: &'a mut StackRef<T>, 351 idxs: Range<LenType>, 352 } 353 354 impl<'a, T: Stackable> Iterator for IterMut<'a, T> { 355 type Item = &'a mut T::Ref; 356 next(&mut self) -> Option<&'a mut T::Ref>357 fn next(&mut self) -> Option<&'a mut T::Ref> { 358 unsafe { 359 self.idxs 360 .next() 361 .map(|i| T::Ref::from_ptr_mut(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _)) 362 } 363 } 364 size_hint(&self) -> (usize, Option<usize>)365 fn size_hint(&self) -> (usize, Option<usize>) { 366 self.idxs.size_hint() 367 } 368 } 369 370 impl<'a, T: Stackable> DoubleEndedIterator for IterMut<'a, T> { next_back(&mut self) -> Option<&'a mut T::Ref>371 fn next_back(&mut self) -> Option<&'a mut T::Ref> { 372 unsafe { 373 self.idxs 374 .next_back() 375 .map(|i| T::Ref::from_ptr_mut(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _)) 376 } 377 } 378 } 379 380 impl<'a, T: Stackable> ExactSizeIterator for IterMut<'a, T> {} 381