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 | { |
53 | 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> { |
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> { |
67 | pub fn new() -> Result<Stack<T>, ErrorStack> { |
68 | unsafe { |
69 | ffi::init(); |
70 | let ptr: *mut OPENSSL_STACK = 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 | |
80 | fn into_iter(self) -> IntoIter<T> { |
81 | let it: IntoIter = 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> { |
91 | fn as_ref(&self) -> &StackRef<T> { |
92 | self |
93 | } |
94 | } |
95 | |
96 | impl<T: Stackable> Borrow<StackRef<T>> for Stack<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 ] |
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 | |
122 | impl<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 | |
130 | impl<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 | |
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> { |
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 | |
155 | fn next(&mut self) -> Option<T> { |
156 | unsafe { |
157 | self.idxs |
158 | .next() |
159 | .map(|i: i32| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, idx:i) as *mut _)) |
160 | } |
161 | } |
162 | |
163 | fn size_hint(&self) -> (usize, Option<usize>) { |
164 | self.idxs.size_hint() |
165 | } |
166 | } |
167 | |
168 | impl<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: i32| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, idx: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> { |
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 | |
264 | impl<T: Stackable> Index<usize> for StackRef<T> { |
265 | type Output = T::Ref; |
266 | |
267 | fn index(&self, index: usize) -> &T::Ref { |
268 | self.get(idx:index).unwrap() |
269 | } |
270 | } |
271 | |
272 | impl<T: Stackable> IndexMut<usize> for StackRef<T> { |
273 | fn index_mut(&mut self, index: usize) -> &mut T::Ref { |
274 | self.get_mut(idx: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 | |
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 | |
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 | |
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 | |
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 | |
323 | fn next(&mut self) -> Option<&'a T::Ref> { |
324 | unsafe { |
325 | self.idxs |
326 | .next() |
327 | .map(|i: i32| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), idx:i) as *mut _)) |
328 | } |
329 | } |
330 | |
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> { |
337 | fn next_back(&mut self) -> Option<&'a T::Ref> { |
338 | unsafe { |
339 | self.idxs |
340 | .next_back() |
341 | .map(|i: i32| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), idx: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 | |
357 | fn next(&mut self) -> Option<&'a mut T::Ref> { |
358 | unsafe { |
359 | self.idxs |
360 | .next() |
361 | .map(|i: i32| T::Ref::from_ptr_mut(ptr:OPENSSL_sk_value(self.stack.as_stack(), idx:i) as *mut _)) |
362 | } |
363 | } |
364 | |
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> { |
371 | fn next_back(&mut self) -> Option<&'a mut T::Ref> { |
372 | unsafe { |
373 | self.idxs |
374 | .next_back() |
375 | .map(|i: i32| T::Ref::from_ptr_mut(ptr:OPENSSL_sk_value(self.stack.as_stack(), idx:i) as *mut _)) |
376 | } |
377 | } |
378 | } |
379 | |
380 | impl<'a, T: Stackable> ExactSizeIterator for IterMut<'a, T> {} |
381 | |