1use core::ops::{Bound, Index, IndexMut, Range, RangeBounds};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub struct Region<'a, T>(&'a [T], &'a [T]);
13
14impl<'a, T> Region<'a, T> {
15 #[inline]
19 pub fn new(slice_0: &'a [T], slice_1: &'a [T]) -> Self {
20 Region(slice_0, slice_1)
21 }
22
23 #[inline]
25 pub fn is_empty(&self) -> bool {
26 self.0.is_empty() && self.1.is_empty()
27 }
28
29 #[inline]
31 pub fn len(&self) -> usize {
32 self.0.len() + self.1.len()
33 }
34
35 pub fn iter(&self) -> impl Iterator<Item = &'a T> + 'a {
39 [self.0.iter(), self.1.iter()].into_iter().flatten()
40 }
41
42 #[inline]
47 pub fn contiguous(&self) -> &'a [T] {
48 if self.0.is_empty() {
49 self.1
50 } else {
51 self.0
52 }
53 }
54
55 pub fn slice<R>(&self, range: R) -> Self
60 where
61 R: RangeBounds<usize>,
62 {
63 let (range_0, range_1) = self.slice_ranges(range);
64
65 let slice_0 = &self.0[range_0];
66 let slice_1 = &self.1[range_1];
67
68 Region(slice_0, slice_1)
69 }
70
71 fn slice_ranges<R>(&self, range: R) -> (Range<usize>, Range<usize>)
72 where
73 R: RangeBounds<usize>,
74 {
75 let start_inclusive = match range.start_bound() {
76 Bound::Included(v) => *v,
77 Bound::Excluded(v) => v.saturating_add(1),
78 Bound::Unbounded => 0,
79 };
80 let end_exclusive = match range.end_bound() {
81 Bound::Included(v) => v.saturating_add(1),
82 Bound::Excluded(v) => *v,
83 Bound::Unbounded => self.len(),
84 };
85
86 let mid = self.0.len();
87 let slice_0 = start_inclusive.min(mid)..end_exclusive.min(mid);
88 let slice_1 = (start_inclusive - slice_0.start)..(end_exclusive - slice_0.end);
89
90 (slice_0, slice_1)
91 }
92}
93
94impl<'a, T> Region<'a, T>
95where
96 T: Copy,
97{
98 pub fn copy_to_slice(&self, dest: &mut [T]) {
109 assert_eq!(
110 self.len(),
111 dest.len(),
112 "destination and source slices have different lengths"
113 );
114
115 let (dest_0, dest_1) = dest.split_at_mut(self.0.len());
116 dest_0.copy_from_slice(self.0);
117 dest_1.copy_from_slice(self.1);
118 }
119}
120
121impl<'a, T> Region<'a, T>
122where
123 T: Clone,
124{
125 pub fn clone_to_slice(&self, dest: &mut [T]) {
132 assert_eq!(
133 self.len(),
134 dest.len(),
135 "destination and source slices have different lengths"
136 );
137
138 let (dest_0, dest_1) = dest.split_at_mut(self.0.len());
139 dest_0.clone_from_slice(self.0);
140 dest_1.clone_from_slice(self.1);
141 }
142}
143
144impl<'a, T> Default for Region<'a, T> {
145 #[inline]
146 fn default() -> Self {
147 Region(Default::default(), Default::default())
148 }
149}
150
151impl<'a, T> Index<usize> for Region<'a, T> {
152 type Output = T;
153
154 fn index(&self, index: usize) -> &Self::Output {
155 if index >= self.0.len() {
156 &self.1[index - self.0.len()]
157 } else {
158 &self.0[index]
159 }
160 }
161}
162
163#[derive(Debug, PartialEq, Eq, Hash)]
169pub struct RegionMut<'a, T>(&'a mut [T], &'a mut [T]);
170
171impl<'a, T> RegionMut<'a, T> {
172 #[inline]
176 pub fn new(slice_0: &'a mut [T], slice_1: &'a mut [T]) -> Self {
177 RegionMut(slice_0, slice_1)
178 }
179
180 #[inline]
182 pub fn as_ref(&self) -> Region<T> {
183 Region(self.0, self.1)
184 }
185
186 #[inline]
188 pub fn is_empty(&self) -> bool {
189 self.as_ref().is_empty()
190 }
191
192 #[inline]
194 pub fn len(&self) -> usize {
195 self.as_ref().len()
196 }
197
198 #[inline]
202 pub fn iter(&self) -> impl Iterator<Item = &T> {
203 self.as_ref().iter()
204 }
205
206 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
210 [self.0.iter_mut(), self.1.iter_mut()].into_iter().flatten()
211 }
212
213 #[inline]
217 pub fn contiguous(&self) -> &[T] {
218 self.as_ref().contiguous()
219 }
220
221 #[inline]
225 pub fn contiguous_mut(&mut self) -> &mut [T] {
226 if self.0.is_empty() {
227 self.1
228 } else {
229 self.0
230 }
231 }
232
233 #[inline]
238 pub fn slice<R>(&self, range: R) -> Region<T>
239 where
240 R: RangeBounds<usize>,
241 {
242 self.as_ref().slice(range)
243 }
244
245 pub fn slice_mut<R>(&mut self, range: R) -> RegionMut<T>
250 where
251 R: RangeBounds<usize>,
252 {
253 let (range_0, range_1) = self.as_ref().slice_ranges(range);
254
255 let slice_0 = &mut self.0[range_0];
256 let slice_1 = &mut self.1[range_1];
257
258 RegionMut(slice_0, slice_1)
259 }
260}
261
262impl<'a, T> RegionMut<'a, T>
263where
264 T: Copy,
265{
266 #[inline]
277 pub fn copy_to_slice(&self, slice: &mut [T]) {
278 self.as_ref().copy_to_slice(slice)
279 }
280
281 pub fn copy_from_slice(&mut self, src: &[T]) {
292 assert_eq!(
293 self.len(),
294 src.len(),
295 "destination and source slices have different lengths"
296 );
297
298 let (src_0, src_1) = src.split_at(self.0.len());
299 self.0.copy_from_slice(src_0);
300 self.1.copy_from_slice(src_1);
301 }
302}
303
304impl<'a, T> RegionMut<'a, T>
305where
306 T: Clone,
307{
308 #[inline]
315 pub fn clone_to_slice(&self, slice: &mut [T]) {
316 self.as_ref().clone_to_slice(slice)
317 }
318
319 pub fn clone_from_slice(&mut self, src: &[T]) {
326 assert_eq!(
327 self.len(),
328 src.len(),
329 "destination and source slices have different lengths"
330 );
331
332 let (src_0, src_1) = src.split_at(self.0.len());
333 self.0.clone_from_slice(src_0);
334 self.1.clone_from_slice(src_1);
335 }
336}
337
338impl<'a, T> Default for RegionMut<'a, T> {
339 #[inline]
340 fn default() -> Self {
341 RegionMut(Default::default(), Default::default())
342 }
343}
344
345impl<'a, T> Index<usize> for RegionMut<'a, T> {
346 type Output = T;
347
348 fn index(&self, index: usize) -> &Self::Output {
349 if index >= self.0.len() {
350 &self.1[index - self.0.len()]
351 } else {
352 &self.0[index]
353 }
354 }
355}
356
357impl<'a, T> IndexMut<usize> for RegionMut<'a, T> {
358 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
359 if index >= self.0.len() {
360 &mut self.1[index - self.0.len()]
361 } else {
362 &mut self.0[index]
363 }
364 }
365}
366
367#[cfg(test)]
368mod tests {
369 use crate::{Region, RegionMut};
370
371 fn collect<T: Clone>(region: &Region<T>) -> Vec<T> {
372 region.iter().cloned().collect()
373 }
374
375 #[test]
376 fn region_default_is_empty() {
377 assert!(Region::<u8>::default().is_empty());
378 assert_eq!(Region::<u8>::default().len(), 0);
379 }
380
381 #[test]
382 fn region_is_empty() {
383 let empty_arr = [];
384 let full_arr = [1, 2, 3];
385
386 assert!(Region::new(&empty_arr, &empty_arr).is_empty());
387 assert!(!Region::new(&full_arr, &full_arr).is_empty());
388 assert!(!Region::new(&full_arr, &empty_arr).is_empty());
389 assert!(!Region::new(&empty_arr, &full_arr).is_empty());
390 }
391
392 #[test]
393 fn region_len() {
394 let empty_arr = [];
395 let full_arr = [1, 2, 3];
396
397 assert_eq!(Region::new(&empty_arr, &empty_arr).len(), 0);
398 assert_eq!(Region::new(&full_arr, &full_arr).len(), 6);
399 assert_eq!(Region::new(&full_arr, &empty_arr).len(), 3);
400 assert_eq!(Region::new(&empty_arr, &full_arr).len(), 3);
401 }
402
403 #[test]
404 fn region_iter() {
405 let empty_arr = [];
406 let arr_1 = [1, 2, 3];
407 let arr_2 = [4, 5, 6];
408
409 assert_eq!(
410 Region::new(&empty_arr, &empty_arr)
411 .iter()
412 .cloned()
413 .collect::<Vec<_>>(),
414 vec![]
415 );
416 assert_eq!(
417 Region::new(&arr_1, &arr_2)
418 .iter()
419 .cloned()
420 .collect::<Vec<_>>(),
421 vec![1, 2, 3, 4, 5, 6]
422 );
423 assert_eq!(
424 Region::new(&arr_1, &empty_arr)
425 .iter()
426 .cloned()
427 .collect::<Vec<_>>(),
428 vec![1, 2, 3]
429 );
430 assert_eq!(
431 Region::new(&empty_arr, &arr_2)
432 .iter()
433 .cloned()
434 .collect::<Vec<_>>(),
435 vec![4, 5, 6]
436 );
437 }
438
439 #[test]
440 fn region_contiguous() {
441 let empty_arr = [];
442 let arr_1 = [1, 2, 3];
443 let arr_2 = [4, 5, 6];
444
445 assert!(Region::new(&empty_arr, &empty_arr).contiguous().is_empty());
446 assert_eq!(Region::new(&arr_1, &arr_2).contiguous(), [1, 2, 3]);
447 assert_eq!(Region::new(&arr_1, &empty_arr).contiguous(), [1, 2, 3]);
448 assert_eq!(Region::new(&empty_arr, &arr_2).contiguous(), [4, 5, 6]);
449 }
450
451 #[test]
452 fn region_slice() {
453 let arr_1 = [1, 2, 3];
454 let arr_2 = [4, 5, 6];
455 let region = Region::new(&arr_1, &arr_2);
456
457 assert_eq!(collect(®ion.slice(..)), vec![1, 2, 3, 4, 5, 6]);
458 assert_eq!(collect(®ion.slice(1..)), vec![2, 3, 4, 5, 6]);
459 assert_eq!(collect(®ion.slice(3..)), vec![4, 5, 6]);
460 assert_eq!(collect(®ion.slice(5..)), vec![6]);
461 assert_eq!(collect(®ion.slice(6..)), vec![]);
462 assert_eq!(collect(®ion.slice(..5)), vec![1, 2, 3, 4, 5]);
463 assert_eq!(collect(®ion.slice(..3)), vec![1, 2, 3]);
464 assert_eq!(collect(®ion.slice(..1)), vec![1]);
465 assert_eq!(collect(®ion.slice(..0)), vec![]);
466 assert_eq!(collect(®ion.slice(..=5)), vec![1, 2, 3, 4, 5, 6]);
467 assert_eq!(collect(®ion.slice(1..3)), vec![2, 3]);
468 assert_eq!(collect(®ion.slice(2..4)), vec![3, 4]);
469 assert_eq!(collect(®ion.slice(3..5)), vec![4, 5]);
470 assert_eq!(collect(®ion.slice(0..6)), vec![1, 2, 3, 4, 5, 6]);
471 }
472
473 #[test]
474 fn region_copy_to_slice() {
475 let arr_1 = [1, 2, 3];
476 let arr_2 = [4, 5, 6];
477 let region = Region::new(&arr_1, &arr_2);
478
479 let mut dest = [0, 0, 0, 0, 0, 0];
480 region.copy_to_slice(&mut dest);
481
482 assert_eq!(dest, [1, 2, 3, 4, 5, 6]);
483 }
484
485 #[test]
486 fn region_clone_to_slice() {
487 let arr_1 = [1, 2, 3];
488 let arr_2 = [4, 5, 6];
489 let region = Region::new(&arr_1, &arr_2);
490
491 let mut dest = [0, 0, 0, 0, 0, 0];
492 region.clone_to_slice(&mut dest);
493
494 assert_eq!(dest, [1, 2, 3, 4, 5, 6]);
495 }
496
497 #[test]
498 fn region_index() {
499 let arr_1 = [1, 2, 3];
500 let arr_2 = [4, 5, 6];
501 let region = Region::new(&arr_1, &arr_2);
502
503 assert_eq!(region[0], 1);
504 assert_eq!(region[2], 3);
505 assert_eq!(region[4], 5);
506 }
507
508 #[test]
509 fn region_mut_as_ref() {
510 let mut arr_1 = [1, 2, 3];
511 let mut arr_2 = [4, 5, 6];
512 let region = RegionMut::new(&mut arr_1, &mut arr_2);
513
514 assert_eq!(collect(®ion.as_ref()), vec![1, 2, 3, 4, 5, 6]);
515 }
516
517 #[test]
518 fn region_mut_copy_from_slice() {
519 let mut arr_1 = [1, 2, 3];
520 let mut arr_2 = [4, 5, 6];
521 let mut region = RegionMut::new(&mut arr_1, &mut arr_2);
522
523 let src = [100, 101, 102, 103, 104, 105];
524 region.copy_from_slice(&src);
525
526 assert_eq!(
527 collect(®ion.as_ref()),
528 vec![100, 101, 102, 103, 104, 105]
529 );
530 assert_eq!(region.contiguous(), [100, 101, 102]);
531 }
532
533 #[test]
534 fn region_mut_clone_from_slice() {
535 let mut arr_1 = [1, 2, 3];
536 let mut arr_2 = [4, 5, 6];
537 let mut region = RegionMut::new(&mut arr_1, &mut arr_2);
538
539 let src = [100, 101, 102, 103, 104, 105];
540 region.clone_from_slice(&src);
541
542 assert_eq!(
543 collect(®ion.as_ref()),
544 vec![100, 101, 102, 103, 104, 105]
545 );
546 assert_eq!(region.contiguous(), [100, 101, 102]);
547 }
548
549 #[test]
550 fn region_mut_index() {
551 let mut arr_1 = [1, 2, 3];
552 let mut arr_2 = [4, 5, 6];
553 let mut region = RegionMut::new(&mut arr_1, &mut arr_2);
554
555 region[1] = 100;
556 region[3] = 200;
557 region[5] = 300;
558
559 assert_eq!(collect(®ion.as_ref()), vec![1, 100, 3, 200, 5, 300]);
560 }
561}