Skip to main content

rama_boring/
stack.rs

1use crate::ffi;
2use crate::libc_types::size_t;
3use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
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.cast());
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.cast()))
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.cast());
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.cast(), i).cast()))
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.cast(), i).cast()))
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().cast()
180    }
181
182    /// Returns the number of items in the stack.
183    #[must_use]
184    pub fn len(&self) -> usize {
185        unsafe { OPENSSL_sk_num(self.as_stack()) }
186    }
187
188    /// Determines if the stack is empty.
189    #[must_use]
190    pub fn is_empty(&self) -> bool {
191        self.len() == 0
192    }
193
194    #[must_use]
195    pub fn iter(&self) -> Iter<'_, T> {
196        Iter {
197            stack: self,
198            idxs: 0..self.len(),
199        }
200    }
201
202    pub fn iter_mut(&mut self) -> IterMut<'_, T> {
203        IterMut {
204            idxs: 0..self.len(),
205            stack: self,
206        }
207    }
208
209    /// Returns a reference to the element at the given index in the
210    /// stack or `None` if the index is out of bounds
211    #[must_use]
212    pub fn get(&self, idx: usize) -> Option<&T::Ref> {
213        unsafe {
214            if idx >= self.len() {
215                return None;
216            }
217
218            Some(T::Ref::from_ptr(self._get(idx)))
219        }
220    }
221
222    /// Returns a mutable reference to the element at the given index in the
223    /// stack or `None` if the index is out of bounds
224    pub fn get_mut(&mut self, idx: usize) -> Option<&mut T::Ref> {
225        unsafe {
226            if idx >= self.len() {
227                return None;
228            }
229
230            Some(T::Ref::from_ptr_mut(self._get(idx)))
231        }
232    }
233
234    /// Pushes a value onto the top of the stack.
235    pub fn push(&mut self, data: T) -> Result<(), ErrorStack> {
236        unsafe {
237            cvt_0(OPENSSL_sk_push(self.as_stack(), data.as_ptr().cast()))?;
238            mem::forget(data);
239            Ok(())
240        }
241    }
242
243    /// Removes the last element from the stack and returns it.
244    pub fn pop(&mut self) -> Option<T> {
245        unsafe {
246            let ptr = OPENSSL_sk_pop(self.as_stack());
247            if ptr.is_null() {
248                None
249            } else {
250                Some(T::from_ptr(ptr.cast()))
251            }
252        }
253    }
254
255    unsafe fn _get(&self, idx: usize) -> *mut T::CType {
256        OPENSSL_sk_value(self.as_stack(), idx).cast()
257    }
258}
259
260impl<T: Stackable> Index<usize> for StackRef<T> {
261    type Output = T::Ref;
262
263    fn index(&self, index: usize) -> &T::Ref {
264        self.get(index).unwrap()
265    }
266}
267
268impl<T: Stackable> IndexMut<usize> for StackRef<T> {
269    fn index_mut(&mut self, index: usize) -> &mut T::Ref {
270        self.get_mut(index).unwrap()
271    }
272}
273
274impl<'a, T: Stackable> iter::IntoIterator for &'a StackRef<T> {
275    type Item = &'a T::Ref;
276    type IntoIter = Iter<'a, T>;
277
278    fn into_iter(self) -> Iter<'a, T> {
279        self.iter()
280    }
281}
282
283impl<'a, T: Stackable> iter::IntoIterator for &'a mut StackRef<T> {
284    type Item = &'a mut T::Ref;
285    type IntoIter = IterMut<'a, T>;
286
287    fn into_iter(self) -> IterMut<'a, T> {
288        self.iter_mut()
289    }
290}
291
292impl<'a, T: Stackable> iter::IntoIterator for &'a Stack<T> {
293    type Item = &'a T::Ref;
294    type IntoIter = Iter<'a, T>;
295
296    fn into_iter(self) -> Iter<'a, T> {
297        self.iter()
298    }
299}
300
301impl<'a, T: Stackable> iter::IntoIterator for &'a mut Stack<T> {
302    type Item = &'a mut T::Ref;
303    type IntoIter = IterMut<'a, T>;
304
305    fn into_iter(self) -> IterMut<'a, T> {
306        self.iter_mut()
307    }
308}
309
310/// An iterator over the stack's contents.
311pub struct Iter<'a, T: Stackable>
312where
313    T: 'a,
314{
315    stack: &'a StackRef<T>,
316    idxs: Range<size_t>,
317}
318
319impl<'a, T: Stackable> Iterator for Iter<'a, T> {
320    type Item = &'a T::Ref;
321
322    fn next(&mut self) -> Option<&'a T::Ref> {
323        unsafe {
324            self.idxs
325                .next()
326                .map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i).cast()))
327        }
328    }
329
330    fn size_hint(&self) -> (usize, Option<usize>) {
331        self.idxs.size_hint()
332    }
333}
334
335impl<'a, T: Stackable> DoubleEndedIterator for Iter<'a, T> {
336    fn next_back(&mut self) -> Option<&'a T::Ref> {
337        unsafe {
338            self.idxs
339                .next_back()
340                .map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i).cast()))
341        }
342    }
343}
344
345impl<T: Stackable> ExactSizeIterator for Iter<'_, T> {}
346
347/// A mutable iterator over the stack's contents.
348pub struct IterMut<'a, T: Stackable + 'a> {
349    stack: &'a mut StackRef<T>,
350    idxs: Range<size_t>,
351}
352
353impl<'a, T: Stackable> Iterator for IterMut<'a, T> {
354    type Item = &'a mut T::Ref;
355
356    fn next(&mut self) -> Option<&'a mut T::Ref> {
357        unsafe {
358            self.idxs
359                .next()
360                .map(|i| T::Ref::from_ptr_mut(OPENSSL_sk_value(self.stack.as_stack(), i).cast()))
361        }
362    }
363
364    fn size_hint(&self) -> (usize, Option<usize>) {
365        self.idxs.size_hint()
366    }
367}
368
369impl<'a, T: Stackable> DoubleEndedIterator for IterMut<'a, T> {
370    fn next_back(&mut self) -> Option<&'a mut T::Ref> {
371        unsafe {
372            self.idxs
373                .next_back()
374                .map(|i| T::Ref::from_ptr_mut(OPENSSL_sk_value(self.stack.as_stack(), i).cast()))
375        }
376    }
377}
378
379impl<T: Stackable> ExactSizeIterator for IterMut<'_, T> {}