Skip to content

Commit a9329d3

Browse files
committedMar 31, 2017
Auto merge of #40737 - nagisa:safe-slicing-strs, r=BurntSushi
Checked slicing for strings cc #39932
2 parents 474f7a9 + 53a3692 commit a9329d3

File tree

8 files changed

+448
-63
lines changed

8 files changed

+448
-63
lines changed
 

‎src/libcollections/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#![feature(unicode)]
6161
#![feature(unique)]
6262
#![feature(untagged_unions)]
63+
#![cfg_attr(not(test), feature(str_checked_slicing))]
6364
#![cfg_attr(test, feature(rand, test))]
6465

6566
#![no_std]

‎src/libcollections/slice.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ impl<T> [T] {
362362
#[stable(feature = "rust1", since = "1.0.0")]
363363
#[inline]
364364
pub fn get<I>(&self, index: I) -> Option<&I::Output>
365-
where I: SliceIndex<T>
365+
where I: SliceIndex<Self>
366366
{
367367
core_slice::SliceExt::get(self, index)
368368
}
@@ -385,7 +385,7 @@ impl<T> [T] {
385385
#[stable(feature = "rust1", since = "1.0.0")]
386386
#[inline]
387387
pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
388-
where I: SliceIndex<T>
388+
where I: SliceIndex<Self>
389389
{
390390
core_slice::SliceExt::get_mut(self, index)
391391
}
@@ -405,7 +405,7 @@ impl<T> [T] {
405405
#[stable(feature = "rust1", since = "1.0.0")]
406406
#[inline]
407407
pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
408-
where I: SliceIndex<T>
408+
where I: SliceIndex<Self>
409409
{
410410
core_slice::SliceExt::get_unchecked(self, index)
411411
}
@@ -427,7 +427,7 @@ impl<T> [T] {
427427
#[stable(feature = "rust1", since = "1.0.0")]
428428
#[inline]
429429
pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
430-
where I: SliceIndex<T>
430+
where I: SliceIndex<Self>
431431
{
432432
core_slice::SliceExt::get_unchecked_mut(self, index)
433433
}

‎src/libcollections/str.rs

+109-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ use borrow::{Borrow, ToOwned};
5151
use string::String;
5252
use std_unicode;
5353
use vec::Vec;
54-
use slice::SliceConcatExt;
54+
use slice::{SliceConcatExt, SliceIndex};
5555
use boxed::Box;
5656

5757
#[stable(feature = "rust1", since = "1.0.0")]
@@ -310,6 +310,114 @@ impl str {
310310
core_str::StrExt::as_ptr(self)
311311
}
312312

313+
/// Returns a subslice of `str`.
314+
///
315+
/// This is the non-panicking alternative to indexing the `str`. Returns `None` whenever
316+
/// equivalent indexing operation would panic.
317+
///
318+
/// # Examples
319+
///
320+
/// ```
321+
/// # #![feature(str_checked_slicing)]
322+
/// let v = "🗻∈🌏";
323+
/// assert_eq!(Some("🗻"), v.get(0..4));
324+
/// assert!(v.get(1..).is_none());
325+
/// assert!(v.get(..8).is_none());
326+
/// assert!(v.get(..42).is_none());
327+
/// ```
328+
#[unstable(feature = "str_checked_slicing", issue = "39932")]
329+
#[inline]
330+
pub fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
331+
core_str::StrExt::get(self, i)
332+
}
333+
334+
/// Returns a mutable subslice of `str`.
335+
///
336+
/// This is the non-panicking alternative to indexing the `str`. Returns `None` whenever
337+
/// equivalent indexing operation would panic.
338+
///
339+
/// # Examples
340+
///
341+
/// ```
342+
/// # #![feature(str_checked_slicing)]
343+
/// let mut v = String::from("🗻∈🌏");
344+
/// assert_eq!(Some("🗻"), v.get_mut(0..4).map(|v| &*v));
345+
/// assert!(v.get_mut(1..).is_none());
346+
/// assert!(v.get_mut(..8).is_none());
347+
/// assert!(v.get_mut(..42).is_none());
348+
/// ```
349+
#[unstable(feature = "str_checked_slicing", issue = "39932")]
350+
#[inline]
351+
pub fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
352+
core_str::StrExt::get_mut(self, i)
353+
}
354+
355+
/// Returns a unchecked subslice of `str`.
356+
///
357+
/// This is the unchecked alternative to indexing the `str`.
358+
///
359+
/// # Safety
360+
///
361+
/// Callers of this function are responsible that these preconditions are
362+
/// satisfied:
363+
///
364+
/// * The starting index must come before the ending index;
365+
/// * Indexes must be within bounds of the original slice;
366+
/// * Indexes must lie on UTF-8 sequence boundaries.
367+
///
368+
/// Failing that, the returned string slice may reference invalid memory or
369+
/// violate the invariants communicated by the `str` type.
370+
///
371+
/// # Examples
372+
///
373+
/// ```
374+
/// # #![feature(str_checked_slicing)]
375+
/// let v = "🗻∈🌏";
376+
/// unsafe {
377+
/// assert_eq!("🗻", v.get_unchecked(0..4));
378+
/// assert_eq!("∈", v.get_unchecked(4..7));
379+
/// assert_eq!("🌏", v.get_unchecked(7..11));
380+
/// }
381+
/// ```
382+
#[unstable(feature = "str_checked_slicing", issue = "39932")]
383+
#[inline]
384+
pub unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output {
385+
core_str::StrExt::get_unchecked(self, i)
386+
}
387+
388+
/// Returns a mutable, unchecked subslice of `str`.
389+
///
390+
/// This is the unchecked alternative to indexing the `str`.
391+
///
392+
/// # Safety
393+
///
394+
/// Callers of this function are responsible that these preconditions are
395+
/// satisfied:
396+
///
397+
/// * The starting index must come before the ending index;
398+
/// * Indexes must be within bounds of the original slice;
399+
/// * Indexes must lie on UTF-8 sequence boundaries.
400+
///
401+
/// Failing that, the returned string slice may reference invalid memory or
402+
/// violate the invariants communicated by the `str` type.
403+
///
404+
/// # Examples
405+
///
406+
/// ```
407+
/// # #![feature(str_checked_slicing)]
408+
/// let mut v = String::from("🗻∈🌏");
409+
/// unsafe {
410+
/// assert_eq!("🗻", v.get_unchecked_mut(0..4));
411+
/// assert_eq!("∈", v.get_unchecked_mut(4..7));
412+
/// assert_eq!("🌏", v.get_unchecked_mut(7..11));
413+
/// }
414+
/// ```
415+
#[unstable(feature = "str_checked_slicing", issue = "39932")]
416+
#[inline]
417+
pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output {
418+
core_str::StrExt::get_unchecked_mut(self, i)
419+
}
420+
313421
/// Creates a string slice from another string slice, bypassing safety
314422
/// checks.
315423
///

‎src/libcore/slice/mod.rs

+24-28
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,7 @@ pub trait SliceExt {
9797

9898
#[stable(feature = "core", since = "1.6.0")]
9999
fn get<I>(&self, index: I) -> Option<&I::Output>
100-
where I: SliceIndex<Self::Item>;
101-
100+
where I: SliceIndex<Self>;
102101
#[stable(feature = "core", since = "1.6.0")]
103102
fn first(&self) -> Option<&Self::Item>;
104103

@@ -113,8 +112,7 @@ pub trait SliceExt {
113112

114113
#[stable(feature = "core", since = "1.6.0")]
115114
unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
116-
where I: SliceIndex<Self::Item>;
117-
115+
where I: SliceIndex<Self>;
118116
#[stable(feature = "core", since = "1.6.0")]
119117
fn as_ptr(&self) -> *const Self::Item;
120118

@@ -141,8 +139,7 @@ pub trait SliceExt {
141139

142140
#[stable(feature = "core", since = "1.6.0")]
143141
fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
144-
where I: SliceIndex<Self::Item>;
145-
142+
where I: SliceIndex<Self>;
146143
#[stable(feature = "core", since = "1.6.0")]
147144
fn iter_mut(&mut self) -> IterMut<Self::Item>;
148145

@@ -184,8 +181,7 @@ pub trait SliceExt {
184181

185182
#[stable(feature = "core", since = "1.6.0")]
186183
unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
187-
where I: SliceIndex<Self::Item>;
188-
184+
where I: SliceIndex<Self>;
189185
#[stable(feature = "core", since = "1.6.0")]
190186
fn as_mut_ptr(&mut self) -> *mut Self::Item;
191187

@@ -337,7 +333,7 @@ impl<T> SliceExt for [T] {
337333

338334
#[inline]
339335
fn get<I>(&self, index: I) -> Option<&I::Output>
340-
where I: SliceIndex<T>
336+
where I: SliceIndex<[T]>
341337
{
342338
index.get(self)
343339
}
@@ -365,7 +361,7 @@ impl<T> SliceExt for [T] {
365361

366362
#[inline]
367363
unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
368-
where I: SliceIndex<T>
364+
where I: SliceIndex<[T]>
369365
{
370366
index.get_unchecked(self)
371367
}
@@ -406,7 +402,7 @@ impl<T> SliceExt for [T] {
406402

407403
#[inline]
408404
fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
409-
where I: SliceIndex<T>
405+
where I: SliceIndex<[T]>
410406
{
411407
index.get_mut(self)
412408
}
@@ -538,7 +534,7 @@ impl<T> SliceExt for [T] {
538534

539535
#[inline]
540536
unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
541-
where I: SliceIndex<T>
537+
where I: SliceIndex<[T]>
542538
{
543539
index.get_unchecked_mut(self)
544540
}
@@ -631,7 +627,7 @@ impl<T> SliceExt for [T] {
631627
#[stable(feature = "rust1", since = "1.0.0")]
632628
#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
633629
impl<T, I> ops::Index<I> for [T]
634-
where I: SliceIndex<T>
630+
where I: SliceIndex<[T]>
635631
{
636632
type Output = I::Output;
637633

@@ -644,7 +640,7 @@ impl<T, I> ops::Index<I> for [T]
644640
#[stable(feature = "rust1", since = "1.0.0")]
645641
#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
646642
impl<T, I> ops::IndexMut<I> for [T]
647-
where I: SliceIndex<T>
643+
where I: SliceIndex<[T]>
648644
{
649645
#[inline]
650646
fn index_mut(&mut self, index: I) -> &mut I::Output {
@@ -667,37 +663,37 @@ fn slice_index_order_fail(index: usize, end: usize) -> ! {
667663
/// A helper trait used for indexing operations.
668664
#[unstable(feature = "slice_get_slice", issue = "35729")]
669665
#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
670-
pub trait SliceIndex<T> {
666+
pub trait SliceIndex<T: ?Sized> {
671667
/// The output type returned by methods.
672668
type Output: ?Sized;
673669

674670
/// Returns a shared reference to the output at this location, if in
675671
/// bounds.
676-
fn get(self, slice: &[T]) -> Option<&Self::Output>;
672+
fn get(self, slice: &T) -> Option<&Self::Output>;
677673

678674
/// Returns a mutable reference to the output at this location, if in
679675
/// bounds.
680-
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output>;
676+
fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>;
681677

682678
/// Returns a shared reference to the output at this location, without
683679
/// performing any bounds checking.
684-
unsafe fn get_unchecked(self, slice: &[T]) -> &Self::Output;
680+
unsafe fn get_unchecked(self, slice: &T) -> &Self::Output;
685681

686682
/// Returns a mutable reference to the output at this location, without
687683
/// performing any bounds checking.
688-
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut Self::Output;
684+
unsafe fn get_unchecked_mut(self, slice: &mut T) -> &mut Self::Output;
689685

690686
/// Returns a shared reference to the output at this location, panicking
691687
/// if out of bounds.
692-
fn index(self, slice: &[T]) -> &Self::Output;
688+
fn index(self, slice: &T) -> &Self::Output;
693689

694690
/// Returns a mutable reference to the output at this location, panicking
695691
/// if out of bounds.
696-
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output;
692+
fn index_mut(self, slice: &mut T) -> &mut Self::Output;
697693
}
698694

699695
#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
700-
impl<T> SliceIndex<T> for usize {
696+
impl<T> SliceIndex<[T]> for usize {
701697
type Output = T;
702698

703699
#[inline]
@@ -746,7 +742,7 @@ impl<T> SliceIndex<T> for usize {
746742
}
747743

748744
#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
749-
impl<T> SliceIndex<T> for ops::Range<usize> {
745+
impl<T> SliceIndex<[T]> for ops::Range<usize> {
750746
type Output = [T];
751747

752748
#[inline]
@@ -807,7 +803,7 @@ impl<T> SliceIndex<T> for ops::Range<usize> {
807803
}
808804

809805
#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
810-
impl<T> SliceIndex<T> for ops::RangeTo<usize> {
806+
impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
811807
type Output = [T];
812808

813809
#[inline]
@@ -842,7 +838,7 @@ impl<T> SliceIndex<T> for ops::RangeTo<usize> {
842838
}
843839

844840
#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
845-
impl<T> SliceIndex<T> for ops::RangeFrom<usize> {
841+
impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
846842
type Output = [T];
847843

848844
#[inline]
@@ -877,7 +873,7 @@ impl<T> SliceIndex<T> for ops::RangeFrom<usize> {
877873
}
878874

879875
#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
880-
impl<T> SliceIndex<T> for ops::RangeFull {
876+
impl<T> SliceIndex<[T]> for ops::RangeFull {
881877
type Output = [T];
882878

883879
#[inline]
@@ -913,7 +909,7 @@ impl<T> SliceIndex<T> for ops::RangeFull {
913909

914910

915911
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
916-
impl<T> SliceIndex<T> for ops::RangeInclusive<usize> {
912+
impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
917913
type Output = [T];
918914

919915
#[inline]
@@ -976,7 +972,7 @@ impl<T> SliceIndex<T> for ops::RangeInclusive<usize> {
976972
}
977973

978974
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
979-
impl<T> SliceIndex<T> for ops::RangeToInclusive<usize> {
975+
impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
980976
type Output = [T];
981977

982978
#[inline]

‎src/libcore/str/mod.rs

+303-23
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use convert::TryFrom;
2222
use fmt;
2323
use iter::{Map, Cloned, FusedIterator};
2424
use mem;
25-
use slice;
25+
use slice::{self, SliceIndex};
2626

2727
pub mod pattern;
2828

@@ -1445,6 +1445,8 @@ Section: Trait implementations
14451445
mod traits {
14461446
use cmp::Ordering;
14471447
use ops;
1448+
use mem;
1449+
use slice::{self, SliceIndex};
14481450
use str::eq_slice;
14491451

14501452
/// Implements ordering of strings.
@@ -1527,14 +1529,7 @@ mod traits {
15271529
type Output = str;
15281530
#[inline]
15291531
fn index(&self, index: ops::Range<usize>) -> &str {
1530-
// is_char_boundary checks that the index is in [0, .len()]
1531-
if index.start <= index.end &&
1532-
self.is_char_boundary(index.start) &&
1533-
self.is_char_boundary(index.end) {
1534-
unsafe { self.slice_unchecked(index.start, index.end) }
1535-
} else {
1536-
super::slice_error_fail(self, index.start, index.end)
1537-
}
1532+
index.index(self)
15381533
}
15391534
}
15401535

@@ -1556,14 +1551,7 @@ mod traits {
15561551
impl ops::IndexMut<ops::Range<usize>> for str {
15571552
#[inline]
15581553
fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
1559-
// is_char_boundary checks that the index is in [0, .len()]
1560-
if index.start <= index.end &&
1561-
self.is_char_boundary(index.start) &&
1562-
self.is_char_boundary(index.end) {
1563-
unsafe { self.slice_mut_unchecked(index.start, index.end) }
1564-
} else {
1565-
super::slice_error_fail(self, index.start, index.end)
1566-
}
1554+
index.index_mut(self)
15671555
}
15681556
}
15691557

@@ -1731,8 +1719,276 @@ mod traits {
17311719
self.index_mut(0...index.end)
17321720
}
17331721
}
1722+
1723+
#[unstable(feature = "str_checked_slicing", issue = "39932")]
1724+
impl SliceIndex<str> for ops::RangeFull {
1725+
type Output = str;
1726+
#[inline]
1727+
fn get(self, slice: &str) -> Option<&Self::Output> {
1728+
Some(slice)
1729+
}
1730+
#[inline]
1731+
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
1732+
Some(slice)
1733+
}
1734+
#[inline]
1735+
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
1736+
slice
1737+
}
1738+
#[inline]
1739+
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
1740+
slice
1741+
}
1742+
#[inline]
1743+
fn index(self, slice: &str) -> &Self::Output {
1744+
slice
1745+
}
1746+
#[inline]
1747+
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
1748+
slice
1749+
}
1750+
}
1751+
1752+
#[unstable(feature = "str_checked_slicing", issue = "39932")]
1753+
impl SliceIndex<str> for ops::Range<usize> {
1754+
type Output = str;
1755+
#[inline]
1756+
fn get(self, slice: &str) -> Option<&Self::Output> {
1757+
if self.start <= self.end &&
1758+
slice.is_char_boundary(self.start) &&
1759+
slice.is_char_boundary(self.end) {
1760+
Some(unsafe { self.get_unchecked(slice) })
1761+
} else {
1762+
None
1763+
}
1764+
}
1765+
#[inline]
1766+
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
1767+
if self.start <= self.end &&
1768+
slice.is_char_boundary(self.start) &&
1769+
slice.is_char_boundary(self.end) {
1770+
Some(unsafe { self.get_unchecked_mut(slice) })
1771+
} else {
1772+
None
1773+
}
1774+
}
1775+
#[inline]
1776+
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
1777+
let ptr = slice.as_ptr().offset(self.start as isize);
1778+
let len = self.end - self.start;
1779+
super::from_utf8_unchecked(slice::from_raw_parts(ptr, len))
1780+
}
1781+
#[inline]
1782+
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
1783+
let ptr = slice.as_ptr().offset(self.start as isize);
1784+
let len = self.end - self.start;
1785+
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
1786+
}
1787+
#[inline]
1788+
fn index(self, slice: &str) -> &Self::Output {
1789+
let (start, end) = (self.start, self.end);
1790+
self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, start, end))
1791+
}
1792+
#[inline]
1793+
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
1794+
// is_char_boundary checks that the index is in [0, .len()]
1795+
// canot reuse `get` as above, because of NLL trouble
1796+
if self.start <= self.end &&
1797+
slice.is_char_boundary(self.start) &&
1798+
slice.is_char_boundary(self.end) {
1799+
unsafe { self.get_unchecked_mut(slice) }
1800+
} else {
1801+
super::slice_error_fail(slice, self.start, self.end)
1802+
}
1803+
}
1804+
}
1805+
1806+
#[unstable(feature = "str_checked_slicing", issue = "39932")]
1807+
impl SliceIndex<str> for ops::RangeTo<usize> {
1808+
type Output = str;
1809+
#[inline]
1810+
fn get(self, slice: &str) -> Option<&Self::Output> {
1811+
if slice.is_char_boundary(self.end) {
1812+
Some(unsafe { self.get_unchecked(slice) })
1813+
} else {
1814+
None
1815+
}
1816+
}
1817+
#[inline]
1818+
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
1819+
if slice.is_char_boundary(self.end) {
1820+
Some(unsafe { self.get_unchecked_mut(slice) })
1821+
} else {
1822+
None
1823+
}
1824+
}
1825+
#[inline]
1826+
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
1827+
let ptr = slice.as_ptr();
1828+
super::from_utf8_unchecked(slice::from_raw_parts(ptr, self.end))
1829+
}
1830+
#[inline]
1831+
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
1832+
let ptr = slice.as_ptr();
1833+
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, self.end))
1834+
}
1835+
#[inline]
1836+
fn index(self, slice: &str) -> &Self::Output {
1837+
let end = self.end;
1838+
self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, 0, end))
1839+
}
1840+
#[inline]
1841+
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
1842+
if slice.is_char_boundary(self.end) {
1843+
unsafe { self.get_unchecked_mut(slice) }
1844+
} else {
1845+
super::slice_error_fail(slice, 0, self.end)
1846+
}
1847+
}
1848+
}
1849+
1850+
#[unstable(feature = "str_checked_slicing", issue = "39932")]
1851+
impl SliceIndex<str> for ops::RangeFrom<usize> {
1852+
type Output = str;
1853+
#[inline]
1854+
fn get(self, slice: &str) -> Option<&Self::Output> {
1855+
if slice.is_char_boundary(self.start) {
1856+
Some(unsafe { self.get_unchecked(slice) })
1857+
} else {
1858+
None
1859+
}
1860+
}
1861+
#[inline]
1862+
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
1863+
if slice.is_char_boundary(self.start) {
1864+
Some(unsafe { self.get_unchecked_mut(slice) })
1865+
} else {
1866+
None
1867+
}
1868+
}
1869+
#[inline]
1870+
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
1871+
let ptr = slice.as_ptr().offset(self.start as isize);
1872+
let len = slice.len() - self.start;
1873+
super::from_utf8_unchecked(slice::from_raw_parts(ptr, len))
1874+
}
1875+
#[inline]
1876+
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
1877+
let ptr = slice.as_ptr().offset(self.start as isize);
1878+
let len = slice.len() - self.start;
1879+
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
1880+
}
1881+
#[inline]
1882+
fn index(self, slice: &str) -> &Self::Output {
1883+
let (start, end) = (self.start, slice.len());
1884+
self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, start, end))
1885+
}
1886+
#[inline]
1887+
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
1888+
if slice.is_char_boundary(self.start) {
1889+
unsafe { self.get_unchecked_mut(slice) }
1890+
} else {
1891+
super::slice_error_fail(slice, self.start, slice.len())
1892+
}
1893+
}
1894+
}
1895+
1896+
#[unstable(feature = "str_checked_slicing", issue = "39932")]
1897+
impl SliceIndex<str> for ops::RangeInclusive<usize> {
1898+
type Output = str;
1899+
#[inline]
1900+
fn get(self, slice: &str) -> Option<&Self::Output> {
1901+
match self {
1902+
ops::RangeInclusive::Empty { .. } => 0..0,
1903+
ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
1904+
}.get(slice)
1905+
}
1906+
#[inline]
1907+
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
1908+
match self {
1909+
ops::RangeInclusive::Empty { .. } => 0..0,
1910+
ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
1911+
}.get_mut(slice)
1912+
}
1913+
#[inline]
1914+
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
1915+
match self {
1916+
ops::RangeInclusive::Empty { .. } => 0..0,
1917+
ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
1918+
}.get_unchecked(slice)
1919+
}
1920+
#[inline]
1921+
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
1922+
match self {
1923+
ops::RangeInclusive::Empty { .. } => 0..0,
1924+
ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
1925+
}.get_unchecked_mut(slice)
1926+
}
1927+
#[inline]
1928+
fn index(self, slice: &str) -> &Self::Output {
1929+
match self {
1930+
ops::RangeInclusive::Empty { .. } => 0..0,
1931+
ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
1932+
}.index(slice)
1933+
}
1934+
#[inline]
1935+
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
1936+
match self {
1937+
ops::RangeInclusive::Empty { .. } => 0..0,
1938+
ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
1939+
}.index_mut(slice)
1940+
}
1941+
}
1942+
1943+
1944+
1945+
#[unstable(feature = "str_checked_slicing", issue = "39932")]
1946+
impl SliceIndex<str> for ops::RangeToInclusive<usize> {
1947+
type Output = str;
1948+
#[inline]
1949+
fn get(self, slice: &str) -> Option<&Self::Output> {
1950+
if slice.is_char_boundary(self.end + 1) {
1951+
Some(unsafe { self.get_unchecked(slice) })
1952+
} else {
1953+
None
1954+
}
1955+
}
1956+
#[inline]
1957+
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
1958+
if slice.is_char_boundary(self.end + 1) {
1959+
Some(unsafe { self.get_unchecked_mut(slice) })
1960+
} else {
1961+
None
1962+
}
1963+
}
1964+
#[inline]
1965+
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
1966+
let ptr = slice.as_ptr();
1967+
super::from_utf8_unchecked(slice::from_raw_parts(ptr, self.end + 1))
1968+
}
1969+
#[inline]
1970+
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
1971+
let ptr = slice.as_ptr();
1972+
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, self.end + 1))
1973+
}
1974+
#[inline]
1975+
fn index(self, slice: &str) -> &Self::Output {
1976+
let end = self.end + 1;
1977+
self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, 0, end))
1978+
}
1979+
#[inline]
1980+
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
1981+
if slice.is_char_boundary(self.end) {
1982+
unsafe { self.get_unchecked_mut(slice) }
1983+
} else {
1984+
super::slice_error_fail(slice, 0, self.end + 1)
1985+
}
1986+
}
1987+
}
1988+
17341989
}
17351990

1991+
17361992
/// Methods for string slices
17371993
#[allow(missing_docs)]
17381994
#[doc(hidden)]
@@ -1782,6 +2038,14 @@ pub trait StrExt {
17822038
#[rustc_deprecated(since = "1.6.0", reason = "use lines() instead now")]
17832039
#[allow(deprecated)]
17842040
fn lines_any(&self) -> LinesAny;
2041+
#[unstable(feature = "str_checked_slicing", issue = "39932")]
2042+
fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output>;
2043+
#[unstable(feature = "str_checked_slicing", issue = "39932")]
2044+
fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output>;
2045+
#[unstable(feature = "str_checked_slicing", issue = "39932")]
2046+
unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output;
2047+
#[unstable(feature = "str_checked_slicing", issue = "39932")]
2048+
unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output;
17852049
#[stable(feature = "core", since = "1.6.0")]
17862050
unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str;
17872051
#[stable(feature = "core", since = "1.6.0")]
@@ -1971,18 +2235,34 @@ impl StrExt for str {
19712235
LinesAny(self.lines())
19722236
}
19732237

2238+
#[inline]
2239+
fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
2240+
i.get(self)
2241+
}
2242+
2243+
#[inline]
2244+
fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
2245+
i.get_mut(self)
2246+
}
2247+
2248+
#[inline]
2249+
unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output {
2250+
i.get_unchecked(self)
2251+
}
2252+
2253+
#[inline]
2254+
unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output {
2255+
i.get_unchecked_mut(self)
2256+
}
2257+
19742258
#[inline]
19752259
unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
1976-
let ptr = self.as_ptr().offset(begin as isize);
1977-
let len = end - begin;
1978-
from_utf8_unchecked(slice::from_raw_parts(ptr, len))
2260+
(begin..end).get_unchecked(self)
19792261
}
19802262

19812263
#[inline]
19822264
unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str {
1983-
let ptr = self.as_ptr().offset(begin as isize);
1984-
let len = end - begin;
1985-
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
2265+
(begin..end).get_unchecked_mut(self)
19862266
}
19872267

19882268
#[inline]

‎src/test/compile-fail/indexing-requires-a-uint.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
fn main() {
1515
fn bar<T>(_: T) {}
16-
[0][0u8]; //~ ERROR: the trait bound `u8: std::slice::SliceIndex<{integer}>` is not satisfied
16+
[0][0u8]; //~ ERROR: the trait bound `u8: std::slice::SliceIndex<[{integer}]>` is not satisfied
1717

1818
[0][0]; // should infer to be a usize
1919

‎src/test/compile-fail/integral-indexing.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ pub fn main() {
1919
v[3i32]; //~ERROR : std::ops::Index<i32>` is not satisfied
2020
s.as_bytes()[3_usize];
2121
s.as_bytes()[3];
22-
s.as_bytes()[3u8]; //~ERROR : std::slice::SliceIndex<u8>` is not satisfied
23-
s.as_bytes()[3i8]; //~ERROR : std::slice::SliceIndex<u8>` is not satisfied
24-
s.as_bytes()[3u32]; //~ERROR : std::slice::SliceIndex<u8>` is not satisfied
25-
s.as_bytes()[3i32]; //~ERROR : std::slice::SliceIndex<u8>` is not satisfied
22+
s.as_bytes()[3u8]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
23+
s.as_bytes()[3i8]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
24+
s.as_bytes()[3u32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
25+
s.as_bytes()[3i32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
2626
}

‎src/test/compile-fail/on-unimplemented/slice-index.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ fn main() {
2020
let x = &[1, 2, 3] as &[i32];
2121
x[1i32]; //~ ERROR E0277
2222
//~| NOTE slice indices are of type `usize` or ranges of `usize`
23-
//~| NOTE trait `std::slice::SliceIndex<i32>` is not implemented for `i32`
23+
//~| NOTE trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32`
2424
//~| NOTE required because of the requirements on the impl of `std::ops::Index<i32>`
2525
x[..1i32]; //~ ERROR E0277
2626
//~| NOTE slice indices are of type `usize` or ranges of `usize`
27-
//~| NOTE trait `std::slice::SliceIndex<i32>` is not implemented for `std::ops::RangeTo<i32>`
27+
//~| NOTE trait `std::slice::SliceIndex<[i32]>` is not implemented for `std::ops::RangeTo<i32>`
2828
//~| NOTE requirements on the impl of `std::ops::Index<std::ops::RangeTo<i32>>`
2929
}

0 commit comments

Comments
 (0)
Please sign in to comment.