core/slice/
index.rs

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