boring_imp/
stack.rs

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