1use core::ops;
2
3use crate::{TiRangeBounds, TiSlice};
4
5mod private {
6 use core::ops;
7
8 pub trait Sealed<K> {}
9
10 impl<K> Sealed<K> for K {}
11 impl<K> Sealed<K> for ops::Range<K> {}
12 impl<K> Sealed<K> for ops::RangeTo<K> {}
13 impl<K> Sealed<K> for ops::RangeFrom<K> {}
14 impl<K> Sealed<K> for ops::RangeInclusive<K> {}
15 impl<K> Sealed<K> for ops::RangeToInclusive<K> {}
16 impl<K> Sealed<K> for (ops::Bound<K>, ops::Bound<K>) {}
17}
18
19/// A helper trait used for indexing operations.
20///
21/// This trait is implemented for `K`, [`Range<K>`], [`RangeTo<K>`],
22/// [`RangeFrom<K>`], [`RangeInclusive<K>`] and [`RangeToInclusive<K>`].
23/// The [`RangeFull<K>`] trait is not currently supported.
24///
25/// Trait implementations are only forwards to standard Rust [`slice`]
26/// operations.
27///
28/// [`slice`]: https://doc.rust-lang.org/std/primitive.slice.html
29/// [`Range<K>`]: https://doc.rust-lang.org/std/ops/struct.Range.html
30/// [`RangeTo<K>`]: https://doc.rust-lang.org/std/ops/struct.RangeTo.html
31/// [`RangeFrom<K>`]: https://doc.rust-lang.org/std/ops/struct.RangeFrom.html
32/// [`RangeInclusive<K>`]: https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html
33/// [`RangeToInclusive<K>`]: https://doc.rust-lang.org/std/ops/struct.RangeToInclusive.html
34/// [`RangeFull<K>`]: https://doc.rust-lang.org/std/ops/struct.RangeFull.html
35pub trait TiSliceIndex<K, V>: private::Sealed<K> {
36 /// The output type returned by methods.
37 type Output: ?Sized;
38
39 /// Returns a shared reference to the output at this location, if in
40 /// bounds.
41 fn get(self, slice: &TiSlice<K, V>) -> Option<&Self::Output>;
42
43 /// Returns a mutable reference to the output at this location, if in
44 /// bounds.
45 fn get_mut(self, slice: &mut TiSlice<K, V>) -> Option<&mut Self::Output>;
46
47 /// Returns a shared reference to the output at this location, without
48 /// performing any bounds checking.
49 ///
50 /// # Safety
51 ///
52 /// Calling this method with an out-of-bounds index is
53 /// *[undefined behavior]* even if the resulting reference is not used.
54 ///
55 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
56 unsafe fn get_unchecked(self, slice: &TiSlice<K, V>) -> &Self::Output;
57
58 /// Returns a mutable reference to the output at this location, without
59 /// performing any bounds checking.
60 ///
61 /// # Safety
62 ///
63 /// Calling this method with an out-of-bounds index is
64 /// *[undefined behavior]* even if the resulting reference is not used.
65 ///
66 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
67 unsafe fn get_unchecked_mut(self, slice: &mut TiSlice<K, V>) -> &mut Self::Output;
68
69 /// Returns a shared reference to the output at this location, panicking
70 /// if out of bounds.
71 fn index(self, slice: &TiSlice<K, V>) -> &Self::Output;
72
73 /// Returns a mutable reference to the output at this location, panicking
74 /// if out of bounds.
75 fn index_mut(self, slice: &mut TiSlice<K, V>) -> &mut Self::Output;
76}
77
78impl<K, V> TiSliceIndex<K, V> for K
79where
80 usize: From<K>,
81{
82 type Output = V;
83
84 #[inline]
85 fn get(self, slice: &TiSlice<K, V>) -> Option<&Self::Output> {
86 slice.raw.get(usize::from(self))
87 }
88
89 #[inline]
90 fn get_mut(self, slice: &mut TiSlice<K, V>) -> Option<&mut Self::Output> {
91 slice.raw.get_mut(usize::from(self))
92 }
93
94 #[inline]
95 unsafe fn get_unchecked(self, slice: &TiSlice<K, V>) -> &Self::Output {
96 slice.raw.get_unchecked(usize::from(self))
97 }
98
99 #[inline]
100 unsafe fn get_unchecked_mut(self, slice: &mut TiSlice<K, V>) -> &mut Self::Output {
101 slice.raw.get_unchecked_mut(usize::from(self))
102 }
103
104 #[inline]
105 fn index(self, slice: &TiSlice<K, V>) -> &Self::Output {
106 &slice.raw[usize::from(self)]
107 }
108
109 #[inline]
110 fn index_mut(self, slice: &mut TiSlice<K, V>) -> &mut Self::Output {
111 &mut slice.raw[usize::from(self)]
112 }
113}
114
115macro_rules! impl_ti_slice_range {
116 ($ty:ty) => {
117 impl<K, V> TiSliceIndex<K, V> for $ty
118 where
119 usize: From<K>,
120 {
121 type Output = TiSlice<K, V>;
122
123 #[inline]
124 fn get(self, slice: &TiSlice<K, V>) -> Option<&Self::Output> {
125 slice.raw.get(self.into_range()).map(TiSlice::from_ref)
126 }
127
128 #[inline]
129 fn get_mut(self, slice: &mut TiSlice<K, V>) -> Option<&mut Self::Output> {
130 slice.raw.get_mut(self.into_range()).map(TiSlice::from_mut)
131 }
132
133 #[inline]
134 unsafe fn get_unchecked(self, slice: &TiSlice<K, V>) -> &Self::Output {
135 TiSlice::from_ref(slice.raw.get_unchecked(self.into_range()))
136 }
137
138 #[inline]
139 unsafe fn get_unchecked_mut(self, slice: &mut TiSlice<K, V>) -> &mut Self::Output {
140 TiSlice::from_mut(slice.raw.get_unchecked_mut(self.into_range()))
141 }
142
143 #[inline]
144 fn index(self, slice: &TiSlice<K, V>) -> &Self::Output {
145 TiSlice::from_ref(&slice.raw[self.into_range()])
146 }
147
148 #[inline]
149 fn index_mut(self, slice: &mut TiSlice<K, V>) -> &mut Self::Output {
150 TiSlice::from_mut(&mut slice.raw[self.into_range()])
151 }
152 }
153 };
154}
155
156impl_ti_slice_range!(ops::Range<K>);
157impl_ti_slice_range!(ops::RangeFrom<K>);
158impl_ti_slice_range!(ops::RangeInclusive<K>);
159impl_ti_slice_range!(ops::RangeTo<K>);
160impl_ti_slice_range!(ops::RangeToInclusive<K>);
161impl_ti_slice_range!((ops::Bound<K>, ops::Bound<K>));
162