len_trait/
index.rs

1//! Traits involving collections which index over a particular type.
2
3cfg_if! {
4    if #[cfg(feature = "std")] {
5        use std::ops;
6    } else {
7        use core::ops;
8    }
9}
10
11use self::ops::{Index, IndexMut, Range, RangeFrom, RangeFull, RangeTo};
12
13
14mod private {
15    pub trait Sealed {}
16    impl Sealed for str {}
17    impl<T> Sealed for [T] {}
18}
19
20
21/// Shorthand trait for collections which offer consistent, immutable slicing.
22///
23/// Here, "consistent" means that indexing is implemented for all of the `Range` types from the
24/// standard library, and the type returned by each of the slices is always the same.
25///
26/// Currently, because inclusive ranges are unstable, and ranges starting with an exclusive bound
27/// don't exist, this trait can't be implemented for anything other than `str` and `[T]`. Hopefully,
28/// this will change in the future.
29pub trait IndexRange<Idx>
30    : Index<Range<Idx>, Output = <Self as Index<RangeFull>>::Output>
31    + Index<RangeTo<Idx>, Output = <Self as Index<RangeFull>>::Output>
32    + Index<RangeFrom<Idx>, Output = <Self as Index<RangeFull>>::Output>
33    + Index<RangeFull>
34    + private::Sealed {
35}
36impl<T: ?Sized, Idx> IndexRange<Idx> for T
37where
38    T: Index<
39        Range<Idx>,
40        Output = <T as Index<RangeFull>>::Output,
41    >,
42    T: Index<
43        RangeTo<Idx>,
44        Output = <T as Index<RangeFull>>::Output,
45    >,
46    T: Index<
47        RangeFrom<Idx>,
48        Output = <T as Index<RangeFull>>::Output,
49    >,
50    T: Index<RangeFull>,
51    T: private::Sealed,
52{
53}
54
55/// Shorthand trait for collections which offer consistent, mutable slicing.
56///
57/// Here, "consistent" means that indexing is implemented for all of the `Range` types from the
58/// standard library, and the type returned by each of the slices is always the same.
59///
60/// Currently, because inclusive ranges are unstable, and ranges starting with an exclusive bound
61/// don't exist, this trait can't be implemented for anything other than `str` and `[T]`. Hopefully,
62/// this will change in the future.
63pub trait IndexRangeMut<Idx>
64    : IndexMut<Range<Idx>>
65    + IndexMut<RangeTo<Idx>>
66    + IndexMut<RangeFrom<Idx>>
67    + IndexMut<RangeFull>
68    + IndexRange<Idx> {
69}
70
71impl<T: ?Sized, Idx> IndexRangeMut<Idx> for T
72where
73    T: IndexMut<Range<Idx>>,
74    T: IndexMut<RangeTo<Idx>>,
75    T: IndexMut<RangeFrom<Idx>>,
76    T: IndexMut<RangeFull>,
77    T: IndexRange<Idx>,
78{
79}
80
81/// A trait for splitting a collection into two pieces at a given index.
82///
83/// Splitting a collection must take a constant amount of time and space.
84pub trait SplitAt<Idx>: IndexRange<Idx> {
85    /// Splits the collection into two pieces at the given index.
86    ///
87    /// # Panics
88    ///
89    /// Panics if `index` is invalid according to the collection.
90    fn split_at(
91        &self,
92        index: Idx,
93    ) -> (&<Self as Index<RangeFull>>::Output, &<Self as Index<RangeFull>>::Output);
94}
95
96/// A trait for splitting a collection into two mutable pieces at a given index.
97///
98/// Splitting a collection must take a constant amount of time and space.
99pub trait SplitAtMut<Idx>: IndexRangeMut<Idx> + SplitAt<Idx> {
100    /// Splits the collection into two mutable pieces at the given index.
101    ///
102    /// # Panics
103    ///
104    /// Panics if `index` is invalid according to the collection.
105    fn split_at_mut(
106        &mut self,
107        index: Idx,
108    ) -> (&mut <Self as Index<RangeFull>>::Output, &mut <Self as Index<RangeFull>>::Output);
109}