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