1use crate::InOutBuf;
2use core::{marker::PhantomData, ops::Mul, ptr};
3use hybrid_array::{Array, ArraySize, typenum::Prod};
4
5pub struct InOut<'inp, 'out, T> {
8 pub(crate) in_ptr: *const T,
9 pub(crate) out_ptr: *mut T,
10 pub(crate) _pd: PhantomData<(&'inp T, &'out mut T)>,
11}
12
13impl<'inp, 'out, T> InOut<'inp, 'out, T> {
14 #[inline(always)]
16 pub fn reborrow(&mut self) -> InOut<'_, '_, T> {
17 Self {
18 in_ptr: self.in_ptr,
19 out_ptr: self.out_ptr,
20 _pd: PhantomData,
21 }
22 }
23
24 #[inline(always)]
26 #[must_use]
27 pub fn get_in(&self) -> &T {
28 unsafe { &*self.in_ptr }
29 }
30
31 #[inline(always)]
33 pub fn get_out(&mut self) -> &mut T {
34 unsafe { &mut *self.out_ptr }
35 }
36
37 #[must_use]
44 pub fn into_out_with_copied_in(self) -> &'out mut T
45 where
46 T: Copy,
47 {
48 if !ptr::eq(self.in_ptr, self.out_ptr) {
49 unsafe {
50 ptr::copy(self.in_ptr, self.out_ptr, 1);
51 }
52 }
53 unsafe { &mut *self.out_ptr }
54 }
55
56 #[inline(always)]
58 #[must_use]
59 pub fn into_out(self) -> &'out mut T {
60 unsafe { &mut *self.out_ptr }
61 }
62
63 #[inline(always)]
65 #[must_use]
66 pub fn into_raw(self) -> (*const T, *mut T) {
67 (self.in_ptr, self.out_ptr)
68 }
69
70 #[inline(always)]
89 pub unsafe fn from_raw(in_ptr: *const T, out_ptr: *mut T) -> InOut<'inp, 'out, T> {
90 Self {
91 in_ptr,
92 out_ptr,
93 _pd: PhantomData,
94 }
95 }
96}
97
98impl<T: Clone> InOut<'_, '_, T> {
99 #[inline(always)]
101 #[must_use]
102 pub fn clone_in(&self) -> T {
103 unsafe { (*self.in_ptr).clone() }
104 }
105}
106
107impl<'a, T> From<&'a mut T> for InOut<'a, 'a, T> {
108 #[inline(always)]
109 fn from(val: &'a mut T) -> Self {
110 let p = ptr::from_mut(val);
111 Self {
112 in_ptr: p,
113 out_ptr: p,
114 _pd: PhantomData,
115 }
116 }
117}
118
119impl<'inp, 'out, T> From<(&'inp T, &'out mut T)> for InOut<'inp, 'out, T> {
120 #[inline(always)]
121 fn from((in_val, out_val): (&'inp T, &'out mut T)) -> Self {
122 Self {
123 in_ptr: ptr::from_ref::<T>(in_val),
124 out_ptr: ptr::from_mut::<T>(out_val),
125 _pd: Default::default(),
126 }
127 }
128}
129
130impl<'inp, 'out, T, N: ArraySize> InOut<'inp, 'out, Array<T, N>> {
131 #[inline(always)]
136 pub fn get(&mut self, pos: usize) -> InOut<'_, '_, T> {
137 assert!(pos < N::USIZE);
138 unsafe {
139 InOut {
140 in_ptr: self.in_ptr.cast::<T>().add(pos),
141 out_ptr: self.out_ptr.cast::<T>().add(pos),
142 _pd: PhantomData,
143 }
144 }
145 }
146
147 #[inline(always)]
149 #[must_use]
150 pub fn into_buf(self) -> InOutBuf<'inp, 'out, T> {
151 InOutBuf {
152 in_ptr: self.in_ptr.cast::<T>(),
153 out_ptr: self.out_ptr.cast::<T>(),
154 len: N::USIZE,
155 _pd: PhantomData,
156 }
157 }
158}
159
160impl<'inp, 'out, T, N, M> From<InOut<'inp, 'out, Array<T, Prod<N, M>>>>
161 for Array<InOut<'inp, 'out, Array<T, N>>, M>
162where
163 N: ArraySize,
164 M: ArraySize,
165 N: Mul<M>,
166 Prod<N, M>: ArraySize,
167{
168 fn from(buf: InOut<'inp, 'out, Array<T, Prod<N, M>>>) -> Self {
169 let in_ptr: *const Array<T, N> = buf.in_ptr.cast();
170 let out_ptr: *mut Array<T, N> = buf.out_ptr.cast();
171
172 Array::from_fn(|i| unsafe {
173 InOut {
174 in_ptr: in_ptr.add(i),
175 out_ptr: out_ptr.add(i),
176 _pd: PhantomData,
177 }
178 })
179 }
180}
181
182impl<N: ArraySize> InOut<'_, '_, Array<u8, N>> {
183 #[inline(always)]
189 pub fn xor_in2out(&mut self, data: &Array<u8, N>) {
190 unsafe {
191 let input = ptr::read(self.in_ptr);
192 let mut temp = Array::<u8, N>::default();
193 for i in 0..N::USIZE {
194 temp[i] = input[i] ^ data[i];
195 }
196 ptr::write(self.out_ptr, temp);
197 }
198 }
199}
200
201impl<N, M> InOut<'_, '_, Array<Array<u8, N>, M>>
202where
203 N: ArraySize,
204 M: ArraySize,
205{
206 #[inline(always)]
212 pub fn xor_in2out(&mut self, data: &Array<Array<u8, N>, M>) {
213 unsafe {
214 let input = ptr::read(self.in_ptr);
215 let mut temp = Array::<Array<u8, N>, M>::default();
216 for i in 0..M::USIZE {
217 for j in 0..N::USIZE {
218 temp[i][j] = input[i][j] ^ data[i][j];
219 }
220 }
221 ptr::write(self.out_ptr, temp);
222 }
223 }
224}