1#![cfg_attr(not(feature = "std"), no_std)]
32#![cfg_attr(docsrs, feature(doc_auto_cfg))]
33
34use core::{
35 cmp::Ordering,
36 hash::{Hash, Hasher},
37 iter::FusedIterator,
38 ops::{Index, Range},
39 slice::SliceIndex,
40};
41
42#[cfg(feature = "std")]
43use std::backtrace::Backtrace;
44
45#[cfg(all(feature = "alloc", not(feature = "std")))]
46extern crate alloc;
47#[cfg(all(feature = "alloc", not(feature = "std")))]
48use alloc::{boxed::Box, vec::Vec};
49
50#[derive(Debug, Clone, Copy, Eq)]
77pub struct ArraySection<T, const N: usize> {
78 start: usize,
79 end: usize,
80 array: [T; N],
81}
82
83impl<const N: usize, T: Hash> Hash for ArraySection<T, N> {
85 #[inline]
86 fn hash<H: Hasher>(&self, state: &mut H) {
87 self.as_slice().hash(state);
88 }
89}
90
91impl<const N: usize, const M: usize, T: PartialOrd> PartialOrd<ArraySection<T, M>>
93 for ArraySection<T, N>
94{
95 #[inline]
96 fn partial_cmp(&self, other: &ArraySection<T, M>) -> Option<Ordering> {
97 self.as_slice().partial_cmp(other.as_slice())
98 }
99}
100
101impl<const N: usize, T: Ord> Ord for ArraySection<T, N> {
103 #[inline]
104 fn cmp(&self, other: &Self) -> Ordering {
105 self.as_slice().cmp(other.as_slice())
106 }
107}
108
109impl<const N: usize, T> ArraySection<T, N> {
110 #[inline]
116 pub const fn new(array: [T; N], section: Range<usize>) -> Self {
117 assert!(
118 section.start < N && section.end <= N,
119 "the sub-range must be in bounds"
120 );
121
122 if section.start > section.end {
123 Self {
124 start: 0,
125 end: 0,
126 array,
127 }
128 } else {
129 Self {
130 start: section.start,
131 end: section.end,
132 array,
133 }
134 }
135 }
136
137 #[inline]
140 pub const fn start(&self) -> usize {
141 self.start
142 }
143
144 #[inline]
147 pub const fn end(&self) -> usize {
148 self.end
149 }
150
151 #[inline]
157 pub fn change_section(&mut self, section: Range<usize>) {
158 assert!(
159 section.start < N && section.end <= N,
160 "the section must be in bounds"
161 );
162 if section.start > section.end {
163 self.start = 0;
164 self.end = 0;
165 } else {
166 self.start = section.start;
167 self.end = section.end;
168 }
169 }
170
171 #[inline]
173 pub const fn try_as_full_array(&self) -> Option<&[T; N]> {
174 if self.section_is_full_array() {
175 Some(&self.array)
176 } else {
177 None
178 }
179 }
180
181 #[inline]
183 pub fn try_as_full_array_mut(&mut self) -> Option<&mut [T; N]> {
184 self.section_is_full_array().then_some(&mut self.array)
185 }
186
187 #[inline]
189 pub const fn as_full_array(&self) -> &[T; N] {
190 &self.array
191 }
192
193 #[inline]
195 pub fn as_full_array_mut(&mut self) -> &mut [T; N] {
196 &mut self.array
197 }
198
199 #[inline]
202 pub const fn split_at_section(&self) -> (&[T], &[T], &[T]) {
203 let (head, rest) = self.array.split_at(self.start);
204 let (section, tail) = rest.split_at(self.end - self.start);
205 (head, section, tail)
206 }
207
208 #[inline]
211 pub fn split_at_section_mut(&mut self) -> (&mut [T], &mut [T], &mut [T]) {
212 let (head, rest) = self.array.split_at_mut(self.start);
213 let (section, tail) = rest.split_at_mut(self.end - self.start);
214 (head, section, tail)
215 }
216
217 #[inline]
222 pub fn into_full_array(self) -> [T; N] {
223 self.array
224 }
225
226 #[inline]
228 pub const fn as_slice(&self) -> &[T] {
229 self.split_at_section().1
230 }
231
232 #[inline]
234 pub fn as_slice_mut(&mut self) -> &mut [T] {
235 self.split_at_section_mut().1
236 }
237
238 #[inline]
240 pub const fn len(&self) -> usize {
241 self.as_slice().len()
242 }
243
244 #[inline]
246 pub const fn is_empty(&self) -> bool {
247 self.as_slice().is_empty()
248 }
249
250 #[inline]
254 pub const fn section_is_full_array(&self) -> bool {
255 self.len() == N
256 }
257
258 #[inline]
260 pub fn iter(&self) -> ArraySectionIter<'_, T> {
261 ArraySectionIter::new(self.as_slice().iter())
262 }
263
264 #[inline]
266 pub fn iter_mut(&mut self) -> ArraySectionIterMut<'_, T> {
267 ArraySectionIterMut::new(self.as_slice_mut().iter_mut())
268 }
269
270 #[cfg(any(feature = "alloc", feature = "std"))]
271 #[inline]
283 pub fn into_vec(self) -> Vec<T> {
284 self.into_iter().collect()
285 }
286
287 #[cfg(any(feature = "alloc", feature = "std"))]
288 #[inline]
303 pub fn into_boxed_slice(self) -> Box<[T]> {
304 self.into_vec().into_boxed_slice()
305 }
306}
307
308impl<T: Clone, const N: usize> ArraySection<T, N> {
309 #[cfg(any(feature = "alloc", feature = "std"))]
310 #[inline]
312 pub fn to_vec(&self) -> Vec<T> {
313 self.as_slice().to_vec()
314 }
315
316 #[cfg(any(feature = "alloc", feature = "std"))]
317 #[inline]
319 pub fn to_boxed_slice(&self) -> Box<[T]> {
320 self.as_slice().into()
321 }
322}
323
324#[cfg(any(feature = "alloc", feature = "std"))]
325impl<T: Clone, const N: usize> From<ArraySection<T, N>> for Vec<T> {
326 #[inline]
328 fn from(value: ArraySection<T, N>) -> Vec<T> {
329 value.as_slice().into()
330 }
331}
332#[cfg(any(feature = "alloc", feature = "std"))]
333impl<T: Clone, const N: usize> From<ArraySection<T, N>> for Box<[T]> {
334 #[inline]
336 fn from(value: ArraySection<T, N>) -> Box<[T]> {
337 value.as_slice().into()
338 }
339}
340
341impl<T: Copy, const N: usize> ArraySection<T, N> {
342 #[inline]
344 pub const fn into_full_array_const(self) -> [T; N] {
345 self.array
346 }
347}
348
349#[derive(Debug)]
355pub struct TryFromArraySectionError<T, const N: usize> {
356 section: ArraySection<T, N>,
357 #[cfg(feature = "std")]
358 backtrace: Backtrace,
359}
360
361impl<T, const N: usize> TryFromArraySectionError<T, N> {
362 #[inline]
364 pub fn array_section(self) -> ArraySection<T, N> {
365 self.section
366 }
367
368 #[inline]
369 pub(crate) fn new(section: ArraySection<T, N>) -> Self {
370 Self {
371 section,
372 #[cfg(feature = "std")]
373 backtrace: Backtrace::capture(),
374 }
375 }
376
377 #[cfg(feature = "std")]
378 #[inline]
382 pub fn backtrace(&self) -> &Backtrace {
383 &self.backtrace
384 }
385}
386
387impl<T, const N: usize> core::fmt::Display for TryFromArraySectionError<T, N> {
388 #[inline]
389 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
390 write!(f, "the array was not fully populated")
391 }
392}
393
394impl<T: core::fmt::Debug, const N: usize> core::error::Error for TryFromArraySectionError<T, N> {}
395
396impl<T, const N: usize> From<TryFromArraySectionError<T, N>> for ArraySection<T, N> {
397 #[inline]
398 fn from(value: TryFromArraySectionError<T, N>) -> Self {
399 value.section
400 }
401}
402
403impl<const N: usize, T> TryFrom<ArraySection<T, N>> for [T; N] {
405 type Error = TryFromArraySectionError<T, N>;
406
407 #[inline]
408 fn try_from(value: ArraySection<T, N>) -> Result<Self, Self::Error> {
409 if value.section_is_full_array() {
410 Ok(value.array)
411 } else {
412 Err(TryFromArraySectionError::new(value))
413 }
414 }
415}
416
417impl<const N: usize, T> From<[T; N]> for ArraySection<T, N> {
420 #[inline]
421 fn from(value: [T; N]) -> Self {
422 Self {
423 start: 0,
424 end: N,
425 array: value,
426 }
427 }
428}
429
430impl<const N: usize, T> AsRef<[T]> for ArraySection<T, N> {
431 #[inline]
432 fn as_ref(&self) -> &[T] {
433 self.as_slice()
434 }
435}
436
437impl<const N: usize, T, I: SliceIndex<[T]>> Index<I> for ArraySection<T, N> {
438 type Output = I::Output;
439 #[inline]
440 fn index(&self, index: I) -> &Self::Output {
441 self.as_slice().index(index)
442 }
443}
444
445impl<const N: usize, const M: usize, T, U> PartialEq<ArraySection<T, N>> for ArraySection<U, M>
448where
449 [U]: PartialEq<[T]>,
450{
451 #[inline]
452 fn eq(&self, other: &ArraySection<T, N>) -> bool {
453 self.as_slice().eq(other.as_slice())
454 }
455}
456
457impl<const N: usize, T, U> PartialEq<[U]> for ArraySection<T, N>
458where
459 U: PartialEq<T>,
460{
461 #[inline]
462 fn eq(&self, other: &[U]) -> bool {
463 other == self.as_slice()
464 }
465}
466
467impl<const N: usize, T, U> PartialEq<ArraySection<T, N>> for [U]
468where
469 U: PartialEq<T>,
470{
471 #[inline]
472 fn eq(&self, other: &ArraySection<T, N>) -> bool {
473 self == other.as_slice()
474 }
475}
476
477impl<const N: usize, const M: usize, T, U> PartialEq<[T; N]> for ArraySection<U, M>
478where
479 [U]: PartialEq<[T]>,
480{
481 #[inline]
482 fn eq(&self, other: &[T; N]) -> bool {
483 self.as_slice().eq(other.as_slice())
484 }
485}
486
487impl<const N: usize, const M: usize, T, U> PartialEq<ArraySection<U, M>> for [T; N]
488where
489 [T]: PartialEq<[U]>,
490{
491 #[inline]
492 fn eq(&self, other: &ArraySection<U, M>) -> bool {
493 self.as_slice().eq(other.as_slice())
494 }
495}
496
497impl<const N: usize, T> IntoIterator for ArraySection<T, N> {
500 type IntoIter = ArraySectionIntoIter<T, N>;
501 type Item = <ArraySectionIntoIter<T, N> as Iterator>::Item;
502 #[inline]
503 fn into_iter(self) -> Self::IntoIter {
504 let start = self.start;
505 let len = self.len();
506 ArraySectionIntoIter::new(self.array.into_iter().skip(start).take(len))
507 }
508}
509
510impl<'a, const N: usize, T> IntoIterator for &'a ArraySection<T, N> {
511 type IntoIter = ArraySectionIter<'a, T>;
512 type Item = <ArraySectionIter<'a, T> as Iterator>::Item;
513 #[inline]
514 fn into_iter(self) -> Self::IntoIter {
515 ArraySectionIter::new(self.as_slice().iter())
516 }
517}
518
519impl<'a, const N: usize, T> IntoIterator for &'a mut ArraySection<T, N> {
520 type IntoIter = ArraySectionIter<'a, T>;
521 type Item = <ArraySectionIter<'a, T> as Iterator>::Item;
522 #[inline]
523 fn into_iter(self) -> Self::IntoIter {
524 ArraySectionIter::new(self.as_slice().iter())
525 }
526}
527
528pub use array_section_iter_mut::ArraySectionIterMut;
529mod array_section_iter_mut {
530 use super::FusedIterator;
531
532 #[derive(Debug)]
534 pub struct ArraySectionIterMut<'a, T>(core::slice::IterMut<'a, T>);
535
536 impl<'a, T> ArraySectionIterMut<'a, T> {
537 #[inline]
538 pub(crate) const fn new(iter: core::slice::IterMut<'a, T>) -> Self {
539 Self(iter)
540 }
541 }
542
543 impl<'a, T> Iterator for ArraySectionIterMut<'a, T> {
544 type Item = &'a mut T;
545 #[inline]
546 fn next(&mut self) -> Option<Self::Item> {
547 self.0.next()
548 }
549
550 #[inline]
551 fn nth(&mut self, n: usize) -> Option<Self::Item> {
552 self.0.nth(n)
553 }
554
555 #[inline]
556 fn last(self) -> Option<Self::Item> {
557 self.0.last()
558 }
559
560 #[inline]
561 fn count(self) -> usize {
562 self.0.count()
563 }
564
565 #[inline]
566 fn size_hint(&self) -> (usize, Option<usize>) {
567 self.0.size_hint()
568 }
569 }
570
571 impl<'a, T> DoubleEndedIterator for ArraySectionIterMut<'a, T> {
572 #[inline]
573 fn next_back(&mut self) -> Option<Self::Item> {
574 self.0.next_back()
575 }
576
577 #[inline]
578 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
579 self.0.nth_back(n)
580 }
581 }
582
583 impl<'a, T> ExactSizeIterator for ArraySectionIterMut<'a, T> {
584 #[inline]
585 fn len(&self) -> usize {
586 self.0.len()
587 }
588 }
589
590 impl<'a, T> FusedIterator for ArraySectionIterMut<'a, T> {}
591}
592
593pub use array_section_iter::ArraySectionIter;
594mod array_section_iter {
595 use super::FusedIterator;
596
597 #[derive(Debug, Clone)]
599 #[must_use = "iterators are lazy and do nothing unless consumed"]
600 pub struct ArraySectionIter<'a, T>(core::slice::Iter<'a, T>);
601
602 impl<'a, T> ArraySectionIter<'a, T> {
603 pub(crate) const fn new(iter: core::slice::Iter<'a, T>) -> Self {
604 Self(iter)
605 }
606 }
607
608 impl<'a, T> Iterator for ArraySectionIter<'a, T> {
609 type Item = &'a T;
610 #[inline]
611 fn next(&mut self) -> Option<Self::Item> {
612 self.0.next()
613 }
614
615 #[inline]
616 fn size_hint(&self) -> (usize, Option<usize>) {
617 self.0.size_hint()
618 }
619
620 #[inline]
621 fn last(self) -> Option<Self::Item> {
622 self.0.last()
623 }
624
625 #[inline]
626 fn nth(&mut self, n: usize) -> Option<Self::Item> {
627 self.0.nth(n)
628 }
629
630 #[inline]
631 fn count(self) -> usize {
632 self.0.count()
633 }
634 }
635 impl<'a, T> DoubleEndedIterator for ArraySectionIter<'a, T> {
636 #[inline]
637 fn next_back(&mut self) -> Option<Self::Item> {
638 self.0.next_back()
639 }
640
641 #[inline]
642 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
643 self.0.nth_back(n)
644 }
645 }
646 impl<'a, T> ExactSizeIterator for ArraySectionIter<'a, T> {
647 fn len(&self) -> usize {
648 self.0.len()
649 }
650 }
651 impl<'a, T> FusedIterator for ArraySectionIter<'a, T> {}
652}
653
654pub use array_section_into_iter::ArraySectionIntoIter;
655mod array_section_into_iter {
656 use super::FusedIterator;
657
658 #[derive(Debug, Clone)]
659 #[must_use = "iterators are lazy and do nothing unless consumed"]
661 pub struct ArraySectionIntoIter<T, const N: usize>(
662 core::iter::Take<core::iter::Skip<core::array::IntoIter<T, N>>>,
663 );
664
665 impl<const N: usize, T> ArraySectionIntoIter<T, N> {
666 pub(crate) const fn new(
667 iter: core::iter::Take<core::iter::Skip<core::array::IntoIter<T, N>>>,
668 ) -> Self {
669 Self(iter)
670 }
671 }
672
673 impl<const N: usize, T> Iterator for ArraySectionIntoIter<T, N> {
674 type Item = T;
675 #[inline]
676 fn next(&mut self) -> Option<Self::Item> {
677 self.0.next()
678 }
679
680 #[inline]
681 fn size_hint(&self) -> (usize, Option<usize>) {
682 let l = self.0.len();
683 (l, Some(l))
684 }
685
686 #[inline]
687 fn nth(&mut self, index: usize) -> Option<Self::Item> {
688 self.0.nth(index)
689 }
690
691 #[inline]
692 fn last(self) -> Option<T> {
693 self.0.last()
694 }
695
696 #[inline]
697 fn count(self) -> usize {
698 self.0.count()
699 }
700 }
701 impl<const N: usize, T> FusedIterator for ArraySectionIntoIter<T, N> {}
702 impl<const N: usize, T> ExactSizeIterator for ArraySectionIntoIter<T, N> {}
703 impl<const N: usize, T> DoubleEndedIterator for ArraySectionIntoIter<T, N> {
704 #[inline]
705 fn next_back(&mut self) -> Option<Self::Item> {
706 self.0.next_back()
707 }
708
709 #[inline]
710 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
711 self.0.nth_back(n)
712 }
713 }
714}