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