]>
Commit | Line | Data |
---|---|---|
1b1a35ee XL |
1 | //! Indexing implementations for `[T]`. |
2 | ||
29967ef6 | 3 | use crate::ops; |
1b1a35ee XL |
4 | use crate::ptr; |
5 | ||
6 | #[stable(feature = "rust1", since = "1.0.0")] | |
7 | impl<T, I> ops::Index<I> for [T] | |
8 | where | |
9 | I: SliceIndex<[T]>, | |
10 | { | |
11 | type Output = I::Output; | |
12 | ||
13 | #[inline] | |
14 | fn index(&self, index: I) -> &I::Output { | |
15 | index.index(self) | |
16 | } | |
17 | } | |
18 | ||
19 | #[stable(feature = "rust1", since = "1.0.0")] | |
20 | impl<T, I> ops::IndexMut<I> for [T] | |
21 | where | |
22 | I: SliceIndex<[T]>, | |
23 | { | |
24 | #[inline] | |
25 | fn index_mut(&mut self, index: I) -> &mut I::Output { | |
26 | index.index_mut(self) | |
27 | } | |
28 | } | |
29 | ||
30 | #[inline(never)] | |
31 | #[cold] | |
32 | #[track_caller] | |
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); | |
35 | } | |
36 | ||
37 | #[inline(never)] | |
38 | #[cold] | |
39 | #[track_caller] | |
6a06907d | 40 | fn slice_end_index_len_fail(index: usize, len: usize) -> ! { |
1b1a35ee XL |
41 | panic!("range end index {} out of range for slice of length {}", index, len); |
42 | } | |
43 | ||
44 | #[inline(never)] | |
45 | #[cold] | |
46 | #[track_caller] | |
6a06907d | 47 | fn slice_index_order_fail(index: usize, end: usize) -> ! { |
1b1a35ee XL |
48 | panic!("slice index starts at {} but ends at {}", index, end); |
49 | } | |
50 | ||
51 | #[inline(never)] | |
52 | #[cold] | |
53 | #[track_caller] | |
6a06907d | 54 | fn slice_start_index_overflow_fail() -> ! { |
1b1a35ee XL |
55 | panic!("attempted to index slice from after maximum usize"); |
56 | } | |
57 | ||
58 | #[inline(never)] | |
59 | #[cold] | |
60 | #[track_caller] | |
6a06907d | 61 | fn slice_end_index_overflow_fail() -> ! { |
1b1a35ee XL |
62 | panic!("attempted to index slice up to maximum usize"); |
63 | } | |
64 | ||
1b1a35ee XL |
65 | mod private_slice_index { |
66 | use super::ops; | |
67 | #[stable(feature = "slice_get_slice", since = "1.28.0")] | |
68 | pub trait Sealed {} | |
69 | ||
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 | } | |
85 | ||
86 | /// A helper trait used for indexing operations. | |
87 | /// | |
88 | /// Implementations of this trait have to promise that if the argument | |
89 | /// to `get_(mut_)unchecked` is a safe reference, then so is the result. | |
90 | #[stable(feature = "slice_get_slice", since = "1.28.0")] | |
91 | #[rustc_on_unimplemented( | |
92 | on(T = "str", label = "string indices are ranges of `usize`",), | |
93 | on( | |
94 | all(any(T = "str", T = "&str", T = "std::string::String"), _Self = "{integer}"), | |
95 | note = "you can use `.chars().nth()` or `.bytes().nth()`\n\ | |
96 | for more information, see chapter 8 in The Book: \ | |
97 | <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>" | |
98 | ), | |
99 | message = "the type `{T}` cannot be indexed by `{Self}`", | |
100 | label = "slice indices are of type `usize` or ranges of `usize`" | |
101 | )] | |
102 | pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed { | |
103 | /// The output type returned by methods. | |
104 | #[stable(feature = "slice_get_slice", since = "1.28.0")] | |
105 | type Output: ?Sized; | |
106 | ||
107 | /// Returns a shared reference to the output at this location, if in | |
108 | /// bounds. | |
109 | #[unstable(feature = "slice_index_methods", issue = "none")] | |
110 | fn get(self, slice: &T) -> Option<&Self::Output>; | |
111 | ||
112 | /// Returns a mutable reference to the output at this location, if in | |
113 | /// bounds. | |
114 | #[unstable(feature = "slice_index_methods", issue = "none")] | |
115 | fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>; | |
116 | ||
117 | /// Returns a shared reference to the output at this location, without | |
118 | /// performing any bounds checking. | |
119 | /// Calling this method with an out-of-bounds index or a dangling `slice` pointer | |
120 | /// is *[undefined behavior]* even if the resulting reference is not used. | |
121 | /// | |
122 | /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html | |
123 | #[unstable(feature = "slice_index_methods", issue = "none")] | |
124 | unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output; | |
125 | ||
126 | /// Returns a mutable reference to the output at this location, without | |
127 | /// performing any bounds checking. | |
128 | /// Calling this method with an out-of-bounds index or a dangling `slice` pointer | |
129 | /// is *[undefined behavior]* even if the resulting reference is not used. | |
130 | /// | |
131 | /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html | |
132 | #[unstable(feature = "slice_index_methods", issue = "none")] | |
133 | unsafe fn get_unchecked_mut(self, slice: *mut T) -> *mut Self::Output; | |
134 | ||
135 | /// Returns a shared reference to the output at this location, panicking | |
136 | /// if out of bounds. | |
137 | #[unstable(feature = "slice_index_methods", issue = "none")] | |
138 | #[track_caller] | |
139 | fn index(self, slice: &T) -> &Self::Output; | |
140 | ||
141 | /// Returns a mutable reference to the output at this location, panicking | |
142 | /// if out of bounds. | |
143 | #[unstable(feature = "slice_index_methods", issue = "none")] | |
144 | #[track_caller] | |
145 | fn index_mut(self, slice: &mut T) -> &mut Self::Output; | |
146 | } | |
147 | ||
148 | #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] | |
149 | unsafe impl<T> SliceIndex<[T]> for usize { | |
150 | type Output = T; | |
151 | ||
152 | #[inline] | |
153 | fn get(self, slice: &[T]) -> Option<&T> { | |
154 | // SAFETY: `self` is checked to be in bounds. | |
155 | if self < slice.len() { unsafe { Some(&*self.get_unchecked(slice)) } } else { None } | |
156 | } | |
157 | ||
158 | #[inline] | |
159 | fn get_mut(self, slice: &mut [T]) -> Option<&mut T> { | |
160 | // SAFETY: `self` is checked to be in bounds. | |
161 | if self < slice.len() { unsafe { Some(&mut *self.get_unchecked_mut(slice)) } } else { None } | |
162 | } | |
163 | ||
164 | #[inline] | |
165 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const T { | |
166 | // SAFETY: the caller guarantees that `slice` is not dangling, so it | |
167 | // cannot be longer than `isize::MAX`. They also guarantee that | |
168 | // `self` is in bounds of `slice` so `self` cannot overflow an `isize`, | |
169 | // so the call to `add` is safe. | |
170 | unsafe { slice.as_ptr().add(self) } | |
171 | } | |
172 | ||
173 | #[inline] | |
174 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T { | |
175 | // SAFETY: see comments for `get_unchecked` above. | |
176 | unsafe { slice.as_mut_ptr().add(self) } | |
177 | } | |
178 | ||
179 | #[inline] | |
180 | fn index(self, slice: &[T]) -> &T { | |
181 | // N.B., use intrinsic indexing | |
182 | &(*slice)[self] | |
183 | } | |
184 | ||
185 | #[inline] | |
186 | fn index_mut(self, slice: &mut [T]) -> &mut T { | |
187 | // N.B., use intrinsic indexing | |
188 | &mut (*slice)[self] | |
189 | } | |
190 | } | |
191 | ||
192 | #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] | |
193 | unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> { | |
194 | type Output = [T]; | |
195 | ||
196 | #[inline] | |
197 | fn get(self, slice: &[T]) -> Option<&[T]> { | |
198 | if self.start > self.end || self.end > slice.len() { | |
199 | None | |
200 | } else { | |
201 | // SAFETY: `self` is checked to be valid and in bounds above. | |
202 | unsafe { Some(&*self.get_unchecked(slice)) } | |
203 | } | |
204 | } | |
205 | ||
206 | #[inline] | |
207 | fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { | |
208 | if self.start > self.end || self.end > slice.len() { | |
209 | None | |
210 | } else { | |
211 | // SAFETY: `self` is checked to be valid and in bounds above. | |
212 | unsafe { Some(&mut *self.get_unchecked_mut(slice)) } | |
213 | } | |
214 | } | |
215 | ||
216 | #[inline] | |
217 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { | |
218 | // SAFETY: the caller guarantees that `slice` is not dangling, so it | |
219 | // cannot be longer than `isize::MAX`. They also guarantee that | |
220 | // `self` is in bounds of `slice` so `self` cannot overflow an `isize`, | |
221 | // so the call to `add` is safe. | |
222 | unsafe { ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start) } | |
223 | } | |
224 | ||
225 | #[inline] | |
226 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { | |
227 | // SAFETY: see comments for `get_unchecked` above. | |
228 | unsafe { | |
229 | ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start) | |
230 | } | |
231 | } | |
232 | ||
233 | #[inline] | |
234 | fn index(self, slice: &[T]) -> &[T] { | |
235 | if self.start > self.end { | |
236 | slice_index_order_fail(self.start, self.end); | |
237 | } else if self.end > slice.len() { | |
238 | slice_end_index_len_fail(self.end, slice.len()); | |
239 | } | |
240 | // SAFETY: `self` is checked to be valid and in bounds above. | |
241 | unsafe { &*self.get_unchecked(slice) } | |
242 | } | |
243 | ||
244 | #[inline] | |
245 | fn index_mut(self, slice: &mut [T]) -> &mut [T] { | |
246 | if self.start > self.end { | |
247 | slice_index_order_fail(self.start, self.end); | |
248 | } else if self.end > slice.len() { | |
249 | slice_end_index_len_fail(self.end, slice.len()); | |
250 | } | |
251 | // SAFETY: `self` is checked to be valid and in bounds above. | |
252 | unsafe { &mut *self.get_unchecked_mut(slice) } | |
253 | } | |
254 | } | |
255 | ||
256 | #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] | |
257 | unsafe impl<T> SliceIndex<[T]> for ops::RangeTo<usize> { | |
258 | type Output = [T]; | |
259 | ||
260 | #[inline] | |
261 | fn get(self, slice: &[T]) -> Option<&[T]> { | |
262 | (0..self.end).get(slice) | |
263 | } | |
264 | ||
265 | #[inline] | |
266 | fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { | |
267 | (0..self.end).get_mut(slice) | |
268 | } | |
269 | ||
270 | #[inline] | |
271 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { | |
272 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. | |
273 | unsafe { (0..self.end).get_unchecked(slice) } | |
274 | } | |
275 | ||
276 | #[inline] | |
277 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { | |
278 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. | |
279 | unsafe { (0..self.end).get_unchecked_mut(slice) } | |
280 | } | |
281 | ||
282 | #[inline] | |
283 | fn index(self, slice: &[T]) -> &[T] { | |
284 | (0..self.end).index(slice) | |
285 | } | |
286 | ||
287 | #[inline] | |
288 | fn index_mut(self, slice: &mut [T]) -> &mut [T] { | |
289 | (0..self.end).index_mut(slice) | |
290 | } | |
291 | } | |
292 | ||
293 | #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] | |
294 | unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> { | |
295 | type Output = [T]; | |
296 | ||
297 | #[inline] | |
298 | fn get(self, slice: &[T]) -> Option<&[T]> { | |
299 | (self.start..slice.len()).get(slice) | |
300 | } | |
301 | ||
302 | #[inline] | |
303 | fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { | |
304 | (self.start..slice.len()).get_mut(slice) | |
305 | } | |
306 | ||
307 | #[inline] | |
308 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { | |
309 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. | |
310 | unsafe { (self.start..slice.len()).get_unchecked(slice) } | |
311 | } | |
312 | ||
313 | #[inline] | |
314 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { | |
315 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. | |
316 | unsafe { (self.start..slice.len()).get_unchecked_mut(slice) } | |
317 | } | |
318 | ||
319 | #[inline] | |
320 | fn index(self, slice: &[T]) -> &[T] { | |
321 | if self.start > slice.len() { | |
322 | slice_start_index_len_fail(self.start, slice.len()); | |
323 | } | |
324 | // SAFETY: `self` is checked to be valid and in bounds above. | |
325 | unsafe { &*self.get_unchecked(slice) } | |
326 | } | |
327 | ||
328 | #[inline] | |
329 | fn index_mut(self, slice: &mut [T]) -> &mut [T] { | |
330 | if self.start > slice.len() { | |
331 | slice_start_index_len_fail(self.start, slice.len()); | |
332 | } | |
333 | // SAFETY: `self` is checked to be valid and in bounds above. | |
334 | unsafe { &mut *self.get_unchecked_mut(slice) } | |
335 | } | |
336 | } | |
337 | ||
338 | #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] | |
339 | unsafe impl<T> SliceIndex<[T]> for ops::RangeFull { | |
340 | type Output = [T]; | |
341 | ||
342 | #[inline] | |
343 | fn get(self, slice: &[T]) -> Option<&[T]> { | |
344 | Some(slice) | |
345 | } | |
346 | ||
347 | #[inline] | |
348 | fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { | |
349 | Some(slice) | |
350 | } | |
351 | ||
352 | #[inline] | |
353 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { | |
354 | slice | |
355 | } | |
356 | ||
357 | #[inline] | |
358 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { | |
359 | slice | |
360 | } | |
361 | ||
362 | #[inline] | |
363 | fn index(self, slice: &[T]) -> &[T] { | |
364 | slice | |
365 | } | |
366 | ||
367 | #[inline] | |
368 | fn index_mut(self, slice: &mut [T]) -> &mut [T] { | |
369 | slice | |
370 | } | |
371 | } | |
372 | ||
373 | #[stable(feature = "inclusive_range", since = "1.26.0")] | |
374 | unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> { | |
375 | type Output = [T]; | |
376 | ||
377 | #[inline] | |
378 | fn get(self, slice: &[T]) -> Option<&[T]> { | |
29967ef6 | 379 | if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) } |
1b1a35ee XL |
380 | } |
381 | ||
382 | #[inline] | |
383 | fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { | |
29967ef6 | 384 | if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) } |
1b1a35ee XL |
385 | } |
386 | ||
387 | #[inline] | |
388 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { | |
389 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. | |
29967ef6 | 390 | unsafe { self.into_slice_range().get_unchecked(slice) } |
1b1a35ee XL |
391 | } |
392 | ||
393 | #[inline] | |
394 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { | |
395 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. | |
29967ef6 | 396 | unsafe { self.into_slice_range().get_unchecked_mut(slice) } |
1b1a35ee XL |
397 | } |
398 | ||
399 | #[inline] | |
400 | fn index(self, slice: &[T]) -> &[T] { | |
401 | if *self.end() == usize::MAX { | |
402 | slice_end_index_overflow_fail(); | |
403 | } | |
29967ef6 | 404 | self.into_slice_range().index(slice) |
1b1a35ee XL |
405 | } |
406 | ||
407 | #[inline] | |
408 | fn index_mut(self, slice: &mut [T]) -> &mut [T] { | |
409 | if *self.end() == usize::MAX { | |
410 | slice_end_index_overflow_fail(); | |
411 | } | |
29967ef6 | 412 | self.into_slice_range().index_mut(slice) |
1b1a35ee XL |
413 | } |
414 | } | |
415 | ||
416 | #[stable(feature = "inclusive_range", since = "1.26.0")] | |
417 | unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> { | |
418 | type Output = [T]; | |
419 | ||
420 | #[inline] | |
421 | fn get(self, slice: &[T]) -> Option<&[T]> { | |
422 | (0..=self.end).get(slice) | |
423 | } | |
424 | ||
425 | #[inline] | |
426 | fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> { | |
427 | (0..=self.end).get_mut(slice) | |
428 | } | |
429 | ||
430 | #[inline] | |
431 | unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] { | |
432 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. | |
433 | unsafe { (0..=self.end).get_unchecked(slice) } | |
434 | } | |
435 | ||
436 | #[inline] | |
437 | unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] { | |
438 | // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. | |
439 | unsafe { (0..=self.end).get_unchecked_mut(slice) } | |
440 | } | |
441 | ||
442 | #[inline] | |
443 | fn index(self, slice: &[T]) -> &[T] { | |
444 | (0..=self.end).index(slice) | |
445 | } | |
446 | ||
447 | #[inline] | |
448 | fn index_mut(self, slice: &mut [T]) -> &mut [T] { | |
449 | (0..=self.end).index_mut(slice) | |
450 | } | |
451 | } | |
6a06907d XL |
452 | |
453 | /// Performs bounds-checking of a range. | |
454 | /// | |
455 | /// This method is similar to [`Index::index`] for slices, but it returns a | |
456 | /// [`Range`] equivalent to `range`. You can use this method to turn any range | |
457 | /// into `start` and `end` values. | |
458 | /// | |
459 | /// `bounds` is the range of the slice to use for bounds-checking. It should | |
460 | /// be a [`RangeTo`] range that ends at the length of the slice. | |
461 | /// | |
462 | /// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and | |
463 | /// [`slice::get_unchecked_mut`] for slices with the given range. | |
464 | /// | |
465 | /// [`Range`]: ops::Range | |
466 | /// [`RangeTo`]: ops::RangeTo | |
467 | /// [`slice::get_unchecked`]: slice::get_unchecked | |
468 | /// [`slice::get_unchecked_mut`]: slice::get_unchecked_mut | |
469 | /// | |
470 | /// # Panics | |
471 | /// | |
472 | /// Panics if `range` would be out of bounds. | |
473 | /// | |
474 | /// # Examples | |
475 | /// | |
476 | /// ``` | |
477 | /// #![feature(slice_range)] | |
478 | /// | |
479 | /// use std::slice; | |
480 | /// | |
481 | /// let v = [10, 40, 30]; | |
482 | /// assert_eq!(1..2, slice::range(1..2, ..v.len())); | |
483 | /// assert_eq!(0..2, slice::range(..2, ..v.len())); | |
484 | /// assert_eq!(1..3, slice::range(1.., ..v.len())); | |
485 | /// ``` | |
486 | /// | |
487 | /// Panics when [`Index::index`] would panic: | |
488 | /// | |
489 | /// ```should_panic | |
490 | /// #![feature(slice_range)] | |
491 | /// | |
492 | /// use std::slice; | |
493 | /// | |
494 | /// slice::range(2..1, ..3); | |
495 | /// ``` | |
496 | /// | |
497 | /// ```should_panic | |
498 | /// #![feature(slice_range)] | |
499 | /// | |
500 | /// use std::slice; | |
501 | /// | |
502 | /// slice::range(1..4, ..3); | |
503 | /// ``` | |
504 | /// | |
505 | /// ```should_panic | |
506 | /// #![feature(slice_range)] | |
507 | /// | |
508 | /// use std::slice; | |
509 | /// | |
510 | /// slice::range(1..=usize::MAX, ..3); | |
511 | /// ``` | |
512 | /// | |
513 | /// [`Index::index`]: ops::Index::index | |
514 | #[track_caller] | |
515 | #[unstable(feature = "slice_range", issue = "76393")] | |
516 | pub fn range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize> | |
517 | where | |
518 | R: ops::RangeBounds<usize>, | |
519 | { | |
520 | let len = bounds.end; | |
521 | ||
522 | let start: ops::Bound<&usize> = range.start_bound(); | |
523 | let start = match start { | |
524 | ops::Bound::Included(&start) => start, | |
525 | ops::Bound::Excluded(start) => { | |
526 | start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail()) | |
527 | } | |
528 | ops::Bound::Unbounded => 0, | |
529 | }; | |
530 | ||
531 | let end: ops::Bound<&usize> = range.end_bound(); | |
532 | let end = match end { | |
533 | ops::Bound::Included(end) => { | |
534 | end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail()) | |
535 | } | |
536 | ops::Bound::Excluded(&end) => end, | |
537 | ops::Bound::Unbounded => len, | |
538 | }; | |
539 | ||
540 | if start > end { | |
541 | slice_index_order_fail(start, end); | |
542 | } | |
543 | if end > len { | |
544 | slice_end_index_len_fail(end, len); | |
545 | } | |
546 | ||
547 | ops::Range { start, end } | |
548 | } |