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