|
1 | 1 | //! Trait implementations for `str`. |
2 | 2 |
|
3 | 3 | use crate::cmp::Ordering; |
| 4 | +use crate::intrinsics::assert_unsafe_precondition; |
4 | 5 | use crate::ops; |
5 | 6 | use crate::ptr; |
6 | 7 | use crate::slice::SliceIndex; |
@@ -194,15 +195,37 @@ unsafe impl const SliceIndex<str> for ops::Range<usize> { |
194 | 195 | let slice = slice as *const [u8]; |
195 | 196 | // SAFETY: the caller guarantees that `self` is in bounds of `slice` |
196 | 197 | // which satisfies all the conditions for `add`. |
197 | | - let ptr = unsafe { slice.as_ptr().add(self.start) }; |
| 198 | + let ptr = unsafe { |
| 199 | + let this = ops::Range { ..self }; |
| 200 | + assert_unsafe_precondition!( |
| 201 | + "str::get_unchecked requires that the range is within the string slice", |
| 202 | + (this: ops::Range<usize>, slice: *const [u8]) => |
| 203 | + // We'd like to check that the bounds are on char boundaries, |
| 204 | + // but there's not really a way to do so without reading |
| 205 | + // behind the pointer, which has aliasing implications. |
| 206 | + // It's also not possible to move this check up to |
| 207 | + // `str::get_unchecked` without adding a special function |
| 208 | + // to `SliceIndex` just for this. |
| 209 | + this.end >= this.start && this.end <= slice.len() |
| 210 | + ); |
| 211 | + slice.as_ptr().add(self.start) |
| 212 | + }; |
198 | 213 | let len = self.end - self.start; |
199 | 214 | ptr::slice_from_raw_parts(ptr, len) as *const str |
200 | 215 | } |
201 | 216 | #[inline] |
202 | 217 | unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { |
203 | 218 | let slice = slice as *mut [u8]; |
204 | 219 | // SAFETY: see comments for `get_unchecked`. |
205 | | - let ptr = unsafe { slice.as_mut_ptr().add(self.start) }; |
| 220 | + let ptr = unsafe { |
| 221 | + let this = ops::Range { ..self }; |
| 222 | + assert_unsafe_precondition!( |
| 223 | + "str::get_unchecked_mut requires that the range is within the string slice", |
| 224 | + (this: ops::Range<usize>, slice: *mut [u8]) => |
| 225 | + this.end >= this.start && this.end <= slice.len() |
| 226 | + ); |
| 227 | + slice.as_mut_ptr().add(self.start) |
| 228 | + }; |
206 | 229 | let len = self.end - self.start; |
207 | 230 | ptr::slice_from_raw_parts_mut(ptr, len) as *mut str |
208 | 231 | } |
@@ -272,15 +295,13 @@ unsafe impl const SliceIndex<str> for ops::RangeTo<usize> { |
272 | 295 | } |
273 | 296 | #[inline] |
274 | 297 | unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { |
275 | | - let slice = slice as *const [u8]; |
276 | | - let ptr = slice.as_ptr(); |
277 | | - ptr::slice_from_raw_parts(ptr, self.end) as *const str |
| 298 | + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. |
| 299 | + unsafe { (0..self.end).get_unchecked(slice) } |
278 | 300 | } |
279 | 301 | #[inline] |
280 | 302 | unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { |
281 | | - let slice = slice as *mut [u8]; |
282 | | - let ptr = slice.as_mut_ptr(); |
283 | | - ptr::slice_from_raw_parts_mut(ptr, self.end) as *mut str |
| 303 | + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. |
| 304 | + unsafe { (0..self.end).get_unchecked_mut(slice) } |
284 | 305 | } |
285 | 306 | #[inline] |
286 | 307 | fn index(self, slice: &str) -> &Self::Output { |
@@ -343,20 +364,15 @@ unsafe impl const SliceIndex<str> for ops::RangeFrom<usize> { |
343 | 364 | } |
344 | 365 | #[inline] |
345 | 366 | unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { |
346 | | - let slice = slice as *const [u8]; |
347 | | - // SAFETY: the caller guarantees that `self` is in bounds of `slice` |
348 | | - // which satisfies all the conditions for `add`. |
349 | | - let ptr = unsafe { slice.as_ptr().add(self.start) }; |
350 | | - let len = slice.len() - self.start; |
351 | | - ptr::slice_from_raw_parts(ptr, len) as *const str |
| 367 | + let len = (slice as *const [u8]).len(); |
| 368 | + // SAFETY: the caller has to uphold the safety contract for `get_unchecked`. |
| 369 | + unsafe { (self.start..len).get_unchecked(slice) } |
352 | 370 | } |
353 | 371 | #[inline] |
354 | 372 | unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { |
355 | | - let slice = slice as *mut [u8]; |
356 | | - // SAFETY: identical to `get_unchecked`. |
357 | | - let ptr = unsafe { slice.as_mut_ptr().add(self.start) }; |
358 | | - let len = slice.len() - self.start; |
359 | | - ptr::slice_from_raw_parts_mut(ptr, len) as *mut str |
| 373 | + let len = (slice as *mut [u8]).len(); |
| 374 | + // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`. |
| 375 | + unsafe { (self.start..len).get_unchecked_mut(slice) } |
360 | 376 | } |
361 | 377 | #[inline] |
362 | 378 | fn index(self, slice: &str) -> &Self::Output { |
@@ -452,35 +468,29 @@ unsafe impl const SliceIndex<str> for ops::RangeToInclusive<usize> { |
452 | 468 | type Output = str; |
453 | 469 | #[inline] |
454 | 470 | fn get(self, slice: &str) -> Option<&Self::Output> { |
455 | | - if self.end == usize::MAX { None } else { (..self.end + 1).get(slice) } |
| 471 | + (0..=self.end).get(slice) |
456 | 472 | } |
457 | 473 | #[inline] |
458 | 474 | fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { |
459 | | - if self.end == usize::MAX { None } else { (..self.end + 1).get_mut(slice) } |
| 475 | + (0..=self.end).get_mut(slice) |
460 | 476 | } |
461 | 477 | #[inline] |
462 | 478 | unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output { |
463 | 479 | // SAFETY: the caller must uphold the safety contract for `get_unchecked`. |
464 | | - unsafe { (..self.end + 1).get_unchecked(slice) } |
| 480 | + unsafe { (0..=self.end).get_unchecked(slice) } |
465 | 481 | } |
466 | 482 | #[inline] |
467 | 483 | unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output { |
468 | 484 | // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`. |
469 | | - unsafe { (..self.end + 1).get_unchecked_mut(slice) } |
| 485 | + unsafe { (0..=self.end).get_unchecked_mut(slice) } |
470 | 486 | } |
471 | 487 | #[inline] |
472 | 488 | fn index(self, slice: &str) -> &Self::Output { |
473 | | - if self.end == usize::MAX { |
474 | | - str_index_overflow_fail(); |
475 | | - } |
476 | | - (..self.end + 1).index(slice) |
| 489 | + (0..=self.end).index(slice) |
477 | 490 | } |
478 | 491 | #[inline] |
479 | 492 | fn index_mut(self, slice: &mut str) -> &mut Self::Output { |
480 | | - if self.end == usize::MAX { |
481 | | - str_index_overflow_fail(); |
482 | | - } |
483 | | - (..self.end + 1).index_mut(slice) |
| 493 | + (0..=self.end).index_mut(slice) |
484 | 494 | } |
485 | 495 | } |
486 | 496 |
|
|
0 commit comments