• 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::{unified_sk_free, unified_sk_num, unified_sk_pop, unified_sk_value, STACK};
22 
23 use crate::c_openssl::foreign::{Foreign, ForeignRef, ForeignRefWrapper};
24 
25 pub(crate) trait Stackof: Foreign {
26     type StackType;
27 }
28 
29 pub(crate) struct Stack<T: Stackof>(*mut T::StackType);
30 
31 pub(crate) struct StackRef<T: Stackof>(ForeignRefWrapper, PhantomData<T>);
32 
33 unsafe impl<T: Stackof + Send> Send for Stack<T> {}
34 
35 unsafe impl<T: Stackof + Sync> Sync for Stack<T> {}
36 
37 unsafe impl<T: Stackof + Send> Send for StackRef<T> {}
38 
39 unsafe impl<T: Stackof + Sync> Sync for StackRef<T> {}
40 
41 impl<T: Stackof> Deref for Stack<T> {
42     type Target = StackRef<T>;
43 
deref(&self) -> &StackRef<T>44     fn deref(&self) -> &StackRef<T> {
45         unsafe { StackRef::from_ptr(self.0) }
46     }
47 }
48 
49 impl<T: Stackof> DerefMut for Stack<T> {
deref_mut(&mut self) -> &mut StackRef<T>50     fn deref_mut(&mut self) -> &mut StackRef<T> {
51         unsafe { StackRef::from_ptr_mut(self.0) }
52     }
53 }
54 
55 impl<T: Stackof> AsRef<StackRef<T>> for Stack<T> {
as_ref(&self) -> &StackRef<T>56     fn as_ref(&self) -> &StackRef<T> {
57         self
58     }
59 }
60 
61 impl<T: Stackof> Borrow<StackRef<T>> for Stack<T> {
borrow(&self) -> &StackRef<T>62     fn borrow(&self) -> &StackRef<T> {
63         self
64     }
65 }
66 
67 impl<T: Stackof> Drop for Stack<T> {
drop(&mut self)68     fn drop(&mut self) {
69         unsafe {
70             while self.pop().is_some() {}
71             unified_sk_free(self.0 as *mut _)
72         }
73     }
74 }
75 
76 pub(crate) struct StackRefIter<'a, T: Stackof>
77 where
78     T: 'a,
79 {
80     stack: &'a StackRef<T>,
81     index: Range<c_int>,
82 }
83 
84 impl<'a, T: Stackof> Iterator for StackRefIter<'a, T> {
85     type Item = &'a T::Ref;
86 
next(&mut self) -> Option<&'a T::Ref>87     fn next(&mut self) -> Option<&'a T::Ref> {
88         unsafe {
89             self.index
90                 .next()
91                 .map(|i| T::Ref::from_ptr(unified_sk_value(self.stack.as_stack(), i) as *mut _))
92         }
93     }
94 
size_hint(&self) -> (usize, Option<usize>)95     fn size_hint(&self) -> (usize, Option<usize>) {
96         self.index.size_hint()
97     }
98 }
99 
100 impl<T: Stackof> StackRef<T> {
101     #[allow(clippy::len_without_is_empty)]
len(&self) -> usize102     pub(crate) fn len(&self) -> usize {
103         unsafe { unified_sk_num(self.as_stack()) as usize }
104     }
105 
pop(&mut self) -> Option<T>106     pub(crate) fn pop(&mut self) -> Option<T> {
107         unsafe {
108             let ptr = unified_sk_pop(self.as_stack());
109             match ptr.is_null() {
110                 true => None,
111                 false => Some(T::from_ptr(ptr as *mut _)),
112             }
113         }
114     }
115 }
116 
117 impl<T: Stackof> ForeignRef for StackRef<T> {
118     type CStruct = T::StackType;
119 }
120 
121 impl<T: Stackof> StackRef<T> {
as_stack(&self) -> STACK122     fn as_stack(&self) -> STACK {
123         self.as_ptr() as *mut _
124     }
125 }
126 
127 impl<T: Stackof> Foreign for Stack<T> {
128     type CStruct = T::StackType;
129     type Ref = StackRef<T>;
130 
from_ptr(ptr: *mut Self::CStruct) -> Self131     fn from_ptr(ptr: *mut Self::CStruct) -> Self {
132         Stack(ptr)
133     }
134 
as_ptr(&self) -> *mut Self::CStruct135     fn as_ptr(&self) -> *mut Self::CStruct {
136         self.0
137     }
138 }
139 
140 pub(crate) struct IntoStackIter<T: Stackof> {
141     stack: *mut T::StackType,
142     index: Range<c_int>,
143 }
144 
145 impl<T: Stackof> Iterator for IntoStackIter<T> {
146     type Item = T;
147 
next(&mut self) -> Option<Self::Item>148     fn next(&mut self) -> Option<Self::Item> {
149         unsafe {
150             self.index
151                 .next()
152                 .map(|i| T::from_ptr(unified_sk_value(self.stack as *mut _, i) as *mut _))
153         }
154     }
155 }
156 
157 impl<T: Stackof> Drop for IntoStackIter<T> {
drop(&mut self)158     fn drop(&mut self) {
159         unsafe {
160             while self.next().is_some() {}
161             unified_sk_free(self.stack as *mut _);
162         }
163     }
164 }
165 
166 impl<T: Stackof> IntoIterator for Stack<T> {
167     type Item = T;
168     type IntoIter = IntoStackIter<T>;
169 
into_iter(self) -> IntoStackIter<T>170     fn into_iter(self) -> IntoStackIter<T> {
171         let it = IntoStackIter {
172             stack: self.0,
173             index: 0..self.len() as c_int,
174         };
175         forget(self);
176         it
177     }
178 }
179