1use core::marker::PhantomData;
2
3use crate::{Split, SplitInplace, SplitProcess};
4
5#[derive(Clone, Copy, Debug, Default)]
10pub struct FrameMajor;
11
12#[derive(Clone, Copy, Debug, Default)]
17pub struct LaneMajor;
18
19#[derive(Clone, Copy, Debug)]
24pub struct View<'a, T, Layout, const L: usize> {
25 flat: &'a [T],
26 frames: usize,
27 _layout: PhantomData<Layout>,
28}
29
30#[derive(Debug)]
32pub struct ViewMut<'a, T, Layout, const L: usize> {
33 flat: &'a mut [T],
34 frames: usize,
35 _layout: PhantomData<Layout>,
36}
37
38#[derive(Clone, Copy, Debug, Default)]
49pub struct PerFrame<C>(pub C);
50
51impl<'a, T, Layout, const L: usize> View<'a, T, Layout, L> {
52 #[must_use]
54 pub fn flat(self) -> &'a [T] {
55 self.flat
56 }
57
58 #[must_use]
60 pub const fn frames(self) -> usize {
61 self.frames
62 }
63
64 #[must_use]
66 pub fn as_layout<Other>(self) -> View<'a, T, Other, L> {
67 View {
68 flat: self.flat,
69 frames: self.frames,
70 _layout: PhantomData,
71 }
72 }
73}
74
75impl<'a, T, Layout, const L: usize> ViewMut<'a, T, Layout, L> {
76 #[must_use]
78 pub fn flat(&self) -> &[T] {
79 self.flat
80 }
81
82 #[must_use]
84 pub fn flat_mut(&mut self) -> &mut [T] {
85 self.flat
86 }
87
88 #[must_use]
90 pub const fn frames(&self) -> usize {
91 self.frames
92 }
93
94 #[must_use]
96 pub fn as_layout<Other>(self) -> ViewMut<'a, T, Other, L> {
97 let Self { flat, frames, .. } = self;
98 ViewMut {
99 flat,
100 frames,
101 _layout: PhantomData,
102 }
103 }
104}
105
106impl<'a, T, const L: usize> View<'a, T, FrameMajor, L> {
107 #[must_use]
109 pub fn from_frames(frames: &'a [[T; L]]) -> Self {
110 Self {
111 flat: frames.as_flattened(),
112 frames: frames.len(),
113 _layout: PhantomData,
114 }
115 }
116
117 #[must_use]
119 pub fn as_frames(self) -> &'a [[T; L]] {
120 let (frames, []) = self.flat.as_chunks::<L>() else {
121 unreachable!()
122 };
123 frames
124 }
125
126 #[must_use]
128 pub fn frame(self, i: usize) -> &'a [T; L] {
129 &self.as_frames()[i]
130 }
131}
132
133impl<'a, T, const L: usize> ViewMut<'a, T, FrameMajor, L> {
134 #[must_use]
136 pub fn from_frames(frames: &'a mut [[T; L]]) -> Self {
137 let frames_len = frames.len();
138 Self {
139 flat: frames.as_flattened_mut(),
140 frames: frames_len,
141 _layout: PhantomData,
142 }
143 }
144
145 #[must_use]
147 pub fn as_frames(&self) -> &[[T; L]] {
148 let (frames, []) = self.flat.as_chunks::<L>() else {
149 unreachable!()
150 };
151 frames
152 }
153
154 #[must_use]
156 pub fn as_frames_mut(&mut self) -> &mut [[T; L]] {
157 let (frames, []) = self.flat.as_chunks_mut::<L>() else {
158 unreachable!()
159 };
160 frames
161 }
162
163 #[must_use]
165 pub fn frame(&self, i: usize) -> &[T; L] {
166 &self.as_frames()[i]
167 }
168
169 #[must_use]
171 pub fn frame_mut(&mut self, i: usize) -> &mut [T; L] {
172 &mut self.as_frames_mut()[i]
173 }
174}
175
176impl<'a, T, const L: usize> View<'a, T, LaneMajor, L> {
177 #[must_use]
181 pub fn from_flat(flat: &'a [T], frames: usize) -> Self {
182 assert_eq!(flat.len(), frames * L);
183 Self {
184 flat,
185 frames,
186 _layout: PhantomData,
187 }
188 }
189
190 #[must_use]
192 pub fn lane(self, i: usize) -> &'a [T] {
193 let start = i * self.frames;
194 &self.flat[start..start + self.frames]
195 }
196}
197
198impl<'a, T, const L: usize> ViewMut<'a, T, LaneMajor, L> {
199 #[must_use]
203 pub fn from_flat(flat: &'a mut [T], frames: usize) -> Self {
204 assert_eq!(flat.len(), frames * L);
205 Self {
206 flat,
207 frames,
208 _layout: PhantomData,
209 }
210 }
211
212 #[must_use]
214 pub fn lane(&self, i: usize) -> &[T] {
215 let start = i * self.frames;
216 &self.flat[start..start + self.frames]
217 }
218
219 #[must_use]
221 pub fn lane_mut(&mut self, i: usize) -> &mut [T] {
222 let start = i * self.frames;
223 &mut self.flat[start..start + self.frames]
224 }
225}
226
227pub trait ViewProcess<X, Y = X> {
246 fn process_view(&mut self, x: X, y: Y);
248}
249
250pub trait ViewInplace<X> {
252 fn inplace_view(&mut self, xy: X);
254}
255
256pub trait SplitViewProcess<X, Y = X, S: ?Sized = ()> {
258 fn process_view(&self, state: &mut S, x: X, y: Y);
260}
261
262pub trait SplitViewInplace<X, S: ?Sized = ()> {
264 fn inplace_view(&self, state: &mut S, xy: X);
266}
267
268impl<'a, 'b, X, Y, S: ?Sized, T, const L: usize>
269 SplitViewProcess<View<'a, X, FrameMajor, L>, ViewMut<'b, Y, FrameMajor, L>, S> for T
270where
271 X: Copy,
272 T: SplitProcess<X, Y, S>,
273{
274 fn process_view(
275 &self,
276 state: &mut S,
277 x: View<'a, X, FrameMajor, L>,
278 mut y: ViewMut<'b, Y, FrameMajor, L>,
279 ) {
280 debug_assert_eq!(x.frames(), y.frames());
281 SplitProcess::block(self, state, x.flat(), y.flat_mut());
282 }
283}
284
285impl<'a, X, S: ?Sized, T, const L: usize> SplitViewInplace<ViewMut<'a, X, FrameMajor, L>, S> for T
286where
287 X: Copy,
288 T: SplitInplace<X, S>,
289{
290 fn inplace_view(&self, state: &mut S, mut xy: ViewMut<'a, X, FrameMajor, L>) {
291 SplitInplace::inplace(self, state, xy.flat_mut());
292 }
293}
294
295impl<X, Y, C, S> ViewProcess<X, Y> for Split<C, S>
296where
297 C: SplitViewProcess<X, Y, S>,
298{
299 fn process_view(&mut self, x: X, y: Y) {
300 self.config.process_view(&mut self.state, x, y);
301 }
302}
303
304impl<X, C, S> ViewInplace<X> for Split<C, S>
305where
306 C: SplitViewInplace<X, S>,
307{
308 fn inplace_view(&mut self, xy: X) {
309 self.config.inplace_view(&mut self.state, xy);
310 }
311}
312
313impl<C, S> Split<PerFrame<C>, S> {
314 pub fn process_frames<'a, 'b, X, Y, const Q: usize, const R: usize>(
330 &mut self,
331 x: View<'a, X, FrameMajor, Q>,
332 mut y: ViewMut<'b, Y, FrameMajor, R>,
333 ) where
334 X: Copy,
335 C: SplitProcess<[X; Q], [Y; R], S>,
336 {
337 debug_assert_eq!(x.frames(), y.frames());
338 self.config
339 .0
340 .block(&mut self.state, x.as_frames(), y.as_frames_mut());
341 }
342
343 pub fn inplace_frames<'a, X, const L: usize>(&mut self, mut xy: ViewMut<'a, X, FrameMajor, L>)
345 where
346 X: Copy,
347 C: SplitInplace<[X; L], S>,
348 {
349 self.config.0.inplace(&mut self.state, xy.as_frames_mut());
350 }
351}