1use cfg_if::cfg_if; 2use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; 3use libc::c_int; 4use std::borrow::Borrow; 5use std::convert::AsRef; 6use std::fmt; 7use std::iter; 8use std::marker::PhantomData; 9use std::mem; 10use std::ops::{Deref, DerefMut, Index, IndexMut, Range}; 11 12use crate::error::ErrorStack; 13use crate::util::ForeignTypeExt; 14use crate::{cvt, cvt_p, LenType}; 15 16cfg_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. 34pub 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`. 43pub struct Stack<T: Stackable>(*mut T::StackType); 44 45unsafe impl<T: Stackable + Send> Send for Stack<T> {} 46unsafe impl<T: Stackable + Sync> Sync for Stack<T> {} 47 48impl<T> fmt::Debug for Stack<T> 49where 50 T: Stackable, 51 T::Ref: fmt::Debug, 52{ 53 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 54 fmt.debug_list().entries(self).finish() 55 } 56} 57impl<T: Stackable> Drop for Stack<T> { 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 66impl<T: Stackable> Stack<T> { 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 76impl<T: Stackable> iter::IntoIterator for Stack<T> { 77 type IntoIter = IntoIter<T>; 78 type Item = T; 79 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 90impl<T: Stackable> AsRef<StackRef<T>> for Stack<T> { 91 fn as_ref(&self) -> &StackRef<T> { 92 self 93 } 94} 95 96impl<T: Stackable> Borrow<StackRef<T>> for Stack<T> { 97 fn borrow(&self) -> &StackRef<T> { 98 self 99 } 100} 101 102impl<T: Stackable> ForeignType for Stack<T> { 103 type CType = T::StackType; 104 type Ref = StackRef<T>; 105 106 #[inline] 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] 117 fn as_ptr(&self) -> *mut T::StackType { 118 self.0 119 } 120} 121 122impl<T: Stackable> Deref for Stack<T> { 123 type Target = StackRef<T>; 124 125 fn deref(&self) -> &StackRef<T> { 126 unsafe { StackRef::from_ptr(self.0) } 127 } 128} 129 130impl<T: Stackable> DerefMut for Stack<T> { 131 fn deref_mut(&mut self) -> &mut StackRef<T> { 132 unsafe { StackRef::from_ptr_mut(self.0) } 133 } 134} 135 136pub struct IntoIter<T: Stackable> { 137 stack: *mut T::StackType, 138 idxs: Range<LenType>, 139} 140 141impl<T: Stackable> Drop for IntoIter<T> { 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 152impl<T: Stackable> Iterator for IntoIter<T> { 153 type Item = T; 154 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 163 fn size_hint(&self) -> (usize, Option<usize>) { 164 self.idxs.size_hint() 165 } 166} 167 168impl<T: Stackable> DoubleEndedIterator for IntoIter<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 178impl<T: Stackable> ExactSizeIterator for IntoIter<T> {} 179 180pub struct StackRef<T: Stackable>(Opaque, PhantomData<T>); 181 182unsafe impl<T: Stackable + Send> Send for StackRef<T> {} 183unsafe impl<T: Stackable + Sync> Sync for StackRef<T> {} 184 185impl<T: Stackable> ForeignTypeRef for StackRef<T> { 186 type CType = T::StackType; 187} 188 189impl<T: Stackable> StackRef<T> { 190 fn as_stack(&self) -> *mut OPENSSL_STACK { 191 self.as_ptr() as *mut _ 192 } 193 194 /// Returns the number of items in the stack. 195 pub fn len(&self) -> usize { 196 unsafe { OPENSSL_sk_num(self.as_stack()) as usize } 197 } 198 199 /// Determines if the stack is empty. 200 pub fn is_empty(&self) -> bool { 201 self.len() == 0 202 } 203 204 pub fn iter(&self) -> Iter<'_, T> { 205 Iter { 206 stack: self, 207 idxs: 0..self.len() as LenType, 208 } 209 } 210 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 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 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. 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. 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 259 unsafe fn _get(&self, idx: usize) -> *mut T::CType { 260 OPENSSL_sk_value(self.as_stack(), idx as LenType) as *mut _ 261 } 262} 263 264impl<T: Stackable> Index<usize> for StackRef<T> { 265 type Output = T::Ref; 266 267 fn index(&self, index: usize) -> &T::Ref { 268 self.get(index).unwrap() 269 } 270} 271 272impl<T: Stackable> IndexMut<usize> for StackRef<T> { 273 fn index_mut(&mut self, index: usize) -> &mut T::Ref { 274 self.get_mut(index).unwrap() 275 } 276} 277 278impl<'a, T: Stackable> iter::IntoIterator for &'a StackRef<T> { 279 type Item = &'a T::Ref; 280 type IntoIter = Iter<'a, T>; 281 282 fn into_iter(self) -> Iter<'a, T> { 283 self.iter() 284 } 285} 286 287impl<'a, T: Stackable> iter::IntoIterator for &'a mut StackRef<T> { 288 type Item = &'a mut T::Ref; 289 type IntoIter = IterMut<'a, T>; 290 291 fn into_iter(self) -> IterMut<'a, T> { 292 self.iter_mut() 293 } 294} 295 296impl<'a, T: Stackable> iter::IntoIterator for &'a Stack<T> { 297 type Item = &'a T::Ref; 298 type IntoIter = Iter<'a, T>; 299 300 fn into_iter(self) -> Iter<'a, T> { 301 self.iter() 302 } 303} 304 305impl<'a, T: Stackable> iter::IntoIterator for &'a mut Stack<T> { 306 type Item = &'a mut T::Ref; 307 type IntoIter = IterMut<'a, T>; 308 309 fn into_iter(self) -> IterMut<'a, T> { 310 self.iter_mut() 311 } 312} 313 314/// An iterator over the stack's contents. 315pub struct Iter<'a, T: Stackable> { 316 stack: &'a StackRef<T>, 317 idxs: Range<LenType>, 318} 319 320impl<'a, T: Stackable> Iterator for Iter<'a, T> { 321 type Item = &'a T::Ref; 322 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 331 fn size_hint(&self) -> (usize, Option<usize>) { 332 self.idxs.size_hint() 333 } 334} 335 336impl<'a, T: Stackable> DoubleEndedIterator for Iter<'a, T> { 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 346impl<'a, T: Stackable> ExactSizeIterator for Iter<'a, T> {} 347 348/// A mutable iterator over the stack's contents. 349pub struct IterMut<'a, T: Stackable> { 350 stack: &'a mut StackRef<T>, 351 idxs: Range<LenType>, 352} 353 354impl<'a, T: Stackable> Iterator for IterMut<'a, T> { 355 type Item = &'a mut T::Ref; 356 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 365 fn size_hint(&self) -> (usize, Option<usize>) { 366 self.idxs.size_hint() 367 } 368} 369 370impl<'a, T: Stackable> DoubleEndedIterator for IterMut<'a, T> { 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 380impl<'a, T: Stackable> ExactSizeIterator for IterMut<'a, T> {} 381