Skip to content

Commit 26ac2d9

Browse files
committed
add SliceIndex wrapper types Last and Clamp<Idx>
1 parent 71289c3 commit 26ac2d9

File tree

3 files changed

+234
-0
lines changed

3 files changed

+234
-0
lines changed

library/core/src/index.rs

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
use crate::intrinsics::slice_get_unchecked;
2+
use crate::range;
3+
use crate::slice::SliceIndex;
4+
5+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
6+
pub struct Clamp<Idx>(pub Idx);
7+
8+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
9+
pub struct Last;
10+
11+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
12+
unsafe impl<T> SliceIndex<[T]> for Clamp<usize> {
13+
type Output = T;
14+
15+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
16+
slice.get(self.0.min(slice.len() - 1))
17+
}
18+
19+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
20+
slice.get_mut(self.0.min(slice.len() - 1))
21+
}
22+
23+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
24+
// SAFETY: the index before the length is always valid
25+
unsafe { slice_get_unchecked(slice, self.0.min(slice.len() - 1)) }
26+
}
27+
28+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
29+
// SAFETY: the index before the length is always valid
30+
unsafe { slice_get_unchecked(slice, self.0.min(slice.len() - 1)) }
31+
}
32+
33+
fn index(self, slice: &[T]) -> &Self::Output {
34+
&(*slice)[self.0.min(slice.len() - 1)]
35+
}
36+
37+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
38+
&mut (*slice)[self.0.min(slice.len() - 1)]
39+
}
40+
}
41+
42+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
43+
unsafe impl<T> SliceIndex<[T]> for Clamp<range::Range<usize>> {
44+
type Output = [T];
45+
46+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
47+
(self.0.start..self.0.end.min(slice.len())).get(slice)
48+
}
49+
50+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
51+
(self.0.start..self.0.end.min(slice.len())).get_mut(slice)
52+
}
53+
54+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
55+
// SAFETY: a range ending before len is always valid
56+
unsafe { (self.0.start..self.0.end.min(slice.len())).get_unchecked(slice) }
57+
}
58+
59+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
60+
// SAFETY: a range ending before len is always valid
61+
unsafe { (self.0.start..self.0.end.min(slice.len())).get_unchecked_mut(slice) }
62+
}
63+
64+
fn index(self, slice: &[T]) -> &Self::Output {
65+
(self.0.start..self.0.end.min(slice.len())).index(slice)
66+
}
67+
68+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
69+
(self.0.start..self.0.end.min(slice.len())).index_mut(slice)
70+
}
71+
}
72+
73+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
74+
unsafe impl<T> SliceIndex<[T]> for Clamp<range::RangeInclusive<usize>> {
75+
type Output = [T];
76+
77+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
78+
(self.0.start..=self.0.end.min(slice.len() - 1)).get(slice)
79+
}
80+
81+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
82+
(self.0.start..=self.0.end.min(slice.len() - 1)).get_mut(slice)
83+
}
84+
85+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
86+
// SAFETY: the index before the length is always valid
87+
unsafe { (self.0.start..=self.0.end.min(slice.len() - 1)).get_unchecked(slice) }
88+
}
89+
90+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
91+
// SAFETY: the index before the length is always valid
92+
unsafe { (self.0.start..=self.0.end.min(slice.len() - 1)).get_unchecked_mut(slice) }
93+
}
94+
95+
fn index(self, slice: &[T]) -> &Self::Output {
96+
(self.0.start..=self.0.end.min(slice.len() - 1)).index(slice)
97+
}
98+
99+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
100+
(self.0.start..=self.0.end.min(slice.len() - 1)).index_mut(slice)
101+
}
102+
}
103+
104+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
105+
unsafe impl<T> SliceIndex<[T]> for Clamp<range::RangeFrom<usize>> {
106+
type Output = [T];
107+
108+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
109+
(self.0.start..slice.len()).get(slice)
110+
}
111+
112+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
113+
(self.0.start..slice.len()).get_mut(slice)
114+
}
115+
116+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
117+
// SAFETY: a range ending before len is always valid
118+
unsafe { (self.0.start..slice.len()).get_unchecked(slice) }
119+
}
120+
121+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
122+
// SAFETY: a range ending before len is always valid
123+
unsafe { (self.0.start..slice.len()).get_unchecked_mut(slice) }
124+
}
125+
126+
fn index(self, slice: &[T]) -> &Self::Output {
127+
(self.0.start..slice.len()).index(slice)
128+
}
129+
130+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
131+
(self.0.start..slice.len()).index_mut(slice)
132+
}
133+
}
134+
135+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
136+
unsafe impl<T> SliceIndex<[T]> for Clamp<range::RangeTo<usize>> {
137+
type Output = [T];
138+
139+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
140+
(0..self.0.end.min(slice.len())).get(slice)
141+
}
142+
143+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
144+
(0..self.0.end.min(slice.len())).get_mut(slice)
145+
}
146+
147+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
148+
// SAFETY: a range ending before len is always valid
149+
unsafe { (0..self.0.end.min(slice.len())).get_unchecked(slice) }
150+
}
151+
152+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
153+
// SAFETY: a range ending before len is always valid
154+
unsafe { (0..self.0.end.min(slice.len())).get_unchecked_mut(slice) }
155+
}
156+
157+
fn index(self, slice: &[T]) -> &Self::Output {
158+
(0..self.0.end.min(slice.len())).index(slice)
159+
}
160+
161+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
162+
(0..self.0.end.min(slice.len())).index_mut(slice)
163+
}
164+
}
165+
166+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
167+
unsafe impl<T> SliceIndex<[T]> for Clamp<range::RangeToInclusive<usize>> {
168+
type Output = [T];
169+
170+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
171+
(0..=self.0.end.min(slice.len() - 1)).get(slice)
172+
}
173+
174+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
175+
(0..=self.0.end.min(slice.len() - 1)).get_mut(slice)
176+
}
177+
178+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
179+
// SAFETY: the index before the length is always valid
180+
unsafe { (0..=self.0.end.min(slice.len() - 1)).get_unchecked(slice) }
181+
}
182+
183+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
184+
// SAFETY: the index before the length is always valid
185+
unsafe { (0..=self.0.end.min(slice.len() - 1)).get_unchecked_mut(slice) }
186+
}
187+
188+
fn index(self, slice: &[T]) -> &Self::Output {
189+
(0..=self.0.end.min(slice.len() - 1)).index(slice)
190+
}
191+
192+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
193+
(0..=self.0.end.min(slice.len() - 1)).index_mut(slice)
194+
}
195+
}
196+
197+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
198+
unsafe impl<T> SliceIndex<[T]> for Last {
199+
type Output = T;
200+
201+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
202+
slice.last()
203+
}
204+
205+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
206+
slice.last_mut()
207+
}
208+
209+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
210+
// SAFETY: the index before the length is always valid
211+
unsafe { slice_get_unchecked(slice, slice.len() - 1) }
212+
}
213+
214+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
215+
// SAFETY: the index before the length is always valid
216+
unsafe { slice_get_unchecked(slice, slice.len() - 1) }
217+
}
218+
219+
fn index(self, slice: &[T]) -> &Self::Output {
220+
// N.B., use intrinsic indexing
221+
&(*slice)[slice.len() - 1]
222+
}
223+
224+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
225+
// N.B., use intrinsic indexing
226+
&mut (*slice)[slice.len() - 1]
227+
}
228+
}

library/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ pub mod cmp;
323323
pub mod convert;
324324
pub mod default;
325325
pub mod error;
326+
pub mod index;
326327
pub mod marker;
327328
pub mod ops;
328329

library/core/src/slice/index.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ mod private_slice_index {
132132
impl Sealed for range::RangeFrom<usize> {}
133133

134134
impl Sealed for ops::IndexRange {}
135+
136+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
137+
impl Sealed for crate::index::Last {}
138+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
139+
impl<T> Sealed for crate::index::Clamp<T> {}
135140
}
136141

137142
/// A helper trait used for indexing operations.

0 commit comments

Comments
 (0)