]> git.proxmox.com Git - cargo.git/blob - vendor/openssl/src/stack.rs
New upstream version 0.52.0
[cargo.git] / vendor / openssl / src / stack.rs
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};
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 = 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 {
82 stack: self.0,
83 idxs: 0..self.len() as c_int,
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<c_int>,
139 }
140
141 impl<T: Stackable> Drop for IntoIter<T> {
142 fn drop(&mut self) {
143 unsafe {
144 while let Some(_) = self.next() {}
145 OPENSSL_sk_free(self.stack as *mut _);
146 }
147 }
148 }
149
150 impl<T: Stackable> Iterator for IntoIter<T> {
151 type Item = T;
152
153 fn next(&mut self) -> Option<T> {
154 unsafe {
155 self.idxs
156 .next()
157 .map(|i| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, i) as *mut _))
158 }
159 }
160
161 fn size_hint(&self) -> (usize, Option<usize>) {
162 self.idxs.size_hint()
163 }
164 }
165
166 impl<T: Stackable> DoubleEndedIterator for IntoIter<T> {
167 fn next_back(&mut self) -> Option<T> {
168 unsafe {
169 self.idxs
170 .next_back()
171 .map(|i| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, i) as *mut _))
172 }
173 }
174 }
175
176 impl<T: Stackable> ExactSizeIterator for IntoIter<T> {}
177
178 pub struct StackRef<T: Stackable>(Opaque, PhantomData<T>);
179
180 unsafe impl<T: Stackable + Send> Send for StackRef<T> {}
181 unsafe impl<T: Stackable + Sync> Sync for StackRef<T> {}
182
183 impl<T: Stackable> ForeignTypeRef for StackRef<T> {
184 type CType = T::StackType;
185 }
186
187 impl<T: Stackable> StackRef<T> {
188 fn as_stack(&self) -> *mut OPENSSL_STACK {
189 self.as_ptr() as *mut _
190 }
191
192 /// Returns the number of items in the stack.
193 pub fn len(&self) -> usize {
194 unsafe { OPENSSL_sk_num(self.as_stack()) as usize }
195 }
196
197 /// Determines if the stack is empty.
198 pub fn is_empty(&self) -> bool {
199 self.len() == 0
200 }
201
202 pub fn iter(&self) -> Iter<'_, T> {
203 Iter {
204 stack: self,
205 idxs: 0..self.len() as c_int,
206 }
207 }
208
209 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
210 IterMut {
211 idxs: 0..self.len() as c_int,
212 stack: self,
213 }
214 }
215
216 /// Returns a reference to the element at the given index in the
217 /// stack or `None` if the index is out of bounds
218 pub fn get(&self, idx: usize) -> Option<&T::Ref> {
219 unsafe {
220 if idx >= self.len() {
221 return None;
222 }
223
224 Some(T::Ref::from_ptr(self._get(idx)))
225 }
226 }
227
228 /// Returns a mutable reference to the element at the given index in the
229 /// stack or `None` if the index is out of bounds
230 pub fn get_mut(&mut self, idx: usize) -> Option<&mut T::Ref> {
231 unsafe {
232 if idx >= self.len() {
233 return None;
234 }
235
236 Some(T::Ref::from_ptr_mut(self._get(idx)))
237 }
238 }
239
240 /// Pushes a value onto the top of the stack.
241 pub fn push(&mut self, data: T) -> Result<(), ErrorStack> {
242 unsafe {
243 cvt(OPENSSL_sk_push(self.as_stack(), data.as_ptr() as *mut _))?;
244 mem::forget(data);
245 Ok(())
246 }
247 }
248
249 /// Removes the last element from the stack and returns it.
250 pub fn pop(&mut self) -> Option<T> {
251 unsafe {
252 let ptr = OPENSSL_sk_pop(self.as_stack());
253 T::from_ptr_opt(ptr as *mut _)
254 }
255 }
256
257 unsafe fn _get(&self, idx: usize) -> *mut T::CType {
258 OPENSSL_sk_value(self.as_stack(), idx as c_int) as *mut _
259 }
260 }
261
262 impl<T: Stackable> Index<usize> for StackRef<T> {
263 type Output = T::Ref;
264
265 fn index(&self, index: usize) -> &T::Ref {
266 self.get(index).unwrap()
267 }
268 }
269
270 impl<T: Stackable> IndexMut<usize> for StackRef<T> {
271 fn index_mut(&mut self, index: usize) -> &mut T::Ref {
272 self.get_mut(index).unwrap()
273 }
274 }
275
276 impl<'a, T: Stackable> iter::IntoIterator for &'a StackRef<T> {
277 type Item = &'a T::Ref;
278 type IntoIter = Iter<'a, T>;
279
280 fn into_iter(self) -> Iter<'a, T> {
281 self.iter()
282 }
283 }
284
285 impl<'a, T: Stackable> iter::IntoIterator for &'a mut StackRef<T> {
286 type Item = &'a mut T::Ref;
287 type IntoIter = IterMut<'a, T>;
288
289 fn into_iter(self) -> IterMut<'a, T> {
290 self.iter_mut()
291 }
292 }
293
294 impl<'a, T: Stackable> iter::IntoIterator for &'a Stack<T> {
295 type Item = &'a T::Ref;
296 type IntoIter = Iter<'a, T>;
297
298 fn into_iter(self) -> Iter<'a, T> {
299 self.iter()
300 }
301 }
302
303 impl<'a, T: Stackable> iter::IntoIterator for &'a mut Stack<T> {
304 type Item = &'a mut T::Ref;
305 type IntoIter = IterMut<'a, T>;
306
307 fn into_iter(self) -> IterMut<'a, T> {
308 self.iter_mut()
309 }
310 }
311
312 /// An iterator over the stack's contents.
313 pub struct Iter<'a, T: Stackable> {
314 stack: &'a StackRef<T>,
315 idxs: Range<c_int>,
316 }
317
318 impl<'a, T: Stackable> Iterator for Iter<'a, T> {
319 type Item = &'a T::Ref;
320
321 fn next(&mut self) -> Option<&'a T::Ref> {
322 unsafe {
323 self.idxs
324 .next()
325 .map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
326 }
327 }
328
329 fn size_hint(&self) -> (usize, Option<usize>) {
330 self.idxs.size_hint()
331 }
332 }
333
334 impl<'a, T: Stackable> DoubleEndedIterator for Iter<'a, T> {
335 fn next_back(&mut self) -> Option<&'a T::Ref> {
336 unsafe {
337 self.idxs
338 .next_back()
339 .map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
340 }
341 }
342 }
343
344 impl<'a, T: Stackable> ExactSizeIterator for Iter<'a, T> {}
345
346 /// A mutable iterator over the stack's contents.
347 pub struct IterMut<'a, T: Stackable> {
348 stack: &'a mut StackRef<T>,
349 idxs: Range<c_int>,
350 }
351
352 impl<'a, T: Stackable> Iterator for IterMut<'a, T> {
353 type Item = &'a mut T::Ref;
354
355 fn next(&mut self) -> Option<&'a mut T::Ref> {
356 unsafe {
357 self.idxs
358 .next()
359 .map(|i| T::Ref::from_ptr_mut(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
360 }
361 }
362
363 fn size_hint(&self) -> (usize, Option<usize>) {
364 self.idxs.size_hint()
365 }
366 }
367
368 impl<'a, T: Stackable> DoubleEndedIterator for IterMut<'a, T> {
369 fn next_back(&mut self) -> Option<&'a mut T::Ref> {
370 unsafe {
371 self.idxs
372 .next_back()
373 .map(|i| T::Ref::from_ptr_mut(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
374 }
375 }
376 }
377
378 impl<'a, T: Stackable> ExactSizeIterator for IterMut<'a, T> {}