core/slice/
index.rs

1//! Indexing implementations for `[T]`.
2
3use crate::panic::const_panic;
4use crate::ub_checks::assert_unsafe_precondition;
5use crate::{ops, range};
6
7#[stable(feature = "rust1", since = "1.0.0")]
8impl<T, I> ops::Index<I> for [T]
9where
10    I: SliceIndex<[T]>,
11{
12    type Output = I::Output;
13
14    #[inline(always)]
15    fn index(&self, index: I) -> &I::Output {
16        index.index(self)
17    }
18}
19
20#[stable(feature = "rust1", since = "1.0.0")]
21impl<T, I> ops::IndexMut<I> for [T]
22where
23    I: SliceIndex<[T]>,
24{
25    #[inline(always)]
26    fn index_mut(&mut self, index: I) -> &mut I::Output {
27        index.index_mut(self)
28    }
29}
30
31#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
32#[cfg_attr(feature = "panic_immediate_abort", inline)]
33#[track_caller]
34const fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
35    const_panic!(
36        "slice start index is out of range for slice",
37        "range start index {index} out of range for slice of length {len}",
38        index: usize,
39        len: usize,
40    )
41}
42
43#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
44#[cfg_attr(feature = "panic_immediate_abort", inline)]
45#[track_caller]
46const fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
47    const_panic!(
48        "slice end index is out of range for slice",
49        "range end index {index} out of range for slice of length {len}",
50        index: usize,
51        len: usize,
52    )
53}
54
55#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
56#[cfg_attr(feature = "panic_immediate_abort", inline)]
57#[track_caller]
58const fn slice_index_order_fail(index: usize, end: usize) -> ! {
59    const_panic!(
60        "slice index start is larger than end",
61        "slice index starts at {index} but ends at {end}",
62        index: usize,
63        end: usize,
64    )
65}
66
67#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
68#[cfg_attr(feature = "panic_immediate_abort", inline)]
69#[track_caller]
70const fn slice_start_index_overflow_fail() -> ! {
71    panic!("attempted to index slice from after maximum usize");
72}
73
74#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
75#[cfg_attr(feature = "panic_immediate_abort", inline)]
76#[track_caller]
77const fn slice_end_index_overflow_fail() -> ! {
78    panic!("attempted to index slice up to maximum usize");
79}
80
81// The UbChecks are great for catching bugs in the unsafe methods, but including
82// them in safe indexing is unnecessary and hurts inlining and debug runtime perf.
83// Both the safe and unsafe public methods share these helpers,
84// which use intrinsics directly to get *no* extra checks.
85
86#[inline(always)]
87const unsafe fn get_noubcheck<T>(ptr: *const [T], index: usize) -> *const T {
88    let ptr = ptr as *const T;
89    // SAFETY: The caller already checked these preconditions
90    unsafe { crate::intrinsics::offset(ptr, index) }
91}
92
93#[inline(always)]
94const unsafe fn get_mut_noubcheck<T>(ptr: *mut [T], index: usize) -> *mut T {
95    let ptr = ptr as *mut T;
96    // SAFETY: The caller already checked these preconditions
97    unsafe { crate::intrinsics::offset(ptr, index) }
98}
99
100#[inline(always)]
101const unsafe fn get_offset_len_noubcheck<T>(
102    ptr: *const [T],
103    offset: usize,
104    len: usize,
105) -> *const [T] {
106    // SAFETY: The caller already checked these preconditions
107    let ptr = unsafe { get_noubcheck(ptr, offset) };
108    crate::intrinsics::aggregate_raw_ptr(ptr, len)
109}
110
111#[inline(always)]
112const unsafe fn get_offset_len_mut_noubcheck<T>(
113    ptr: *mut [T],
114    offset: usize,
115    len: usize,
116) -> *mut [T] {
117    // SAFETY: The caller already checked these preconditions
118    let ptr = unsafe { get_mut_noubcheck(ptr, offset) };
119    crate::intrinsics::aggregate_raw_ptr(ptr, len)
120}
121
122mod private_slice_index {
123    use super::{ops, range};
124
125    #[stable(feature = "slice_get_slice", since = "1.28.0")]
126    pub trait Sealed {}
127
128    #[stable(feature = "slice_get_slice", since = "1.28.0")]
129    impl Sealed for usize {}
130    #[stable(feature = "slice_get_slice", since = "1.28.0")]
131    impl Sealed for ops::Range<usize> {}
132    #[stable(feature = "slice_get_slice", since = "1.28.0")]
133    impl Sealed for ops::RangeTo<usize> {}
134    #[stable(feature = "slice_get_slice", since = "1.28.0")]
135    impl Sealed for ops::RangeFrom<usize> {}
136    #[stable(feature = "slice_get_slice", since = "1.28.0")]
137    impl Sealed for ops::RangeFull {}
138    #[stable(feature = "slice_get_slice", since = "1.28.0")]
139    impl Sealed for ops::RangeInclusive<usize> {}
140    #[stable(feature = "slice_get_slice", since = "1.28.0")]
141    impl Sealed for ops::RangeToInclusive<usize> {}
142    #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")]
143    impl Sealed for (ops::Bound<usize>, ops::Bound<usize>) {}
144
145    #[unstable(feature = "new_range_api", issue = "125687")]
146    impl Sealed for range::Range<usize> {}
147    #[unstable(feature = "new_range_api", issue = "125687")]
148    impl Sealed for range::RangeInclusive<usize> {}
149    #[unstable(feature = "new_range_api", issue = "125687")]
150    impl Sealed for range::RangeFrom<usize> {}
151
152    impl Sealed for ops::IndexRange {}
153}
154
155/// A helper trait used for indexing operations.
156///
157/// Implementations of this trait have to promise that if the argument
158/// to `get_unchecked(_mut)` is a safe reference, then so is the result.
159#[stable(feature = "slice_get_slice", since = "1.28.0")]
160#[rustc_diagnostic_item = "SliceIndex"]
161#[rustc_on_unimplemented(
162    on(T = "str", label = "string indices are ranges of `usize`",),
163    on(
164        all(any(T = "str", T = "&str", T = "alloc::string::String"), _Self = "{integer}"),
165        note = "you can use `.chars().nth()` or `.bytes().nth()`\n\
166                for more information, see chapter 8 in The Book: \
167                <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
168    ),
169    message = "the type `{T}` cannot be indexed by `{Self}`",
170    label = "slice indices are of type `usize` or ranges of `usize`"
171)]
172pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
173    /// The output type returned by methods.
174    #[stable(feature = "slice_get_slice", since = "1.28.0")]
175    type Output: ?Sized;
176
177    /// Returns a shared reference to the output at this location, if in
178    /// bounds.
179    #[unstable(feature = "slice_index_methods", issue = "none")]
180    fn get(self, slice: &T) -> Option<&Self::Output>;
181
182    /// Returns a mutable reference to the output at this location, if in
183    /// bounds.
184    #[unstable(feature = "slice_index_methods", issue = "none")]
185    fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>;
186
187    /// Returns a pointer to the output at this location, without
188    /// performing any bounds checking.
189    ///
190    /// Calling this method with an out-of-bounds index or a dangling `slice` pointer
191    /// is *[undefined behavior]* even if the resulting pointer is not used.
192    ///
193    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
194    #[unstable(feature = "slice_index_methods", issue = "none")]
195    unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
196
197    /// Returns a mutable pointer to the output at this location, without
198    /// performing any bounds checking.
199    ///
200    /// Calling this method with an out-of-bounds index or a dangling `slice` pointer
201    /// is *[undefined behavior]* even if the resulting pointer is not used.
202    ///
203    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
204    #[unstable(feature = "slice_index_methods", issue = "none")]
205    unsafe fn get_unchecked_mut(self, slice: *mut T) -> *mut Self::Output;
206
207    /// Returns a shared reference to the output at this location, panicking
208    /// if out of bounds.
209    #[unstable(feature = "slice_index_methods", issue = "none")]
210    #[track_caller]
211    fn index(self, slice: &T) -> &Self::Output;
212
213    /// Returns a mutable reference to the output at this location, panicking
214    /// if out of bounds.
215    #[unstable(feature = "slice_index_methods", issue = "none")]
216    #[track_caller]
217    fn index_mut(self, slice: &mut T) -> &mut Self::Output;
218}
219
220/// The methods `index` and `index_mut` panic if the index is out of bounds.
221#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
222unsafe impl<T> SliceIndex<[T]> for usize {
223    type Output = T;
224
225    #[inline]
226    fn get(self, slice: &[T]) -> Option<&T> {
227        // SAFETY: `self` is checked to be in bounds.
228        if self < slice.len() { unsafe { Some(&*get_noubcheck(slice, self)) } } else { None }
229    }
230
231    #[inline]
232    fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
233        if self < slice.len() {
234            // SAFETY: `self` is checked to be in bounds.
235            unsafe { Some(&mut *get_mut_noubcheck(slice, self)) }
236        } else {
237            None
238        }
239    }
240
241    #[inline]
242    unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
243        assert_unsafe_precondition!(
244            check_language_ub,
245            "slice::get_unchecked requires that the index is within the slice",
246            (this: usize = self, len: usize = slice.len()) => this < len
247        );
248        // SAFETY: the caller guarantees that `slice` is not dangling, so it
249        // cannot be longer than `isize::MAX`. They also guarantee that
250        // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
251        // so the call to `add` is safe.
252        unsafe {
253            // Use intrinsics::assume instead of hint::assert_unchecked so that we don't check the
254            // precondition of this function twice.
255            crate::intrinsics::assume(self < slice.len());
256            get_noubcheck(slice, self)
257        }
258    }
259
260    #[inline]
261    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T {
262        assert_unsafe_precondition!(
263            check_library_ub,
264            "slice::get_unchecked_mut requires that the index is within the slice",
265            (this: usize = self, len: usize = slice.len()) => this < len
266        );
267        // SAFETY: see comments for `get_unchecked` above.
268        unsafe { get_mut_noubcheck(slice, self) }
269    }
270
271    #[inline]
272    fn index(self, slice: &[T]) -> &T {
273        // N.B., use intrinsic indexing
274        &(*slice)[self]
275    }
276
277    #[inline]
278    fn index_mut(self, slice: &mut [T]) -> &mut T {
279        // N.B., use intrinsic indexing
280        &mut (*slice)[self]
281    }
282}
283
284/// Because `IndexRange` guarantees `start <= end`, fewer checks are needed here
285/// than there are for a general `Range<usize>` (which might be `100..3`).
286unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
287    type Output = [T];
288
289    #[inline]
290    fn get(self, slice: &[T]) -> Option<&[T]> {
291        if self.end() <= slice.len() {
292            // SAFETY: `self` is checked to be valid and in bounds above.
293            unsafe { Some(&*get_offset_len_noubcheck(slice, self.start(), self.len())) }
294        } else {
295            None
296        }
297    }
298
299    #[inline]
300    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
301        if self.end() <= slice.len() {
302            // SAFETY: `self` is checked to be valid and in bounds above.
303            unsafe { Some(&mut *get_offset_len_mut_noubcheck(slice, self.start(), self.len())) }
304        } else {
305            None
306        }
307    }
308
309    #[inline]
310    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
311        assert_unsafe_precondition!(
312            check_library_ub,
313            "slice::get_unchecked requires that the index is within the slice",
314            (end: usize = self.end(), len: usize = slice.len()) => end <= len
315        );
316        // SAFETY: the caller guarantees that `slice` is not dangling, so it
317        // cannot be longer than `isize::MAX`. They also guarantee that
318        // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
319        // so the call to `add` is safe.
320        unsafe { get_offset_len_noubcheck(slice, self.start(), self.len()) }
321    }
322
323    #[inline]
324    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
325        assert_unsafe_precondition!(
326            check_library_ub,
327            "slice::get_unchecked_mut requires that the index is within the slice",
328            (end: usize = self.end(), len: usize = slice.len()) => end <= len
329        );
330
331        // SAFETY: see comments for `get_unchecked` above.
332        unsafe { get_offset_len_mut_noubcheck(slice, self.start(), self.len()) }
333    }
334
335    #[inline]
336    fn index(self, slice: &[T]) -> &[T] {
337        if self.end() <= slice.len() {
338            // SAFETY: `self` is checked to be valid and in bounds above.
339            unsafe { &*get_offset_len_noubcheck(slice, self.start(), self.len()) }
340        } else {
341            slice_end_index_len_fail(self.end(), slice.len())
342        }
343    }
344
345    #[inline]
346    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
347        if self.end() <= slice.len() {
348            // SAFETY: `self` is checked to be valid and in bounds above.
349            unsafe { &mut *get_offset_len_mut_noubcheck(slice, self.start(), self.len()) }
350        } else {
351            slice_end_index_len_fail(self.end(), slice.len())
352        }
353    }
354}
355
356/// The methods `index` and `index_mut` panic if:
357/// - the start of the range is greater than the end of the range or
358/// - the end of the range is out of bounds.
359#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
360unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
361    type Output = [T];
362
363    #[inline]
364    fn get(self, slice: &[T]) -> Option<&[T]> {
365        // Using checked_sub is a safe way to get `SubUnchecked` in MIR
366        if let Some(new_len) = usize::checked_sub(self.end, self.start)
367            && self.end <= slice.len()
368        {
369            // SAFETY: `self` is checked to be valid and in bounds above.
370            unsafe { Some(&*get_offset_len_noubcheck(slice, self.start, new_len)) }
371        } else {
372            None
373        }
374    }
375
376    #[inline]
377    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
378        if let Some(new_len) = usize::checked_sub(self.end, self.start)
379            && self.end <= slice.len()
380        {
381            // SAFETY: `self` is checked to be valid and in bounds above.
382            unsafe { Some(&mut *get_offset_len_mut_noubcheck(slice, self.start, new_len)) }
383        } else {
384            None
385        }
386    }
387
388    #[inline]
389    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
390        assert_unsafe_precondition!(
391            check_library_ub,
392            "slice::get_unchecked requires that the range is within the slice",
393            (
394                start: usize = self.start,
395                end: usize = self.end,
396                len: usize = slice.len()
397            ) => end >= start && end <= len
398        );
399
400        // SAFETY: the caller guarantees that `slice` is not dangling, so it
401        // cannot be longer than `isize::MAX`. They also guarantee that
402        // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
403        // so the call to `add` is safe and the length calculation cannot overflow.
404        unsafe {
405            // Using the intrinsic avoids a superfluous UB check,
406            // since the one on this method already checked `end >= start`.
407            let new_len = crate::intrinsics::unchecked_sub(self.end, self.start);
408            get_offset_len_noubcheck(slice, self.start, new_len)
409        }
410    }
411
412    #[inline]
413    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
414        assert_unsafe_precondition!(
415            check_library_ub,
416            "slice::get_unchecked_mut requires that the range is within the slice",
417            (
418                start: usize = self.start,
419                end: usize = self.end,
420                len: usize = slice.len()
421            ) => end >= start && end <= len
422        );
423        // SAFETY: see comments for `get_unchecked` above.
424        unsafe {
425            let new_len = crate::intrinsics::unchecked_sub(self.end, self.start);
426            get_offset_len_mut_noubcheck(slice, self.start, new_len)
427        }
428    }
429
430    #[inline(always)]
431    fn index(self, slice: &[T]) -> &[T] {
432        // Using checked_sub is a safe way to get `SubUnchecked` in MIR
433        let Some(new_len) = usize::checked_sub(self.end, self.start) else {
434            slice_index_order_fail(self.start, self.end)
435        };
436        if self.end > slice.len() {
437            slice_end_index_len_fail(self.end, slice.len());
438        }
439        // SAFETY: `self` is checked to be valid and in bounds above.
440        unsafe { &*get_offset_len_noubcheck(slice, self.start, new_len) }
441    }
442
443    #[inline]
444    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
445        let Some(new_len) = usize::checked_sub(self.end, self.start) else {
446            slice_index_order_fail(self.start, self.end)
447        };
448        if self.end > slice.len() {
449            slice_end_index_len_fail(self.end, slice.len());
450        }
451        // SAFETY: `self` is checked to be valid and in bounds above.
452        unsafe { &mut *get_offset_len_mut_noubcheck(slice, self.start, new_len) }
453    }
454}
455
456#[unstable(feature = "new_range_api", issue = "125687")]
457unsafe impl<T> SliceIndex<[T]> for range::Range<usize> {
458    type Output = [T];
459
460    #[inline]
461    fn get(self, slice: &[T]) -> Option<&[T]> {
462        ops::Range::from(self).get(slice)
463    }
464
465    #[inline]
466    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
467        ops::Range::from(self).get_mut(slice)
468    }
469
470    #[inline]
471    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
472        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
473        unsafe { ops::Range::from(self).get_unchecked(slice) }
474    }
475
476    #[inline]
477    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
478        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
479        unsafe { ops::Range::from(self).get_unchecked_mut(slice) }
480    }
481
482    #[inline(always)]
483    fn index(self, slice: &[T]) -> &[T] {
484        ops::Range::from(self).index(slice)
485    }
486
487    #[inline]
488    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
489        ops::Range::from(self).index_mut(slice)
490    }
491}
492
493/// The methods `index` and `index_mut` panic if the end of the range is out of bounds.
494#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
495unsafe impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
496    type Output = [T];
497
498    #[inline]
499    fn get(self, slice: &[T]) -> Option<&[T]> {
500        (0..self.end).get(slice)
501    }
502
503    #[inline]
504    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
505        (0..self.end).get_mut(slice)
506    }
507
508    #[inline]
509    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
510        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
511        unsafe { (0..self.end).get_unchecked(slice) }
512    }
513
514    #[inline]
515    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
516        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
517        unsafe { (0..self.end).get_unchecked_mut(slice) }
518    }
519
520    #[inline(always)]
521    fn index(self, slice: &[T]) -> &[T] {
522        (0..self.end).index(slice)
523    }
524
525    #[inline]
526    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
527        (0..self.end).index_mut(slice)
528    }
529}
530
531/// The methods `index` and `index_mut` panic if the start of the range is out of bounds.
532#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
533unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
534    type Output = [T];
535
536    #[inline]
537    fn get(self, slice: &[T]) -> Option<&[T]> {
538        (self.start..slice.len()).get(slice)
539    }
540
541    #[inline]
542    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
543        (self.start..slice.len()).get_mut(slice)
544    }
545
546    #[inline]
547    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
548        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
549        unsafe { (self.start..slice.len()).get_unchecked(slice) }
550    }
551
552    #[inline]
553    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
554        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
555        unsafe { (self.start..slice.len()).get_unchecked_mut(slice) }
556    }
557
558    #[inline]
559    fn index(self, slice: &[T]) -> &[T] {
560        if self.start > slice.len() {
561            slice_start_index_len_fail(self.start, slice.len());
562        }
563        // SAFETY: `self` is checked to be valid and in bounds above.
564        unsafe { &*self.get_unchecked(slice) }
565    }
566
567    #[inline]
568    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
569        if self.start > slice.len() {
570            slice_start_index_len_fail(self.start, slice.len());
571        }
572        // SAFETY: `self` is checked to be valid and in bounds above.
573        unsafe { &mut *self.get_unchecked_mut(slice) }
574    }
575}
576
577#[unstable(feature = "new_range_api", issue = "125687")]
578unsafe impl<T> SliceIndex<[T]> for range::RangeFrom<usize> {
579    type Output = [T];
580
581    #[inline]
582    fn get(self, slice: &[T]) -> Option<&[T]> {
583        ops::RangeFrom::from(self).get(slice)
584    }
585
586    #[inline]
587    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
588        ops::RangeFrom::from(self).get_mut(slice)
589    }
590
591    #[inline]
592    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
593        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
594        unsafe { ops::RangeFrom::from(self).get_unchecked(slice) }
595    }
596
597    #[inline]
598    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
599        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
600        unsafe { ops::RangeFrom::from(self).get_unchecked_mut(slice) }
601    }
602
603    #[inline]
604    fn index(self, slice: &[T]) -> &[T] {
605        ops::RangeFrom::from(self).index(slice)
606    }
607
608    #[inline]
609    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
610        ops::RangeFrom::from(self).index_mut(slice)
611    }
612}
613
614#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
615unsafe impl<T> SliceIndex<[T]> for ops::RangeFull {
616    type Output = [T];
617
618    #[inline]
619    fn get(self, slice: &[T]) -> Option<&[T]> {
620        Some(slice)
621    }
622
623    #[inline]
624    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
625        Some(slice)
626    }
627
628    #[inline]
629    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
630        slice
631    }
632
633    #[inline]
634    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
635        slice
636    }
637
638    #[inline]
639    fn index(self, slice: &[T]) -> &[T] {
640        slice
641    }
642
643    #[inline]
644    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
645        slice
646    }
647}
648
649/// The methods `index` and `index_mut` panic if:
650/// - the end of the range is `usize::MAX` or
651/// - the start of the range is greater than the end of the range or
652/// - the end of the range is out of bounds.
653#[stable(feature = "inclusive_range", since = "1.26.0")]
654unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
655    type Output = [T];
656
657    #[inline]
658    fn get(self, slice: &[T]) -> Option<&[T]> {
659        if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
660    }
661
662    #[inline]
663    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
664        if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
665    }
666
667    #[inline]
668    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
669        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
670        unsafe { self.into_slice_range().get_unchecked(slice) }
671    }
672
673    #[inline]
674    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
675        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
676        unsafe { self.into_slice_range().get_unchecked_mut(slice) }
677    }
678
679    #[inline]
680    fn index(self, slice: &[T]) -> &[T] {
681        if *self.end() == usize::MAX {
682            slice_end_index_overflow_fail();
683        }
684        self.into_slice_range().index(slice)
685    }
686
687    #[inline]
688    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
689        if *self.end() == usize::MAX {
690            slice_end_index_overflow_fail();
691        }
692        self.into_slice_range().index_mut(slice)
693    }
694}
695
696#[unstable(feature = "new_range_api", issue = "125687")]
697unsafe impl<T> SliceIndex<[T]> for range::RangeInclusive<usize> {
698    type Output = [T];
699
700    #[inline]
701    fn get(self, slice: &[T]) -> Option<&[T]> {
702        ops::RangeInclusive::from(self).get(slice)
703    }
704
705    #[inline]
706    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
707        ops::RangeInclusive::from(self).get_mut(slice)
708    }
709
710    #[inline]
711    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
712        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
713        unsafe { ops::RangeInclusive::from(self).get_unchecked(slice) }
714    }
715
716    #[inline]
717    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
718        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
719        unsafe { ops::RangeInclusive::from(self).get_unchecked_mut(slice) }
720    }
721
722    #[inline]
723    fn index(self, slice: &[T]) -> &[T] {
724        ops::RangeInclusive::from(self).index(slice)
725    }
726
727    #[inline]
728    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
729        ops::RangeInclusive::from(self).index_mut(slice)
730    }
731}
732
733/// The methods `index` and `index_mut` panic if the end of the range is out of bounds.
734#[stable(feature = "inclusive_range", since = "1.26.0")]
735unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
736    type Output = [T];
737
738    #[inline]
739    fn get(self, slice: &[T]) -> Option<&[T]> {
740        (0..=self.end).get(slice)
741    }
742
743    #[inline]
744    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
745        (0..=self.end).get_mut(slice)
746    }
747
748    #[inline]
749    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
750        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
751        unsafe { (0..=self.end).get_unchecked(slice) }
752    }
753
754    #[inline]
755    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
756        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
757        unsafe { (0..=self.end).get_unchecked_mut(slice) }
758    }
759
760    #[inline]
761    fn index(self, slice: &[T]) -> &[T] {
762        (0..=self.end).index(slice)
763    }
764
765    #[inline]
766    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
767        (0..=self.end).index_mut(slice)
768    }
769}
770
771/// Performs bounds checking of a range.
772///
773/// This method is similar to [`Index::index`] for slices, but it returns a
774/// [`Range`] equivalent to `range`. You can use this method to turn any range
775/// into `start` and `end` values.
776///
777/// `bounds` is the range of the slice to use for bounds checking. It should
778/// be a [`RangeTo`] range that ends at the length of the slice.
779///
780/// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and
781/// [`slice::get_unchecked_mut`] for slices with the given range.
782///
783/// [`Range`]: ops::Range
784/// [`RangeTo`]: ops::RangeTo
785/// [`slice::get_unchecked`]: slice::get_unchecked
786/// [`slice::get_unchecked_mut`]: slice::get_unchecked_mut
787///
788/// # Panics
789///
790/// Panics if `range` would be out of bounds.
791///
792/// # Examples
793///
794/// ```
795/// #![feature(slice_range)]
796///
797/// use std::slice;
798///
799/// let v = [10, 40, 30];
800/// assert_eq!(1..2, slice::range(1..2, ..v.len()));
801/// assert_eq!(0..2, slice::range(..2, ..v.len()));
802/// assert_eq!(1..3, slice::range(1.., ..v.len()));
803/// ```
804///
805/// Panics when [`Index::index`] would panic:
806///
807/// ```should_panic
808/// #![feature(slice_range)]
809///
810/// use std::slice;
811///
812/// let _ = slice::range(2..1, ..3);
813/// ```
814///
815/// ```should_panic
816/// #![feature(slice_range)]
817///
818/// use std::slice;
819///
820/// let _ = slice::range(1..4, ..3);
821/// ```
822///
823/// ```should_panic
824/// #![feature(slice_range)]
825///
826/// use std::slice;
827///
828/// let _ = slice::range(1..=usize::MAX, ..3);
829/// ```
830///
831/// [`Index::index`]: ops::Index::index
832#[track_caller]
833#[unstable(feature = "slice_range", issue = "76393")]
834#[must_use]
835pub fn range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
836where
837    R: ops::RangeBounds<usize>,
838{
839    let len = bounds.end;
840
841    let start = match range.start_bound() {
842        ops::Bound::Included(&start) => start,
843        ops::Bound::Excluded(start) => {
844            start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
845        }
846        ops::Bound::Unbounded => 0,
847    };
848
849    let end = match range.end_bound() {
850        ops::Bound::Included(end) => {
851            end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
852        }
853        ops::Bound::Excluded(&end) => end,
854        ops::Bound::Unbounded => len,
855    };
856
857    if start > end {
858        slice_index_order_fail(start, end);
859    }
860    if end > len {
861        slice_end_index_len_fail(end, len);
862    }
863
864    ops::Range { start, end }
865}
866
867/// Performs bounds checking of a range without panicking.
868///
869/// This is a version of [`range()`] that returns [`None`] instead of panicking.
870///
871/// # Examples
872///
873/// ```
874/// #![feature(slice_range)]
875///
876/// use std::slice;
877///
878/// let v = [10, 40, 30];
879/// assert_eq!(Some(1..2), slice::try_range(1..2, ..v.len()));
880/// assert_eq!(Some(0..2), slice::try_range(..2, ..v.len()));
881/// assert_eq!(Some(1..3), slice::try_range(1.., ..v.len()));
882/// ```
883///
884/// Returns [`None`] when [`Index::index`] would panic:
885///
886/// ```
887/// #![feature(slice_range)]
888///
889/// use std::slice;
890///
891/// assert_eq!(None, slice::try_range(2..1, ..3));
892/// assert_eq!(None, slice::try_range(1..4, ..3));
893/// assert_eq!(None, slice::try_range(1..=usize::MAX, ..3));
894/// ```
895///
896/// [`Index::index`]: ops::Index::index
897#[unstable(feature = "slice_range", issue = "76393")]
898#[must_use]
899pub fn try_range<R>(range: R, bounds: ops::RangeTo<usize>) -> Option<ops::Range<usize>>
900where
901    R: ops::RangeBounds<usize>,
902{
903    let len = bounds.end;
904
905    let start = match range.start_bound() {
906        ops::Bound::Included(&start) => start,
907        ops::Bound::Excluded(start) => start.checked_add(1)?,
908        ops::Bound::Unbounded => 0,
909    };
910
911    let end = match range.end_bound() {
912        ops::Bound::Included(end) => end.checked_add(1)?,
913        ops::Bound::Excluded(&end) => end,
914        ops::Bound::Unbounded => len,
915    };
916
917    if start > end || end > len { None } else { Some(ops::Range { start, end }) }
918}
919
920/// Converts a pair of `ops::Bound`s into `ops::Range` without performing any
921/// bounds checking or (in debug) overflow checking.
922pub(crate) fn into_range_unchecked(
923    len: usize,
924    (start, end): (ops::Bound<usize>, ops::Bound<usize>),
925) -> ops::Range<usize> {
926    use ops::Bound;
927    let start = match start {
928        Bound::Included(i) => i,
929        Bound::Excluded(i) => i + 1,
930        Bound::Unbounded => 0,
931    };
932    let end = match end {
933        Bound::Included(i) => i + 1,
934        Bound::Excluded(i) => i,
935        Bound::Unbounded => len,
936    };
937    start..end
938}
939
940/// Converts pair of `ops::Bound`s into `ops::Range`.
941/// Returns `None` on overflowing indices.
942pub(crate) fn into_range(
943    len: usize,
944    (start, end): (ops::Bound<usize>, ops::Bound<usize>),
945) -> Option<ops::Range<usize>> {
946    use ops::Bound;
947    let start = match start {
948        Bound::Included(start) => start,
949        Bound::Excluded(start) => start.checked_add(1)?,
950        Bound::Unbounded => 0,
951    };
952
953    let end = match end {
954        Bound::Included(end) => end.checked_add(1)?,
955        Bound::Excluded(end) => end,
956        Bound::Unbounded => len,
957    };
958
959    // Don't bother with checking `start < end` and `end <= len`
960    // since these checks are handled by `Range` impls
961
962    Some(start..end)
963}
964
965/// Converts pair of `ops::Bound`s into `ops::Range`.
966/// Panics on overflowing indices.
967pub(crate) fn into_slice_range(
968    len: usize,
969    (start, end): (ops::Bound<usize>, ops::Bound<usize>),
970) -> ops::Range<usize> {
971    use ops::Bound;
972    let start = match start {
973        Bound::Included(start) => start,
974        Bound::Excluded(start) => {
975            start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
976        }
977        Bound::Unbounded => 0,
978    };
979
980    let end = match end {
981        Bound::Included(end) => {
982            end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
983        }
984        Bound::Excluded(end) => end,
985        Bound::Unbounded => len,
986    };
987
988    // Don't bother with checking `start < end` and `end <= len`
989    // since these checks are handled by `Range` impls
990
991    start..end
992}
993
994#[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")]
995unsafe impl<T> SliceIndex<[T]> for (ops::Bound<usize>, ops::Bound<usize>) {
996    type Output = [T];
997
998    #[inline]
999    fn get(self, slice: &[T]) -> Option<&Self::Output> {
1000        into_range(slice.len(), self)?.get(slice)
1001    }
1002
1003    #[inline]
1004    fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
1005        into_range(slice.len(), self)?.get_mut(slice)
1006    }
1007
1008    #[inline]
1009    unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
1010        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
1011        unsafe { into_range_unchecked(slice.len(), self).get_unchecked(slice) }
1012    }
1013
1014    #[inline]
1015    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
1016        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
1017        unsafe { into_range_unchecked(slice.len(), self).get_unchecked_mut(slice) }
1018    }
1019
1020    #[inline]
1021    fn index(self, slice: &[T]) -> &Self::Output {
1022        into_slice_range(slice.len(), self).index(slice)
1023    }
1024
1025    #[inline]
1026    fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
1027        into_slice_range(slice.len(), self).index_mut(slice)
1028    }
1029}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy