• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use core::borrow::Borrow;
15 use core::marker::PhantomData;
16 use core::mem::forget;
17 use core::ops::{Deref, DerefMut, Range};
18 
19 use libc::c_int;
20 
21 use super::ffi::stack::{
22     OPENSSL_sk_free, OPENSSL_sk_num, OPENSSL_sk_pop, OPENSSL_sk_value, OPENSSL_STACK,
23 };
24 use crate::c_openssl::foreign::{Foreign, ForeignRef, ForeignRefWrapper};
25 
26 pub(crate) trait Stackof: Foreign {
27     type StackType;
28 }
29 
30 pub(crate) struct Stack<T: Stackof>(*mut T::StackType);
31 
32 pub(crate) struct StackRef<T: Stackof>(ForeignRefWrapper, PhantomData<T>);
33 
34 unsafe impl<T: Stackof + Send> Send for Stack<T> {}
35 
36 unsafe impl<T: Stackof + Sync> Sync for Stack<T> {}
37 
38 unsafe impl<T: Stackof + Send> Send for StackRef<T> {}
39 
40 unsafe impl<T: Stackof + Sync> Sync for StackRef<T> {}
41 
42 impl<T: Stackof> Deref for Stack<T> {
43     type Target = StackRef<T>;
44 
deref(&self) -> &StackRef<T>45     fn deref(&self) -> &StackRef<T> {
46         unsafe { StackRef::from_ptr(self.0) }
47     }
48 }
49 
50 impl<T: Stackof> DerefMut for Stack<T> {
deref_mut(&mut self) -> &mut StackRef<T>51     fn deref_mut(&mut self) -> &mut StackRef<T> {
52         unsafe { StackRef::from_ptr_mut(self.0) }
53     }
54 }
55 
56 impl<T: Stackof> AsRef<StackRef<T>> for Stack<T> {
as_ref(&self) -> &StackRef<T>57     fn as_ref(&self) -> &StackRef<T> {
58         self
59     }
60 }
61 
62 impl<T: Stackof> Borrow<StackRef<T>> for Stack<T> {
borrow(&self) -> &StackRef<T>63     fn borrow(&self) -> &StackRef<T> {
64         self
65     }
66 }
67 
68 impl<T: Stackof> Drop for Stack<T> {
drop(&mut self)69     fn drop(&mut self) {
70         unsafe {
71             while self.pop().is_some() {}
72             OPENSSL_sk_free(self.0 as *mut _)
73         }
74     }
75 }
76 
77 pub(crate) struct StackRefIter<'a, T: Stackof>
78 where
79     T: 'a,
80 {
81     stack: &'a StackRef<T>,
82     index: Range<c_int>,
83 }
84 
85 impl<'a, T: Stackof> Iterator for StackRefIter<'a, T> {
86     type Item = &'a T::Ref;
87 
next(&mut self) -> Option<&'a T::Ref>88     fn next(&mut self) -> Option<&'a T::Ref> {
89         unsafe {
90             self.index
91                 .next()
92                 .map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
93         }
94     }
95 
size_hint(&self) -> (usize, Option<usize>)96     fn size_hint(&self) -> (usize, Option<usize>) {
97         self.index.size_hint()
98     }
99 }
100 
101 impl<T: Stackof> StackRef<T> {
102     #[allow(clippy::len_without_is_empty)]
len(&self) -> usize103     pub(crate) fn len(&self) -> usize {
104         unsafe { OPENSSL_sk_num(self.as_stack()) as usize }
105     }
106 
pop(&mut self) -> Option<T>107     pub(crate) fn pop(&mut self) -> Option<T> {
108         unsafe {
109             let ptr = OPENSSL_sk_pop(self.as_stack());
110             match ptr.is_null() {
111                 true => None,
112                 false => Some(T::from_ptr(ptr as *mut _)),
113             }
114         }
115     }
116 
iter(&self) -> StackRefIter<T>117     pub(crate) fn iter(&self) -> StackRefIter<T> {
118         StackRefIter {
119             stack: self,
120             index: 0..self.len() as c_int,
121         }
122     }
123 }
124 
125 impl<T: Stackof> ForeignRef for StackRef<T> {
126     type CStruct = T::StackType;
127 }
128 
129 impl<T: Stackof> StackRef<T> {
as_stack(&self) -> *mut OPENSSL_STACK130     fn as_stack(&self) -> *mut OPENSSL_STACK {
131         self.as_ptr() as *mut _
132     }
133 }
134 
135 impl<T: Stackof> Foreign for Stack<T> {
136     type CStruct = T::StackType;
137     type Ref = StackRef<T>;
138 
from_ptr(ptr: *mut Self::CStruct) -> Self139     fn from_ptr(ptr: *mut Self::CStruct) -> Self {
140         Stack(ptr)
141     }
142 
as_ptr(&self) -> *mut Self::CStruct143     fn as_ptr(&self) -> *mut Self::CStruct {
144         self.0
145     }
146 }
147 
148 pub(crate) struct IntoStackIter<T: Stackof> {
149     stack: *mut T::StackType,
150     index: Range<c_int>,
151 }
152 
153 impl<T: Stackof> Iterator for IntoStackIter<T> {
154     type Item = T;
155 
next(&mut self) -> Option<Self::Item>156     fn next(&mut self) -> Option<Self::Item> {
157         unsafe {
158             self.index
159                 .next()
160                 .map(|i| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, i) as *mut _))
161         }
162     }
163 }
164 
165 impl<T: Stackof> Drop for IntoStackIter<T> {
drop(&mut self)166     fn drop(&mut self) {
167         unsafe {
168             while self.next().is_some() {}
169             OPENSSL_sk_free(self.stack as *mut _);
170         }
171     }
172 }
173 
174 impl<T: Stackof> IntoIterator for Stack<T> {
175     type Item = T;
176     type IntoIter = IntoStackIter<T>;
177 
into_iter(self) -> IntoStackIter<T>178     fn into_iter(self) -> IntoStackIter<T> {
179         let it = IntoStackIter {
180             stack: self.0,
181             index: 0..self.len() as c_int,
182         };
183         forget(self);
184         it
185     }
186 }
187