Skip to content

Commit 17736fe

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

File tree

3 files changed

+373
-0
lines changed

3 files changed

+373
-0
lines changed

library/core/src/index.rs

Lines changed: 367 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,367 @@
1+
#![unstable(feature = "sliceindex_wrappers", issue = "146179")]
2+
3+
//! Helper types for indexing slices.
4+
5+
use crate::intrinsics::slice_get_unchecked;
6+
use crate::slice::SliceIndex;
7+
use crate::{ops, range};
8+
9+
/// Clamps an index, guaranteeing that it will only access valid elements of the slice.
10+
///
11+
/// # Examples
12+
///
13+
/// ```
14+
/// #![feature(sliceindex_wrappers)]
15+
///
16+
/// use core::index::Clamp;
17+
///
18+
/// let s: &[usize] = &[0, 1, 2, 3];
19+
///
20+
/// assert_eq!(&3, &s[Clamp(6)]);
21+
/// assert_eq!(&[1, 2, 3], &s[Clamp(1..6)]);
22+
/// assert_eq!(&[] as &[usize], &s[Clamp(5..6)]);
23+
/// assert_eq!(&[0, 1, 2, 3], &s[Clamp(..6)]);
24+
/// assert_eq!(&[0, 1, 2, 3], &s[Clamp(..=6)]);
25+
/// assert_eq!(&[] as &[usize], &s[Clamp(6..)]);
26+
/// ```
27+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
28+
#[derive(Debug)]
29+
pub struct Clamp<Idx>(pub Idx);
30+
31+
/// Always accesses the last element of the slice.
32+
///
33+
/// # Examples
34+
///
35+
/// ```
36+
/// #![feature(sliceindex_wrappers)]
37+
///
38+
/// use core::index::Last;
39+
///
40+
/// let s = &[0, 1, 2, 3];
41+
///
42+
/// assert_eq!(&3, &s[Last]);
43+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
44+
#[derive(Debug)]
45+
pub struct Last;
46+
47+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
48+
unsafe impl<T> SliceIndex<[T]> for Clamp<usize> {
49+
type Output = T;
50+
51+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
52+
slice.get(self.0.min(slice.len() - 1))
53+
}
54+
55+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
56+
slice.get_mut(self.0.min(slice.len() - 1))
57+
}
58+
59+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
60+
// SAFETY: the index before the length is always valid
61+
unsafe { slice_get_unchecked(slice, self.0.min(slice.len() - 1)) }
62+
}
63+
64+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
65+
// SAFETY: the index before the length is always valid
66+
unsafe { slice_get_unchecked(slice, self.0.min(slice.len() - 1)) }
67+
}
68+
69+
fn index(self, slice: &[T]) -> &Self::Output {
70+
&(*slice)[self.0.min(slice.len() - 1)]
71+
}
72+
73+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
74+
&mut (*slice)[self.0.min(slice.len() - 1)]
75+
}
76+
}
77+
78+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
79+
unsafe impl<T> SliceIndex<[T]> for Clamp<range::Range<usize>> {
80+
type Output = [T];
81+
82+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
83+
(self.0.start.min(slice.len())..self.0.end.min(slice.len())).get(slice)
84+
}
85+
86+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
87+
(self.0.start.min(slice.len())..self.0.end.min(slice.len())).get_mut(slice)
88+
}
89+
90+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
91+
// SAFETY: a range ending before len is always valid
92+
unsafe { (self.0.start.min(slice.len())..self.0.end.min(slice.len())).get_unchecked(slice) }
93+
}
94+
95+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
96+
// SAFETY: a range ending before len is always valid
97+
unsafe {
98+
(self.0.start.min(slice.len())..self.0.end.min(slice.len())).get_unchecked_mut(slice)
99+
}
100+
}
101+
102+
fn index(self, slice: &[T]) -> &Self::Output {
103+
(self.0.start.min(slice.len())..self.0.end.min(slice.len())).index(slice)
104+
}
105+
106+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
107+
(self.0.start.min(slice.len())..self.0.end.min(slice.len())).index_mut(slice)
108+
}
109+
}
110+
111+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
112+
unsafe impl<T> SliceIndex<[T]> for Clamp<ops::Range<usize>> {
113+
type Output = [T];
114+
115+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
116+
(self.0.start.min(slice.len())..self.0.end.min(slice.len())).get(slice)
117+
}
118+
119+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
120+
(self.0.start.min(slice.len())..self.0.end.min(slice.len())).get_mut(slice)
121+
}
122+
123+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
124+
// SAFETY: a range ending before len is always valid
125+
unsafe { (self.0.start.min(slice.len())..self.0.end.min(slice.len())).get_unchecked(slice) }
126+
}
127+
128+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
129+
// SAFETY: a range ending before len is always valid
130+
unsafe {
131+
(self.0.start.min(slice.len())..self.0.end.min(slice.len())).get_unchecked_mut(slice)
132+
}
133+
}
134+
135+
fn index(self, slice: &[T]) -> &Self::Output {
136+
(self.0.start.min(slice.len())..self.0.end.min(slice.len())).index(slice)
137+
}
138+
139+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
140+
(self.0.start.min(slice.len())..self.0.end.min(slice.len())).index_mut(slice)
141+
}
142+
}
143+
144+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
145+
unsafe impl<T> SliceIndex<[T]> for Clamp<range::RangeInclusive<usize>> {
146+
type Output = [T];
147+
148+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
149+
(self.0.start.min(slice.len() - 1)..=self.0.end.min(slice.len() - 1)).get(slice)
150+
}
151+
152+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
153+
(self.0.start.min(slice.len() - 1)..=self.0.end.min(slice.len() - 1)).get_mut(slice)
154+
}
155+
156+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
157+
// SAFETY: the index before the length is always valid
158+
unsafe {
159+
(self.0.start.min(slice.len() - 1)..=self.0.end.min(slice.len() - 1))
160+
.get_unchecked(slice)
161+
}
162+
}
163+
164+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
165+
// SAFETY: the index before the length is always valid
166+
unsafe {
167+
(self.0.start.min(slice.len() - 1)..=self.0.end.min(slice.len() - 1))
168+
.get_unchecked_mut(slice)
169+
}
170+
}
171+
172+
fn index(self, slice: &[T]) -> &Self::Output {
173+
(self.0.start.min(slice.len() - 1)..=self.0.end.min(slice.len() - 1)).index(slice)
174+
}
175+
176+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
177+
(self.0.start.min(slice.len() - 1)..=self.0.end.min(slice.len() - 1)).index_mut(slice)
178+
}
179+
}
180+
181+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
182+
unsafe impl<T> SliceIndex<[T]> for Clamp<range::RangeFrom<usize>> {
183+
type Output = [T];
184+
185+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
186+
(self.0.start.min(slice.len())..).get(slice)
187+
}
188+
189+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
190+
(self.0.start.min(slice.len())..).get_mut(slice)
191+
}
192+
193+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
194+
// SAFETY: a range starting at len is valid
195+
unsafe { (self.0.start.min(slice.len())..).get_unchecked(slice) }
196+
}
197+
198+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
199+
// SAFETY: a range starting at len is valid
200+
unsafe { (self.0.start.min(slice.len())..).get_unchecked_mut(slice) }
201+
}
202+
203+
fn index(self, slice: &[T]) -> &Self::Output {
204+
(self.0.start.min(slice.len())..).index(slice)
205+
}
206+
207+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
208+
(self.0.start.min(slice.len())..).index_mut(slice)
209+
}
210+
}
211+
212+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
213+
unsafe impl<T> SliceIndex<[T]> for Clamp<ops::RangeFrom<usize>> {
214+
type Output = [T];
215+
216+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
217+
(self.0.start.min(slice.len())..).get(slice)
218+
}
219+
220+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
221+
(self.0.start.min(slice.len())..).get_mut(slice)
222+
}
223+
224+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
225+
// SAFETY: a range starting at len is valid
226+
unsafe { (self.0.start.min(slice.len())..).get_unchecked(slice) }
227+
}
228+
229+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
230+
// SAFETY: a range starting at len is valid
231+
unsafe { (self.0.start.min(slice.len())..).get_unchecked_mut(slice) }
232+
}
233+
234+
fn index(self, slice: &[T]) -> &Self::Output {
235+
(self.0.start.min(slice.len())..).index(slice)
236+
}
237+
238+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
239+
(self.0.start.min(slice.len())..).index_mut(slice)
240+
}
241+
}
242+
243+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
244+
unsafe impl<T> SliceIndex<[T]> for Clamp<range::RangeTo<usize>> {
245+
type Output = [T];
246+
247+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
248+
(..self.0.end.min(slice.len())).get(slice)
249+
}
250+
251+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
252+
(..self.0.end.min(slice.len())).get_mut(slice)
253+
}
254+
255+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
256+
// SAFETY: a range ending before len is always valid
257+
unsafe { (..self.0.end.min(slice.len())).get_unchecked(slice) }
258+
}
259+
260+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
261+
// SAFETY: a range ending before len is always valid
262+
unsafe { (..self.0.end.min(slice.len())).get_unchecked_mut(slice) }
263+
}
264+
265+
fn index(self, slice: &[T]) -> &Self::Output {
266+
(..self.0.end.min(slice.len())).index(slice)
267+
}
268+
269+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
270+
(..self.0.end.min(slice.len())).index_mut(slice)
271+
}
272+
}
273+
274+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
275+
unsafe impl<T> SliceIndex<[T]> for Clamp<range::RangeToInclusive<usize>> {
276+
type Output = [T];
277+
278+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
279+
(..=self.0.end.min(slice.len() - 1)).get(slice)
280+
}
281+
282+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
283+
(..=self.0.end.min(slice.len() - 1)).get_mut(slice)
284+
}
285+
286+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
287+
// SAFETY: the index before the length is always valid
288+
unsafe { (..=self.0.end.min(slice.len() - 1)).get_unchecked(slice) }
289+
}
290+
291+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
292+
// SAFETY: the index before the length is always valid
293+
unsafe { (..=self.0.end.min(slice.len() - 1)).get_unchecked_mut(slice) }
294+
}
295+
296+
fn index(self, slice: &[T]) -> &Self::Output {
297+
(..=self.0.end.min(slice.len() - 1)).index(slice)
298+
}
299+
300+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
301+
(..=self.0.end.min(slice.len() - 1)).index_mut(slice)
302+
}
303+
}
304+
305+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
306+
unsafe impl<T> SliceIndex<[T]> for Clamp<range::RangeFull> {
307+
type Output = [T];
308+
309+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
310+
(..).get(slice)
311+
}
312+
313+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
314+
(..).get_mut(slice)
315+
}
316+
317+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
318+
// SAFETY: RangeFull just returns `slice` here
319+
unsafe { (..).get_unchecked(slice) }
320+
}
321+
322+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
323+
// SAFETY: RangeFull just returns `slice` here
324+
unsafe { (..).get_unchecked_mut(slice) }
325+
}
326+
327+
fn index(self, slice: &[T]) -> &Self::Output {
328+
(..).index(slice)
329+
}
330+
331+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
332+
(..).index_mut(slice)
333+
}
334+
}
335+
336+
#[unstable(feature = "sliceindex_wrappers", issue = "146179")]
337+
unsafe impl<T> SliceIndex<[T]> for Last {
338+
type Output = T;
339+
340+
fn get(self, slice: &[T]) -> Option<&Self::Output> {
341+
slice.last()
342+
}
343+
344+
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
345+
slice.last_mut()
346+
}
347+
348+
unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
349+
// SAFETY: the index before the length is always valid
350+
unsafe { slice_get_unchecked(slice, slice.len() - 1) }
351+
}
352+
353+
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
354+
// SAFETY: the index before the length is always valid
355+
unsafe { slice_get_unchecked(slice, slice.len() - 1) }
356+
}
357+
358+
fn index(self, slice: &[T]) -> &Self::Output {
359+
// N.B., use intrinsic indexing
360+
&(*slice)[slice.len() - 1]
361+
}
362+
363+
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
364+
// N.B., use intrinsic indexing
365+
&mut (*slice)[slice.len() - 1]
366+
}
367+
}

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)