1 //! Indexing implementations for `[T]`.
6 #[stable(feature = "rust1", since = "1.0.0")]
7 impl<T, I> ops::Index<I> for [T]
11 type Output = I::Output;
14 fn index(&self, index: I) -> &I::Output {
19 #[stable(feature = "rust1", since = "1.0.0")]
20 impl<T, I> ops::IndexMut<I> for [T]
25 fn index_mut(&mut self, index: I) -> &mut I::Output {
33 fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
34 panic!("range start index {} out of range for slice of length {}", index, len);
40 fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
41 panic!("range end index {} out of range for slice of length {}", index, len);
47 fn slice_index_order_fail(index: usize, end: usize) -> ! {
48 panic!("slice index starts at {} but ends at {}", index, end);
54 fn slice_start_index_overflow_fail() -> ! {
55 panic!("attempted to index slice from after maximum usize");
61 fn slice_end_index_overflow_fail() -> ! {
62 panic!("attempted to index slice up to maximum usize");
65 mod private_slice_index {
67 #[stable(feature = "slice_get_slice", since = "1.28.0")]
70 #[stable(feature = "slice_get_slice", since = "1.28.0")]
71 impl Sealed for usize {}
72 #[stable(feature = "slice_get_slice", since = "1.28.0")]
73 impl Sealed for ops::Range<usize> {}
74 #[stable(feature = "slice_get_slice", since = "1.28.0")]
75 impl Sealed for ops::RangeTo<usize> {}
76 #[stable(feature = "slice_get_slice", since = "1.28.0")]
77 impl Sealed for ops::RangeFrom<usize> {}
78 #[stable(feature = "slice_get_slice", since = "1.28.0")]
79 impl Sealed for ops::RangeFull {}
80 #[stable(feature = "slice_get_slice", since = "1.28.0")]
81 impl Sealed for ops::RangeInclusive<usize> {}
82 #[stable(feature = "slice_get_slice", since = "1.28.0")]
83 impl Sealed for ops::RangeToInclusive<usize> {}
84 #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.51.0")]
85 impl Sealed for (ops::Bound<usize>, ops::Bound<usize>) {}
88 /// A helper trait used for indexing operations.
90 /// Implementations of this trait have to promise that if the argument
91 /// to `get_(mut_)unchecked` is a safe reference, then so is the result.
92 #[stable(feature = "slice_get_slice", since = "1.28.0")]
93 #[rustc_on_unimplemented(
94 on(T = "str", label = "string indices are ranges of `usize`",),
96 all(any(T = "str", T = "&str", T = "std::string::String"), _Self = "{integer}"),
97 note = "you can use `.chars().nth()` or `.bytes().nth()`\n\
98 for more information, see chapter 8 in The Book: \
99 <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
101 message = "the type `{T}` cannot be indexed by `{Self}`",
102 label = "slice indices are of type `usize` or ranges of `usize`"
104 pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
105 /// The output type returned by methods.
106 #[stable(feature = "slice_get_slice", since = "1.28.0")]
109 /// Returns a shared reference to the output at this location, if in
111 #[unstable(feature = "slice_index_methods", issue = "none")]
112 fn get(self, slice: &T) -> Option<&Self::Output>;
114 /// Returns a mutable reference to the output at this location, if in
116 #[unstable(feature = "slice_index_methods", issue = "none")]
117 fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>;
119 /// Returns a shared reference to the output at this location, without
120 /// performing any bounds checking.
121 /// Calling this method with an out-of-bounds index or a dangling `slice` pointer
122 /// is *[undefined behavior]* even if the resulting reference is not used.
124 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
125 #[unstable(feature = "slice_index_methods", issue = "none")]
126 unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
128 /// Returns a mutable reference to the output at this location, without
129 /// performing any bounds checking.
130 /// Calling this method with an out-of-bounds index or a dangling `slice` pointer
131 /// is *[undefined behavior]* even if the resulting reference is not used.
133 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
134 #[unstable(feature = "slice_index_methods", issue = "none")]
135 unsafe fn get_unchecked_mut(self, slice: *mut T) -> *mut Self::Output;
137 /// Returns a shared reference to the output at this location, panicking
138 /// if out of bounds.
139 #[unstable(feature = "slice_index_methods", issue = "none")]
141 fn index(self, slice: &T) -> &Self::Output;
143 /// Returns a mutable reference to the output at this location, panicking
144 /// if out of bounds.
145 #[unstable(feature = "slice_index_methods", issue = "none")]
147 fn index_mut(self, slice: &mut T) -> &mut Self::Output;
150 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
151 unsafe impl<T> SliceIndex<[T]> for usize {
155 fn get(self, slice: &[T]) -> Option<&T> {
156 // SAFETY: `self` is checked to be in bounds.
157 if self < slice.len() { unsafe { Some(&*self.get_unchecked(slice)) } } else { None }
161 fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
162 // SAFETY: `self` is checked to be in bounds.
163 if self < slice.len() { unsafe { Some(&mut *self.get_unchecked_mut(slice)) } } else { None }
167 unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
168 // SAFETY: the caller guarantees that `slice` is not dangling, so it
169 // cannot be longer than `isize::MAX`. They also guarantee that
170 // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
171 // so the call to `add` is safe.
172 unsafe { slice.as_ptr().add(self) }
176 unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T {
177 // SAFETY: see comments for `get_unchecked` above.
178 unsafe { slice.as_mut_ptr().add(self) }
182 fn index(self, slice: &[T]) -> &T {
183 // N.B., use intrinsic indexing
188 fn index_mut(self, slice: &mut [T]) -> &mut T {
189 // N.B., use intrinsic indexing
194 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
195 unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
199 fn get(self, slice: &[T]) -> Option<&[T]> {
200 if self.start > self.end || self.end > slice.len() {
203 // SAFETY: `self` is checked to be valid and in bounds above.
204 unsafe { Some(&*self.get_unchecked(slice)) }
209 fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
210 if self.start > self.end || self.end > slice.len() {
213 // SAFETY: `self` is checked to be valid and in bounds above.
214 unsafe { Some(&mut *self.get_unchecked_mut(slice)) }
219 unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
220 // SAFETY: the caller guarantees that `slice` is not dangling, so it
221 // cannot be longer than `isize::MAX`. They also guarantee that
222 // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
223 // so the call to `add` is safe.
224 unsafe { ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start) }
228 unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
229 // SAFETY: see comments for `get_unchecked` above.
231 ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start)
236 fn index(self, slice: &[T]) -> &[T] {
237 if self.start > self.end {
238 slice_index_order_fail(self.start, self.end);
239 } else if self.end > slice.len() {
240 slice_end_index_len_fail(self.end, slice.len());
242 // SAFETY: `self` is checked to be valid and in bounds above.
243 unsafe { &*self.get_unchecked(slice) }
247 fn index_mut(self, slice: &mut [T]) -> &mut [T] {
248 if self.start > self.end {
249 slice_index_order_fail(self.start, self.end);
250 } else if self.end > slice.len() {
251 slice_end_index_len_fail(self.end, slice.len());
253 // SAFETY: `self` is checked to be valid and in bounds above.
254 unsafe { &mut *self.get_unchecked_mut(slice) }
258 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
259 unsafe impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
263 fn get(self, slice: &[T]) -> Option<&[T]> {
264 (0..self.end).get(slice)
268 fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
269 (0..self.end).get_mut(slice)
273 unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
274 // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
275 unsafe { (0..self.end).get_unchecked(slice) }
279 unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
280 // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
281 unsafe { (0..self.end).get_unchecked_mut(slice) }
285 fn index(self, slice: &[T]) -> &[T] {
286 (0..self.end).index(slice)
290 fn index_mut(self, slice: &mut [T]) -> &mut [T] {
291 (0..self.end).index_mut(slice)
295 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
296 unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
300 fn get(self, slice: &[T]) -> Option<&[T]> {
301 (self.start..slice.len()).get(slice)
305 fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
306 (self.start..slice.len()).get_mut(slice)
310 unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
311 // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
312 unsafe { (self.start..slice.len()).get_unchecked(slice) }
316 unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
317 // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
318 unsafe { (self.start..slice.len()).get_unchecked_mut(slice) }
322 fn index(self, slice: &[T]) -> &[T] {
323 if self.start > slice.len() {
324 slice_start_index_len_fail(self.start, slice.len());
326 // SAFETY: `self` is checked to be valid and in bounds above.
327 unsafe { &*self.get_unchecked(slice) }
331 fn index_mut(self, slice: &mut [T]) -> &mut [T] {
332 if self.start > slice.len() {
333 slice_start_index_len_fail(self.start, slice.len());
335 // SAFETY: `self` is checked to be valid and in bounds above.
336 unsafe { &mut *self.get_unchecked_mut(slice) }
340 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
341 unsafe impl<T> SliceIndex<[T]> for ops::RangeFull {
345 fn get(self, slice: &[T]) -> Option<&[T]> {
350 fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
355 unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
360 unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
365 fn index(self, slice: &[T]) -> &[T] {
370 fn index_mut(self, slice: &mut [T]) -> &mut [T] {
375 #[stable(feature = "inclusive_range", since = "1.26.0")]
376 unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
380 fn get(self, slice: &[T]) -> Option<&[T]> {
381 if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
385 fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
386 if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
390 unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
391 // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
392 unsafe { self.into_slice_range().get_unchecked(slice) }
396 unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
397 // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
398 unsafe { self.into_slice_range().get_unchecked_mut(slice) }
402 fn index(self, slice: &[T]) -> &[T] {
403 if *self.end() == usize::MAX {
404 slice_end_index_overflow_fail();
406 self.into_slice_range().index(slice)
410 fn index_mut(self, slice: &mut [T]) -> &mut [T] {
411 if *self.end() == usize::MAX {
412 slice_end_index_overflow_fail();
414 self.into_slice_range().index_mut(slice)
418 #[stable(feature = "inclusive_range", since = "1.26.0")]
419 unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
423 fn get(self, slice: &[T]) -> Option<&[T]> {
424 (0..=self.end).get(slice)
428 fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
429 (0..=self.end).get_mut(slice)
433 unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
434 // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
435 unsafe { (0..=self.end).get_unchecked(slice) }
439 unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
440 // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
441 unsafe { (0..=self.end).get_unchecked_mut(slice) }
445 fn index(self, slice: &[T]) -> &[T] {
446 (0..=self.end).index(slice)
450 fn index_mut(self, slice: &mut [T]) -> &mut [T] {
451 (0..=self.end).index_mut(slice)
455 /// Performs bounds-checking of a range.
457 /// This method is similar to [`Index::index`] for slices, but it returns a
458 /// [`Range`] equivalent to `range`. You can use this method to turn any range
459 /// into `start` and `end` values.
461 /// `bounds` is the range of the slice to use for bounds-checking. It should
462 /// be a [`RangeTo`] range that ends at the length of the slice.
464 /// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and
465 /// [`slice::get_unchecked_mut`] for slices with the given range.
467 /// [`Range`]: ops::Range
468 /// [`RangeTo`]: ops::RangeTo
469 /// [`slice::get_unchecked`]: slice::get_unchecked
470 /// [`slice::get_unchecked_mut`]: slice::get_unchecked_mut
474 /// Panics if `range` would be out of bounds.
479 /// #![feature(slice_range)]
483 /// let v = [10, 40, 30];
484 /// assert_eq!(1..2, slice::range(1..2, ..v.len()));
485 /// assert_eq!(0..2, slice::range(..2, ..v.len()));
486 /// assert_eq!(1..3, slice::range(1.., ..v.len()));
489 /// Panics when [`Index::index`] would panic:
492 /// #![feature(slice_range)]
496 /// slice::range(2..1, ..3);
500 /// #![feature(slice_range)]
504 /// slice::range(1..4, ..3);
508 /// #![feature(slice_range)]
512 /// slice::range(1..=usize::MAX, ..3);
515 /// [`Index::index`]: ops::Index::index
517 #[unstable(feature = "slice_range", issue = "76393")]
518 pub fn range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
520 R: ops::RangeBounds<usize>,
522 let len = bounds.end;
524 let start: ops::Bound<&usize> = range.start_bound();
525 let start = match start {
526 ops::Bound::Included(&start) => start,
527 ops::Bound::Excluded(start) => {
528 start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
530 ops::Bound::Unbounded => 0,
533 let end: ops::Bound<&usize> = range.end_bound();
534 let end = match end {
535 ops::Bound::Included(end) => {
536 end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
538 ops::Bound::Excluded(&end) => end,
539 ops::Bound::Unbounded => len,
543 slice_index_order_fail(start, end);
546 slice_end_index_len_fail(end, len);
549 ops::Range { start, end }
552 /// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking
553 fn into_range_unchecked(
555 (start, end): (ops::Bound<usize>, ops::Bound<usize>),
556 ) -> ops::Range<usize> {
558 let start = match start {
559 Bound::Included(i) => i,
560 Bound::Excluded(i) => i + 1,
561 Bound::Unbounded => 0,
563 let end = match end {
564 Bound::Included(i) => i + 1,
565 Bound::Excluded(i) => i,
566 Bound::Unbounded => len,
571 /// Convert pair of `ops::Bound`s into `ops::Range`.
572 /// Returns `None` on overflowing indices.
575 (start, end): (ops::Bound<usize>, ops::Bound<usize>),
576 ) -> Option<ops::Range<usize>> {
578 let start = match start {
579 Bound::Included(start) => start,
580 Bound::Excluded(start) => start.checked_add(1)?,
581 Bound::Unbounded => 0,
584 let end = match end {
585 Bound::Included(end) => end.checked_add(1)?,
586 Bound::Excluded(end) => end,
587 Bound::Unbounded => len,
590 // Don't bother with checking `start < end` and `end <= len`
591 // since these checks are handled by `Range` impls
596 /// Convert pair of `ops::Bound`s into `ops::Range`.
597 /// Panics on overflowing indices.
600 (start, end): (ops::Bound<usize>, ops::Bound<usize>),
601 ) -> ops::Range<usize> {
603 let start = match start {
604 Bound::Included(start) => start,
605 Bound::Excluded(start) => {
606 start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
608 Bound::Unbounded => 0,
611 let end = match end {
612 Bound::Included(end) => {
613 end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
615 Bound::Excluded(end) => end,
616 Bound::Unbounded => len,
619 // Don't bother with checking `start < end` and `end <= len`
620 // since these checks are handled by `Range` impls
625 #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.51.0")]
626 unsafe impl<T> SliceIndex<[T]> for (ops::Bound<usize>, ops::Bound<usize>) {
630 fn get(self, slice: &[T]) -> Option<&Self::Output> {
631 into_range(slice.len(), self)?.get(slice)
635 fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
636 into_range(slice.len(), self)?.get_mut(slice)
640 unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
641 // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
642 unsafe { into_range_unchecked(slice.len(), self).get_unchecked(slice) }
646 unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
647 // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
648 unsafe { into_range_unchecked(slice.len(), self).get_unchecked_mut(slice) }
652 fn index(self, slice: &[T]) -> &Self::Output {
653 into_slice_range(slice.len(), self).index(slice)
657 fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
658 into_slice_range(slice.len(), self).index_mut(slice)