1 | //! Indexing implementations for `[T]`. |
2 | |
3 | use crate::intrinsics::const_eval_select; |
4 | use crate::intrinsics::unchecked_sub; |
5 | use crate::ops; |
6 | use crate::panic::debug_assert_nounwind; |
7 | use crate::ptr; |
8 | |
9 | #[stable (feature = "rust1" , since = "1.0.0" )] |
10 | impl<T, I> ops::Index<I> for [T] |
11 | where |
12 | I: SliceIndex<[T]>, |
13 | { |
14 | type Output = I::Output; |
15 | |
16 | #[inline ] |
17 | fn index(&self, index: I) -> &I::Output { |
18 | index.index(self) |
19 | } |
20 | } |
21 | |
22 | #[stable (feature = "rust1" , since = "1.0.0" )] |
23 | impl<T, I> ops::IndexMut<I> for [T] |
24 | where |
25 | I: SliceIndex<[T]>, |
26 | { |
27 | #[inline ] |
28 | fn index_mut(&mut self, index: I) -> &mut I::Output { |
29 | index.index_mut(self) |
30 | } |
31 | } |
32 | |
33 | #[cfg_attr (not(feature = "panic_immediate_abort" ), inline(never), cold)] |
34 | #[cfg_attr (feature = "panic_immediate_abort" , inline)] |
35 | #[track_caller ] |
36 | #[rustc_const_unstable (feature = "const_slice_index" , issue = "none" )] |
37 | const fn slice_start_index_len_fail(index: usize, len: usize) -> ! { |
38 | // SAFETY: we are just panicking here |
39 | unsafe { |
40 | const_eval_select( |
41 | (index, len), |
42 | called_in_const:slice_start_index_len_fail_ct, |
43 | called_at_rt:slice_start_index_len_fail_rt, |
44 | ) |
45 | } |
46 | } |
47 | |
48 | // FIXME const-hack |
49 | #[inline ] |
50 | #[track_caller ] |
51 | fn slice_start_index_len_fail_rt(index: usize, len: usize) -> ! { |
52 | panic!("range start index {index} out of range for slice of length {len}" ); |
53 | } |
54 | |
55 | #[inline ] |
56 | #[track_caller ] |
57 | const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! { |
58 | panic!("slice start index is out of range for slice" ); |
59 | } |
60 | |
61 | #[cfg_attr (not(feature = "panic_immediate_abort" ), inline(never), cold)] |
62 | #[cfg_attr (feature = "panic_immediate_abort" , inline)] |
63 | #[track_caller ] |
64 | #[rustc_const_unstable (feature = "const_slice_index" , issue = "none" )] |
65 | const fn slice_end_index_len_fail(index: usize, len: usize) -> ! { |
66 | // SAFETY: we are just panicking here |
67 | unsafe { |
68 | const_eval_select((index, len), called_in_const:slice_end_index_len_fail_ct, called_at_rt:slice_end_index_len_fail_rt) |
69 | } |
70 | } |
71 | |
72 | // FIXME const-hack |
73 | #[inline ] |
74 | #[track_caller ] |
75 | fn slice_end_index_len_fail_rt(index: usize, len: usize) -> ! { |
76 | panic!("range end index {index} out of range for slice of length {len}" ); |
77 | } |
78 | |
79 | #[inline ] |
80 | #[track_caller ] |
81 | const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! { |
82 | panic!("slice end index is out of range for slice" ); |
83 | } |
84 | |
85 | #[cfg_attr (not(feature = "panic_immediate_abort" ), inline(never), cold)] |
86 | #[cfg_attr (feature = "panic_immediate_abort" , inline)] |
87 | #[track_caller ] |
88 | #[rustc_const_unstable (feature = "const_slice_index" , issue = "none" )] |
89 | const fn slice_index_order_fail(index: usize, end: usize) -> ! { |
90 | // SAFETY: we are just panicking here |
91 | unsafe { const_eval_select((index, end), called_in_const:slice_index_order_fail_ct, called_at_rt:slice_index_order_fail_rt) } |
92 | } |
93 | |
94 | // FIXME const-hack |
95 | #[inline ] |
96 | #[track_caller ] |
97 | fn slice_index_order_fail_rt(index: usize, end: usize) -> ! { |
98 | panic!("slice index starts at {index} but ends at {end}" ); |
99 | } |
100 | |
101 | #[inline ] |
102 | #[track_caller ] |
103 | const fn slice_index_order_fail_ct(_: usize, _: usize) -> ! { |
104 | panic!("slice index start is larger than end" ); |
105 | } |
106 | |
107 | #[cfg_attr (not(feature = "panic_immediate_abort" ), inline(never), cold)] |
108 | #[cfg_attr (feature = "panic_immediate_abort" , inline)] |
109 | #[track_caller ] |
110 | const fn slice_start_index_overflow_fail() -> ! { |
111 | panic!("attempted to index slice from after maximum usize" ); |
112 | } |
113 | |
114 | #[cfg_attr (not(feature = "panic_immediate_abort" ), inline(never), cold)] |
115 | #[cfg_attr (feature = "panic_immediate_abort" , inline)] |
116 | #[track_caller ] |
117 | const fn slice_end_index_overflow_fail() -> ! { |
118 | panic!("attempted to index slice up to maximum usize" ); |
119 | } |
120 | |
121 | mod private_slice_index { |
122 | use super::ops; |
123 | #[stable (feature = "slice_get_slice" , since = "1.28.0" )] |
124 | pub trait Sealed {} |
125 | |
126 | #[stable (feature = "slice_get_slice" , since = "1.28.0" )] |
127 | impl Sealed for usize {} |
128 | #[stable (feature = "slice_get_slice" , since = "1.28.0" )] |
129 | impl Sealed for ops::Range<usize> {} |
130 | #[stable (feature = "slice_get_slice" , since = "1.28.0" )] |
131 | impl Sealed for ops::RangeTo<usize> {} |
132 | #[stable (feature = "slice_get_slice" , since = "1.28.0" )] |
133 | impl Sealed for ops::RangeFrom<usize> {} |
134 | #[stable (feature = "slice_get_slice" , since = "1.28.0" )] |
135 | impl Sealed for ops::RangeFull {} |
136 | #[stable (feature = "slice_get_slice" , since = "1.28.0" )] |
137 | impl Sealed for ops::RangeInclusive<usize> {} |
138 | #[stable (feature = "slice_get_slice" , since = "1.28.0" )] |
139 | impl Sealed for ops::RangeToInclusive<usize> {} |
140 | #[stable (feature = "slice_index_with_ops_bound_pair" , since = "1.53.0" )] |
141 | impl Sealed for (ops::Bound<usize>, ops::Bound<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 | pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed { |
164 | /// The output type returned by methods. |
165 | #[stable (feature = "slice_get_slice" , since = "1.28.0" )] |
166 | type Output: ?Sized; |
167 | |
168 | /// Returns a shared reference to the output at this location, if in |
169 | /// bounds. |
170 | #[unstable (feature = "slice_index_methods" , issue = "none" )] |
171 | fn get(self, slice: &T) -> Option<&Self::Output>; |
172 | |
173 | /// Returns a mutable reference to the output at this location, if in |
174 | /// bounds. |
175 | #[unstable (feature = "slice_index_methods" , issue = "none" )] |
176 | fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>; |
177 | |
178 | /// Returns a shared reference to the output at this location, without |
179 | /// performing any bounds checking. |
180 | /// Calling this method with an out-of-bounds index or a dangling `slice` pointer |
181 | /// is *[undefined behavior]* even if the resulting reference is not used. |
182 | /// |
183 | /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html |
184 | #[unstable (feature = "slice_index_methods" , issue = "none" )] |
185 | unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output; |
186 | |
187 | /// Returns a mutable reference to the output at this location, without |
188 | /// performing any bounds checking. |
189 | /// Calling this method with an out-of-bounds index or a dangling `slice` pointer |
190 | /// is *[undefined behavior]* even if the resulting reference is not used. |
191 | /// |
192 | /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html |
193 | #[unstable (feature = "slice_index_methods" , issue = "none" )] |
194 | unsafe fn get_unchecked_mut(self, slice: *mut T) -> *mut Self::Output; |
195 | |
196 | /// Returns a shared reference to the output at this location, panicking |
197 | /// if out of bounds. |
198 | #[unstable (feature = "slice_index_methods" , issue = "none" )] |
199 | #[track_caller ] |
200 | fn index(self, slice: &T) -> &Self::Output; |
201 | |
202 | /// Returns a mutable reference to the output at this location, panicking |
203 | /// if out of bounds. |
204 | #[unstable (feature = "slice_index_methods" , issue = "none" )] |
205 | #[track_caller ] |
206 | fn index_mut(self, slice: &mut T) -> &mut Self::Output; |
207 | } |
208 | |
209 | #[stable (feature = "slice_get_slice_impls" , since = "1.15.0" )] |
210 | #[rustc_const_unstable (feature = "const_slice_index" , issue = "none" )] |
211 | unsafe impl<T> SliceIndex<[T]> for usize { |
212 | type Output = T; |
213 | |
214 | #[inline ] |
215 | fn get(self, slice: &[T]) -> Option<&T> { |
216 | // SAFETY: `self` is checked to be in bounds. |
217 | if self < slice.len() { unsafe { Some(&*self.get_unchecked(slice)) } } else { None } |
218 | } |
219 | |
220 | #[inline ] |
221 | fn get_mut(self, slice: &mut [T]) -> Option<&mut T> { |
222 | // SAFETY: `self` is checked to be in bounds. |
223 | if self < slice.len() { unsafe { Some(&mut *self.get_unchecked_mut(slice)) } } else { None } |
224 | } |
225 | |
226 | #[inline ] |
227 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const T { |
228 | debug_assert_nounwind!( |
229 | self < slice.len(), |
230 | "slice::get_unchecked requires that the index is within the slice" , |
231 | ); |
232 | // SAFETY: the caller guarantees that `slice` is not dangling, so it |
233 | // cannot be longer than `isize::MAX`. They also guarantee that |
234 | // `self` is in bounds of `slice` so `self` cannot overflow an `isize`, |
235 | // so the call to `add` is safe. |
236 | unsafe { |
237 | crate::hint::assert_unchecked(self < slice.len()); |
238 | slice.as_ptr().add(self) |
239 | } |
240 | } |
241 | |
242 | #[inline ] |
243 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T { |
244 | debug_assert_nounwind!( |
245 | self < slice.len(), |
246 | "slice::get_unchecked_mut requires that the index is within the slice" , |
247 | ); |
248 | // SAFETY: see comments for `get_unchecked` above. |
249 | unsafe { slice.as_mut_ptr().add(self) } |
250 | } |
251 | |
252 | #[inline ] |
253 | fn index(self, slice: &[T]) -> &T { |
254 | // N.B., use intrinsic indexing |
255 | &(*slice)[self] |
256 | } |
257 | |
258 | #[inline ] |
259 | fn index_mut(self, slice: &mut [T]) -> &mut T { |
260 | // N.B., use intrinsic indexing |
261 | &mut (*slice)[self] |
262 | } |
263 | } |
264 | |
265 | /// Because `IndexRange` guarantees `start <= end`, fewer checks are needed here |
266 | /// than there are for a general `Range<usize>` (which might be `100..3`). |
267 | #[rustc_const_unstable (feature = "const_index_range_slice_index" , issue = "none" )] |
268 | unsafe impl<T> SliceIndex<[T]> for ops::IndexRange { |
269 | type Output = [T]; |
270 | |
271 | #[inline ] |
272 | fn get(self, slice: &[T]) -> Option<&[T]> { |
273 | if self.end() <= slice.len() { |
274 | // SAFETY: `self` is checked to be valid and in bounds above. |
275 | unsafe { Some(&*self.get_unchecked(slice)) } |
276 | } else { |
277 | None |
278 | } |
279 | } |
280 | |
281 | #[inline ] |
282 | fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { |
283 | if self.end() <= slice.len() { |
284 | // SAFETY: `self` is checked to be valid and in bounds above. |
285 | unsafe { Some(&mut *self.get_unchecked_mut(slice)) } |
286 | } else { |
287 | None |
288 | } |
289 | } |
290 | |
291 | #[inline ] |
292 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { |
293 | debug_assert_nounwind!( |
294 | self.end() <= slice.len(), |
295 | "slice::get_unchecked requires that the index is within the slice" |
296 | ); |
297 | // SAFETY: the caller guarantees that `slice` is not dangling, so it |
298 | // cannot be longer than `isize::MAX`. They also guarantee that |
299 | // `self` is in bounds of `slice` so `self` cannot overflow an `isize`, |
300 | // so the call to `add` is safe. |
301 | unsafe { ptr::slice_from_raw_parts(slice.as_ptr().add(self.start()), self.len()) } |
302 | } |
303 | |
304 | #[inline ] |
305 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { |
306 | debug_assert_nounwind!( |
307 | self.end() <= slice.len(), |
308 | "slice::get_unchecked_mut requires that the index is within the slice" , |
309 | ); |
310 | // SAFETY: see comments for `get_unchecked` above. |
311 | unsafe { ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start()), self.len()) } |
312 | } |
313 | |
314 | #[inline ] |
315 | fn index(self, slice: &[T]) -> &[T] { |
316 | if self.end() <= slice.len() { |
317 | // SAFETY: `self` is checked to be valid and in bounds above. |
318 | unsafe { &*self.get_unchecked(slice) } |
319 | } else { |
320 | slice_end_index_len_fail(self.end(), slice.len()) |
321 | } |
322 | } |
323 | |
324 | #[inline ] |
325 | fn index_mut(self, slice: &mut [T]) -> &mut [T] { |
326 | if self.end() <= slice.len() { |
327 | // SAFETY: `self` is checked to be valid and in bounds above. |
328 | unsafe { &mut *self.get_unchecked_mut(slice) } |
329 | } else { |
330 | slice_end_index_len_fail(self.end(), slice.len()) |
331 | } |
332 | } |
333 | } |
334 | |
335 | #[stable (feature = "slice_get_slice_impls" , since = "1.15.0" )] |
336 | #[rustc_const_unstable (feature = "const_slice_index" , issue = "none" )] |
337 | unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> { |
338 | type Output = [T]; |
339 | |
340 | #[inline ] |
341 | fn get(self, slice: &[T]) -> Option<&[T]> { |
342 | if self.start > self.end || self.end > slice.len() { |
343 | None |
344 | } else { |
345 | // SAFETY: `self` is checked to be valid and in bounds above. |
346 | unsafe { Some(&*self.get_unchecked(slice)) } |
347 | } |
348 | } |
349 | |
350 | #[inline ] |
351 | fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { |
352 | if self.start > self.end || self.end > slice.len() { |
353 | None |
354 | } else { |
355 | // SAFETY: `self` is checked to be valid and in bounds above. |
356 | unsafe { Some(&mut *self.get_unchecked_mut(slice)) } |
357 | } |
358 | } |
359 | |
360 | #[inline ] |
361 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { |
362 | debug_assert_nounwind!( |
363 | self.end >= self.start && self.end <= slice.len(), |
364 | "slice::get_unchecked requires that the range is within the slice" , |
365 | ); |
366 | // SAFETY: the caller guarantees that `slice` is not dangling, so it |
367 | // cannot be longer than `isize::MAX`. They also guarantee that |
368 | // `self` is in bounds of `slice` so `self` cannot overflow an `isize`, |
369 | // so the call to `add` is safe and the length calculation cannot overflow. |
370 | unsafe { |
371 | let new_len = unchecked_sub(self.end, self.start); |
372 | ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) |
373 | } |
374 | } |
375 | |
376 | #[inline ] |
377 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { |
378 | debug_assert_nounwind!( |
379 | self.end >= self.start && self.end <= slice.len(), |
380 | "slice::get_unchecked_mut requires that the range is within the slice" , |
381 | ); |
382 | // SAFETY: see comments for `get_unchecked` above. |
383 | unsafe { |
384 | let new_len = unchecked_sub(self.end, self.start); |
385 | ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) |
386 | } |
387 | } |
388 | |
389 | #[inline ] |
390 | fn index(self, slice: &[T]) -> &[T] { |
391 | if self.start > self.end { |
392 | slice_index_order_fail(self.start, self.end); |
393 | } else if self.end > slice.len() { |
394 | slice_end_index_len_fail(self.end, slice.len()); |
395 | } |
396 | // SAFETY: `self` is checked to be valid and in bounds above. |
397 | unsafe { &*self.get_unchecked(slice) } |
398 | } |
399 | |
400 | #[inline ] |
401 | fn index_mut(self, slice: &mut [T]) -> &mut [T] { |
402 | if self.start > self.end { |
403 | slice_index_order_fail(self.start, self.end); |
404 | } else if self.end > slice.len() { |
405 | slice_end_index_len_fail(self.end, slice.len()); |
406 | } |
407 | // SAFETY: `self` is checked to be valid and in bounds above. |
408 | unsafe { &mut *self.get_unchecked_mut(slice) } |
409 | } |
410 | } |
411 | |
412 | #[stable (feature = "slice_get_slice_impls" , since = "1.15.0" )] |
413 | #[rustc_const_unstable (feature = "const_slice_index" , issue = "none" )] |
414 | unsafe impl<T> SliceIndex<[T]> for ops::RangeTo<usize> { |
415 | type Output = [T]; |
416 | |
417 | #[inline ] |
418 | fn get(self, slice: &[T]) -> Option<&[T]> { |
419 | (0..self.end).get(slice) |
420 | } |
421 | |
422 | #[inline ] |
423 | fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { |
424 | (0..self.end).get_mut(slice) |
425 | } |
426 | |
427 | #[inline ] |
428 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { |
429 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. |
430 | unsafe { (0..self.end).get_unchecked(slice) } |
431 | } |
432 | |
433 | #[inline ] |
434 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { |
435 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. |
436 | unsafe { (0..self.end).get_unchecked_mut(slice) } |
437 | } |
438 | |
439 | #[inline ] |
440 | fn index(self, slice: &[T]) -> &[T] { |
441 | (0..self.end).index(slice) |
442 | } |
443 | |
444 | #[inline ] |
445 | fn index_mut(self, slice: &mut [T]) -> &mut [T] { |
446 | (0..self.end).index_mut(slice) |
447 | } |
448 | } |
449 | |
450 | #[stable (feature = "slice_get_slice_impls" , since = "1.15.0" )] |
451 | #[rustc_const_unstable (feature = "const_slice_index" , issue = "none" )] |
452 | unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> { |
453 | type Output = [T]; |
454 | |
455 | #[inline ] |
456 | fn get(self, slice: &[T]) -> Option<&[T]> { |
457 | (self.start..slice.len()).get(slice) |
458 | } |
459 | |
460 | #[inline ] |
461 | fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { |
462 | (self.start..slice.len()).get_mut(slice) |
463 | } |
464 | |
465 | #[inline ] |
466 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { |
467 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. |
468 | unsafe { (self.start..slice.len()).get_unchecked(slice) } |
469 | } |
470 | |
471 | #[inline ] |
472 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { |
473 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. |
474 | unsafe { (self.start..slice.len()).get_unchecked_mut(slice) } |
475 | } |
476 | |
477 | #[inline ] |
478 | fn index(self, slice: &[T]) -> &[T] { |
479 | if self.start > slice.len() { |
480 | slice_start_index_len_fail(self.start, slice.len()); |
481 | } |
482 | // SAFETY: `self` is checked to be valid and in bounds above. |
483 | unsafe { &*self.get_unchecked(slice) } |
484 | } |
485 | |
486 | #[inline ] |
487 | fn index_mut(self, slice: &mut [T]) -> &mut [T] { |
488 | if self.start > slice.len() { |
489 | slice_start_index_len_fail(self.start, slice.len()); |
490 | } |
491 | // SAFETY: `self` is checked to be valid and in bounds above. |
492 | unsafe { &mut *self.get_unchecked_mut(slice) } |
493 | } |
494 | } |
495 | |
496 | #[stable (feature = "slice_get_slice_impls" , since = "1.15.0" )] |
497 | #[rustc_const_unstable (feature = "const_slice_index" , issue = "none" )] |
498 | unsafe impl<T> SliceIndex<[T]> for ops::RangeFull { |
499 | type Output = [T]; |
500 | |
501 | #[inline ] |
502 | fn get(self, slice: &[T]) -> Option<&[T]> { |
503 | Some(slice) |
504 | } |
505 | |
506 | #[inline ] |
507 | fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { |
508 | Some(slice) |
509 | } |
510 | |
511 | #[inline ] |
512 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { |
513 | slice |
514 | } |
515 | |
516 | #[inline ] |
517 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { |
518 | slice |
519 | } |
520 | |
521 | #[inline ] |
522 | fn index(self, slice: &[T]) -> &[T] { |
523 | slice |
524 | } |
525 | |
526 | #[inline ] |
527 | fn index_mut(self, slice: &mut [T]) -> &mut [T] { |
528 | slice |
529 | } |
530 | } |
531 | |
532 | #[stable (feature = "inclusive_range" , since = "1.26.0" )] |
533 | #[rustc_const_unstable (feature = "const_slice_index" , issue = "none" )] |
534 | unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> { |
535 | type Output = [T]; |
536 | |
537 | #[inline ] |
538 | fn get(self, slice: &[T]) -> Option<&[T]> { |
539 | if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) } |
540 | } |
541 | |
542 | #[inline ] |
543 | fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { |
544 | if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) } |
545 | } |
546 | |
547 | #[inline ] |
548 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { |
549 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. |
550 | unsafe { self.into_slice_range().get_unchecked(slice) } |
551 | } |
552 | |
553 | #[inline ] |
554 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { |
555 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. |
556 | unsafe { self.into_slice_range().get_unchecked_mut(slice) } |
557 | } |
558 | |
559 | #[inline ] |
560 | fn index(self, slice: &[T]) -> &[T] { |
561 | if *self.end() == usize::MAX { |
562 | slice_end_index_overflow_fail(); |
563 | } |
564 | self.into_slice_range().index(slice) |
565 | } |
566 | |
567 | #[inline ] |
568 | fn index_mut(self, slice: &mut [T]) -> &mut [T] { |
569 | if *self.end() == usize::MAX { |
570 | slice_end_index_overflow_fail(); |
571 | } |
572 | self.into_slice_range().index_mut(slice) |
573 | } |
574 | } |
575 | |
576 | #[stable (feature = "inclusive_range" , since = "1.26.0" )] |
577 | #[rustc_const_unstable (feature = "const_slice_index" , issue = "none" )] |
578 | unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> { |
579 | type Output = [T]; |
580 | |
581 | #[inline ] |
582 | fn get(self, slice: &[T]) -> Option<&[T]> { |
583 | (0..=self.end).get(slice) |
584 | } |
585 | |
586 | #[inline ] |
587 | fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { |
588 | (0..=self.end).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 { (0..=self.end).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 { (0..=self.end).get_unchecked_mut(slice) } |
601 | } |
602 | |
603 | #[inline ] |
604 | fn index(self, slice: &[T]) -> &[T] { |
605 | (0..=self.end).index(slice) |
606 | } |
607 | |
608 | #[inline ] |
609 | fn index_mut(self, slice: &mut [T]) -> &mut [T] { |
610 | (0..=self.end).index_mut(slice) |
611 | } |
612 | } |
613 | |
614 | /// Performs bounds-checking of a range. |
615 | /// |
616 | /// This method is similar to [`Index::index`] for slices, but it returns a |
617 | /// [`Range`] equivalent to `range`. You can use this method to turn any range |
618 | /// into `start` and `end` values. |
619 | /// |
620 | /// `bounds` is the range of the slice to use for bounds-checking. It should |
621 | /// be a [`RangeTo`] range that ends at the length of the slice. |
622 | /// |
623 | /// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and |
624 | /// [`slice::get_unchecked_mut`] for slices with the given range. |
625 | /// |
626 | /// [`Range`]: ops::Range |
627 | /// [`RangeTo`]: ops::RangeTo |
628 | /// [`slice::get_unchecked`]: slice::get_unchecked |
629 | /// [`slice::get_unchecked_mut`]: slice::get_unchecked_mut |
630 | /// |
631 | /// # Panics |
632 | /// |
633 | /// Panics if `range` would be out of bounds. |
634 | /// |
635 | /// # Examples |
636 | /// |
637 | /// ``` |
638 | /// #![feature(slice_range)] |
639 | /// |
640 | /// use std::slice; |
641 | /// |
642 | /// let v = [10, 40, 30]; |
643 | /// assert_eq!(1..2, slice::range(1..2, ..v.len())); |
644 | /// assert_eq!(0..2, slice::range(..2, ..v.len())); |
645 | /// assert_eq!(1..3, slice::range(1.., ..v.len())); |
646 | /// ``` |
647 | /// |
648 | /// Panics when [`Index::index`] would panic: |
649 | /// |
650 | /// ```should_panic |
651 | /// #![feature(slice_range)] |
652 | /// |
653 | /// use std::slice; |
654 | /// |
655 | /// let _ = slice::range(2..1, ..3); |
656 | /// ``` |
657 | /// |
658 | /// ```should_panic |
659 | /// #![feature(slice_range)] |
660 | /// |
661 | /// use std::slice; |
662 | /// |
663 | /// let _ = slice::range(1..4, ..3); |
664 | /// ``` |
665 | /// |
666 | /// ```should_panic |
667 | /// #![feature(slice_range)] |
668 | /// |
669 | /// use std::slice; |
670 | /// |
671 | /// let _ = slice::range(1..=usize::MAX, ..3); |
672 | /// ``` |
673 | /// |
674 | /// [`Index::index`]: ops::Index::index |
675 | #[track_caller ] |
676 | #[unstable (feature = "slice_range" , issue = "76393" )] |
677 | #[must_use ] |
678 | pub fn range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize> |
679 | where |
680 | R: ops::RangeBounds<usize>, |
681 | { |
682 | let len = bounds.end; |
683 | |
684 | let start: ops::Bound<&usize> = range.start_bound(); |
685 | let start = match start { |
686 | ops::Bound::Included(&start) => start, |
687 | ops::Bound::Excluded(start) => { |
688 | start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail()) |
689 | } |
690 | ops::Bound::Unbounded => 0, |
691 | }; |
692 | |
693 | let end: ops::Bound<&usize> = range.end_bound(); |
694 | let end = match end { |
695 | ops::Bound::Included(end) => { |
696 | end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail()) |
697 | } |
698 | ops::Bound::Excluded(&end) => end, |
699 | ops::Bound::Unbounded => len, |
700 | }; |
701 | |
702 | if start > end { |
703 | slice_index_order_fail(start, end); |
704 | } |
705 | if end > len { |
706 | slice_end_index_len_fail(end, len); |
707 | } |
708 | |
709 | ops::Range { start, end } |
710 | } |
711 | |
712 | /// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking |
713 | pub(crate) fn into_range_unchecked( |
714 | len: usize, |
715 | (start: Bound, end: Bound): (ops::Bound<usize>, ops::Bound<usize>), |
716 | ) -> ops::Range<usize> { |
717 | use ops::Bound; |
718 | let start: usize = match start { |
719 | Bound::Included(i: usize) => i, |
720 | Bound::Excluded(i: usize) => i + 1, |
721 | Bound::Unbounded => 0, |
722 | }; |
723 | let end: usize = match end { |
724 | Bound::Included(i: usize) => i + 1, |
725 | Bound::Excluded(i: usize) => i, |
726 | Bound::Unbounded => len, |
727 | }; |
728 | start..end |
729 | } |
730 | |
731 | /// Convert pair of `ops::Bound`s into `ops::Range`. |
732 | /// Returns `None` on overflowing indices. |
733 | pub(crate) fn into_range( |
734 | len: usize, |
735 | (start: Bound, end: Bound): (ops::Bound<usize>, ops::Bound<usize>), |
736 | ) -> Option<ops::Range<usize>> { |
737 | use ops::Bound; |
738 | let start: usize = match start { |
739 | Bound::Included(start: usize) => start, |
740 | Bound::Excluded(start: usize) => start.checked_add(1)?, |
741 | Bound::Unbounded => 0, |
742 | }; |
743 | |
744 | let end: usize = match end { |
745 | Bound::Included(end: usize) => end.checked_add(1)?, |
746 | Bound::Excluded(end: usize) => end, |
747 | Bound::Unbounded => len, |
748 | }; |
749 | |
750 | // Don't bother with checking `start < end` and `end <= len` |
751 | // since these checks are handled by `Range` impls |
752 | |
753 | Some(start..end) |
754 | } |
755 | |
756 | /// Convert pair of `ops::Bound`s into `ops::Range`. |
757 | /// Panics on overflowing indices. |
758 | pub(crate) fn into_slice_range( |
759 | len: usize, |
760 | (start: Bound, end: Bound): (ops::Bound<usize>, ops::Bound<usize>), |
761 | ) -> ops::Range<usize> { |
762 | use ops::Bound; |
763 | let start: usize = match start { |
764 | Bound::Included(start: usize) => start, |
765 | Bound::Excluded(start: usize) => { |
766 | start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail()) |
767 | } |
768 | Bound::Unbounded => 0, |
769 | }; |
770 | |
771 | let end: usize = match end { |
772 | Bound::Included(end: usize) => { |
773 | end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail()) |
774 | } |
775 | Bound::Excluded(end: usize) => end, |
776 | Bound::Unbounded => len, |
777 | }; |
778 | |
779 | // Don't bother with checking `start < end` and `end <= len` |
780 | // since these checks are handled by `Range` impls |
781 | |
782 | start..end |
783 | } |
784 | |
785 | #[stable (feature = "slice_index_with_ops_bound_pair" , since = "1.53.0" )] |
786 | unsafe impl<T> SliceIndex<[T]> for (ops::Bound<usize>, ops::Bound<usize>) { |
787 | type Output = [T]; |
788 | |
789 | #[inline ] |
790 | fn get(self, slice: &[T]) -> Option<&Self::Output> { |
791 | into_range(slice.len(), self)?.get(slice) |
792 | } |
793 | |
794 | #[inline ] |
795 | fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { |
796 | into_range(slice.len(), self)?.get_mut(slice) |
797 | } |
798 | |
799 | #[inline ] |
800 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { |
801 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. |
802 | unsafe { into_range_unchecked(slice.len(), self).get_unchecked(slice) } |
803 | } |
804 | |
805 | #[inline ] |
806 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { |
807 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. |
808 | unsafe { into_range_unchecked(slice.len(), self).get_unchecked_mut(slice) } |
809 | } |
810 | |
811 | #[inline ] |
812 | fn index(self, slice: &[T]) -> &Self::Output { |
813 | into_slice_range(slice.len(), self).index(slice) |
814 | } |
815 | |
816 | #[inline ] |
817 | fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { |
818 | into_slice_range(slice.len(), self).index_mut(slice) |
819 | } |
820 | } |
821 | |