1use crate::{
2 InOut,
3 errors::{IntoArrayError, NotEqualError},
4};
5use core::{marker::PhantomData, ptr, slice};
6use hybrid_array::{Array, ArraySize};
7
8pub struct InOutBuf<'inp, 'out, T> {
12 pub(crate) in_ptr: *const T,
13 pub(crate) out_ptr: *mut T,
14 pub(crate) len: usize,
15 pub(crate) _pd: PhantomData<(&'inp T, &'out mut T)>,
16}
17
18impl<'a, T> From<&'a mut [T]> for InOutBuf<'a, 'a, T> {
19 #[inline(always)]
20 fn from(buf: &'a mut [T]) -> Self {
21 let p = buf.as_mut_ptr();
22 Self {
23 in_ptr: p,
24 out_ptr: p,
25 len: buf.len(),
26 _pd: PhantomData,
27 }
28 }
29}
30
31impl<'a, T> InOutBuf<'a, 'a, T> {
32 #[inline(always)]
34 pub fn from_mut(val: &'a mut T) -> InOutBuf<'a, 'a, T> {
35 let p = ptr::from_mut(val);
36 Self {
37 in_ptr: p,
38 out_ptr: p,
39 len: 1,
40 _pd: PhantomData,
41 }
42 }
43}
44
45impl<'inp, 'out, T> IntoIterator for InOutBuf<'inp, 'out, T> {
46 type Item = InOut<'inp, 'out, T>;
47 type IntoIter = InOutBufIter<'inp, 'out, T>;
48
49 #[inline(always)]
50 fn into_iter(self) -> Self::IntoIter {
51 InOutBufIter { buf: self, pos: 0 }
52 }
53}
54
55impl<'inp, 'out, T> InOutBuf<'inp, 'out, T> {
56 #[inline(always)]
58 pub fn from_ref_mut(in_val: &'inp T, out_val: &'out mut T) -> Self {
59 Self {
60 in_ptr: ptr::from_ref::<T>(in_val),
61 out_ptr: ptr::from_mut::<T>(out_val),
62 len: 1,
63 _pd: PhantomData,
64 }
65 }
66
67 #[inline(always)]
72 pub fn new(in_buf: &'inp [T], out_buf: &'out mut [T]) -> Result<Self, NotEqualError> {
73 if in_buf.len() != out_buf.len() {
74 Err(NotEqualError)
75 } else {
76 Ok(Self {
77 in_ptr: in_buf.as_ptr(),
78 out_ptr: out_buf.as_mut_ptr(),
79 len: in_buf.len(),
80 _pd: Default::default(),
81 })
82 }
83 }
84
85 #[inline(always)]
87 #[must_use]
88 pub fn len(&self) -> usize {
89 self.len
90 }
91
92 #[inline(always)]
94 #[must_use]
95 pub fn is_empty(&self) -> bool {
96 self.len == 0
97 }
98
99 #[inline(always)]
104 pub fn get(&mut self, pos: usize) -> InOut<'_, '_, T> {
105 assert!(pos < self.len);
106 unsafe {
107 InOut {
108 in_ptr: self.in_ptr.add(pos),
109 out_ptr: self.out_ptr.add(pos),
110 _pd: PhantomData,
111 }
112 }
113 }
114
115 #[inline(always)]
117 #[must_use]
118 pub fn get_in(&self) -> &[T] {
119 unsafe { slice::from_raw_parts(self.in_ptr, self.len) }
120 }
121
122 #[inline(always)]
124 pub fn get_out(&mut self) -> &mut [T] {
125 unsafe { slice::from_raw_parts_mut(self.out_ptr, self.len) }
126 }
127
128 #[must_use]
135 pub fn into_out_with_copied_in(self) -> &'out mut [T]
136 where
137 T: Copy,
138 {
139 if !ptr::eq(self.in_ptr, self.out_ptr) {
140 unsafe {
141 ptr::copy(self.in_ptr, self.out_ptr, self.len);
142 }
143 }
144 unsafe { slice::from_raw_parts_mut(self.out_ptr, self.len) }
145 }
146
147 #[inline(always)]
149 #[must_use]
150 pub fn into_out(self) -> &'out mut [T] {
151 unsafe { slice::from_raw_parts_mut(self.out_ptr, self.len) }
152 }
153
154 #[inline(always)]
156 #[must_use]
157 pub fn into_raw(self) -> (*const T, *mut T) {
158 (self.in_ptr, self.out_ptr)
159 }
160
161 #[inline(always)]
163 pub fn reborrow(&mut self) -> InOutBuf<'_, '_, T> {
164 Self {
165 in_ptr: self.in_ptr,
166 out_ptr: self.out_ptr,
167 len: self.len,
168 _pd: PhantomData,
169 }
170 }
171
172 #[inline(always)]
193 pub unsafe fn from_raw(
194 in_ptr: *const T,
195 out_ptr: *mut T,
196 len: usize,
197 ) -> InOutBuf<'inp, 'out, T> {
198 Self {
199 in_ptr,
200 out_ptr,
201 len,
202 _pd: PhantomData,
203 }
204 }
205
206 #[inline(always)]
216 #[must_use]
217 pub fn split_at(self, mid: usize) -> (InOutBuf<'inp, 'out, T>, InOutBuf<'inp, 'out, T>) {
218 assert!(mid <= self.len);
219 let (tail_in_ptr, tail_out_ptr) = unsafe { (self.in_ptr.add(mid), self.out_ptr.add(mid)) };
220 (
221 InOutBuf {
222 in_ptr: self.in_ptr,
223 out_ptr: self.out_ptr,
224 len: mid,
225 _pd: PhantomData,
226 },
227 InOutBuf {
228 in_ptr: tail_in_ptr,
229 out_ptr: tail_out_ptr,
230 len: self.len() - mid,
231 _pd: PhantomData,
232 },
233 )
234 }
235
236 #[inline(always)]
238 #[must_use]
239 pub fn into_chunks<N: ArraySize>(
240 self,
241 ) -> (InOutBuf<'inp, 'out, Array<T, N>>, InOutBuf<'inp, 'out, T>) {
242 let chunks = self.len() / N::USIZE;
243 let tail_pos = N::USIZE * chunks;
244 let tail_len = self.len() - tail_pos;
245 unsafe {
246 let chunks = InOutBuf {
247 in_ptr: self.in_ptr.cast::<Array<T, N>>(),
248 out_ptr: self.out_ptr.cast::<Array<T, N>>(),
249 len: chunks,
250 _pd: PhantomData,
251 };
252 let tail = InOutBuf {
253 in_ptr: self.in_ptr.add(tail_pos),
254 out_ptr: self.out_ptr.add(tail_pos),
255 len: tail_len,
256 _pd: PhantomData,
257 };
258 (chunks, tail)
259 }
260 }
261}
262
263impl InOutBuf<'_, '_, u8> {
264 #[inline(always)]
270 pub fn xor_in2out(&mut self, data: &[u8]) {
271 assert_eq!(self.len(), data.len());
272 unsafe {
273 for i in 0..data.len() {
274 let in_ptr = self.in_ptr.add(i);
275 let out_ptr = self.out_ptr.add(i);
276 *out_ptr = *in_ptr ^ data[i];
277 }
278 }
279 }
280}
281
282impl<'inp, 'out, T, N> TryInto<InOut<'inp, 'out, Array<T, N>>> for InOutBuf<'inp, 'out, T>
283where
284 N: ArraySize,
285{
286 type Error = IntoArrayError;
287
288 #[inline(always)]
289 fn try_into(self) -> Result<InOut<'inp, 'out, Array<T, N>>, Self::Error> {
290 if self.len() == N::USIZE {
291 Ok(InOut {
292 in_ptr: self.in_ptr.cast(),
293 out_ptr: self.out_ptr.cast(),
294 _pd: PhantomData,
295 })
296 } else {
297 Err(IntoArrayError)
298 }
299 }
300}
301
302pub struct InOutBufIter<'inp, 'out, T> {
304 buf: InOutBuf<'inp, 'out, T>,
305 pos: usize,
306}
307
308impl<'inp, 'out, T> Iterator for InOutBufIter<'inp, 'out, T> {
309 type Item = InOut<'inp, 'out, T>;
310
311 #[inline(always)]
312 fn next(&mut self) -> Option<Self::Item> {
313 if self.buf.len() == self.pos {
314 return None;
315 }
316 let res = unsafe {
317 InOut {
318 in_ptr: self.buf.in_ptr.add(self.pos),
319 out_ptr: self.buf.out_ptr.add(self.pos),
320 _pd: PhantomData,
321 }
322 };
323 self.pos += 1;
324 Some(res)
325 }
326}