Auto merge of #40737 - nagisa:safe-slicing-strs, r=BurntSushi
Checked slicing for strings cc https://github.com/rust-lang/rust/issues/39932
This commit is contained in:
commit
a9329d3aa3
@ -60,6 +60,7 @@
|
||||
#![feature(unicode)]
|
||||
#![feature(unique)]
|
||||
#![feature(untagged_unions)]
|
||||
#![cfg_attr(not(test), feature(str_checked_slicing))]
|
||||
#![cfg_attr(test, feature(rand, test))]
|
||||
|
||||
#![no_std]
|
||||
|
@ -362,7 +362,7 @@ impl<T> [T] {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn get<I>(&self, index: I) -> Option<&I::Output>
|
||||
where I: SliceIndex<T>
|
||||
where I: SliceIndex<Self>
|
||||
{
|
||||
core_slice::SliceExt::get(self, index)
|
||||
}
|
||||
@ -385,7 +385,7 @@ impl<T> [T] {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
|
||||
where I: SliceIndex<T>
|
||||
where I: SliceIndex<Self>
|
||||
{
|
||||
core_slice::SliceExt::get_mut(self, index)
|
||||
}
|
||||
@ -405,7 +405,7 @@ impl<T> [T] {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
|
||||
where I: SliceIndex<T>
|
||||
where I: SliceIndex<Self>
|
||||
{
|
||||
core_slice::SliceExt::get_unchecked(self, index)
|
||||
}
|
||||
@ -427,7 +427,7 @@ impl<T> [T] {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
|
||||
where I: SliceIndex<T>
|
||||
where I: SliceIndex<Self>
|
||||
{
|
||||
core_slice::SliceExt::get_unchecked_mut(self, index)
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ use borrow::{Borrow, ToOwned};
|
||||
use string::String;
|
||||
use std_unicode;
|
||||
use vec::Vec;
|
||||
use slice::SliceConcatExt;
|
||||
use slice::{SliceConcatExt, SliceIndex};
|
||||
use boxed::Box;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -310,6 +310,114 @@ impl str {
|
||||
core_str::StrExt::as_ptr(self)
|
||||
}
|
||||
|
||||
/// Returns a subslice of `str`.
|
||||
///
|
||||
/// This is the non-panicking alternative to indexing the `str`. Returns `None` whenever
|
||||
/// equivalent indexing operation would panic.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(str_checked_slicing)]
|
||||
/// let v = "🗻∈🌏";
|
||||
/// assert_eq!(Some("🗻"), v.get(0..4));
|
||||
/// assert!(v.get(1..).is_none());
|
||||
/// assert!(v.get(..8).is_none());
|
||||
/// assert!(v.get(..42).is_none());
|
||||
/// ```
|
||||
#[unstable(feature = "str_checked_slicing", issue = "39932")]
|
||||
#[inline]
|
||||
pub fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
|
||||
core_str::StrExt::get(self, i)
|
||||
}
|
||||
|
||||
/// Returns a mutable subslice of `str`.
|
||||
///
|
||||
/// This is the non-panicking alternative to indexing the `str`. Returns `None` whenever
|
||||
/// equivalent indexing operation would panic.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(str_checked_slicing)]
|
||||
/// let mut v = String::from("🗻∈🌏");
|
||||
/// assert_eq!(Some("🗻"), v.get_mut(0..4).map(|v| &*v));
|
||||
/// assert!(v.get_mut(1..).is_none());
|
||||
/// assert!(v.get_mut(..8).is_none());
|
||||
/// assert!(v.get_mut(..42).is_none());
|
||||
/// ```
|
||||
#[unstable(feature = "str_checked_slicing", issue = "39932")]
|
||||
#[inline]
|
||||
pub fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
|
||||
core_str::StrExt::get_mut(self, i)
|
||||
}
|
||||
|
||||
/// Returns a unchecked subslice of `str`.
|
||||
///
|
||||
/// This is the unchecked alternative to indexing the `str`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Callers of this function are responsible that these preconditions are
|
||||
/// satisfied:
|
||||
///
|
||||
/// * The starting index must come before the ending index;
|
||||
/// * Indexes must be within bounds of the original slice;
|
||||
/// * Indexes must lie on UTF-8 sequence boundaries.
|
||||
///
|
||||
/// Failing that, the returned string slice may reference invalid memory or
|
||||
/// violate the invariants communicated by the `str` type.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(str_checked_slicing)]
|
||||
/// let v = "🗻∈🌏";
|
||||
/// unsafe {
|
||||
/// assert_eq!("🗻", v.get_unchecked(0..4));
|
||||
/// assert_eq!("∈", v.get_unchecked(4..7));
|
||||
/// assert_eq!("🌏", v.get_unchecked(7..11));
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "str_checked_slicing", issue = "39932")]
|
||||
#[inline]
|
||||
pub unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output {
|
||||
core_str::StrExt::get_unchecked(self, i)
|
||||
}
|
||||
|
||||
/// Returns a mutable, unchecked subslice of `str`.
|
||||
///
|
||||
/// This is the unchecked alternative to indexing the `str`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Callers of this function are responsible that these preconditions are
|
||||
/// satisfied:
|
||||
///
|
||||
/// * The starting index must come before the ending index;
|
||||
/// * Indexes must be within bounds of the original slice;
|
||||
/// * Indexes must lie on UTF-8 sequence boundaries.
|
||||
///
|
||||
/// Failing that, the returned string slice may reference invalid memory or
|
||||
/// violate the invariants communicated by the `str` type.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(str_checked_slicing)]
|
||||
/// let mut v = String::from("🗻∈🌏");
|
||||
/// unsafe {
|
||||
/// assert_eq!("🗻", v.get_unchecked_mut(0..4));
|
||||
/// assert_eq!("∈", v.get_unchecked_mut(4..7));
|
||||
/// assert_eq!("🌏", v.get_unchecked_mut(7..11));
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "str_checked_slicing", issue = "39932")]
|
||||
#[inline]
|
||||
pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output {
|
||||
core_str::StrExt::get_unchecked_mut(self, i)
|
||||
}
|
||||
|
||||
/// Creates a string slice from another string slice, bypassing safety
|
||||
/// checks.
|
||||
///
|
||||
|
@ -97,8 +97,7 @@ pub trait SliceExt {
|
||||
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn get<I>(&self, index: I) -> Option<&I::Output>
|
||||
where I: SliceIndex<Self::Item>;
|
||||
|
||||
where I: SliceIndex<Self>;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn first(&self) -> Option<&Self::Item>;
|
||||
|
||||
@ -113,8 +112,7 @@ pub trait SliceExt {
|
||||
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
|
||||
where I: SliceIndex<Self::Item>;
|
||||
|
||||
where I: SliceIndex<Self>;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn as_ptr(&self) -> *const Self::Item;
|
||||
|
||||
@ -141,8 +139,7 @@ pub trait SliceExt {
|
||||
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
|
||||
where I: SliceIndex<Self::Item>;
|
||||
|
||||
where I: SliceIndex<Self>;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn iter_mut(&mut self) -> IterMut<Self::Item>;
|
||||
|
||||
@ -184,8 +181,7 @@ pub trait SliceExt {
|
||||
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
|
||||
where I: SliceIndex<Self::Item>;
|
||||
|
||||
where I: SliceIndex<Self>;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn as_mut_ptr(&mut self) -> *mut Self::Item;
|
||||
|
||||
@ -337,7 +333,7 @@ impl<T> SliceExt for [T] {
|
||||
|
||||
#[inline]
|
||||
fn get<I>(&self, index: I) -> Option<&I::Output>
|
||||
where I: SliceIndex<T>
|
||||
where I: SliceIndex<[T]>
|
||||
{
|
||||
index.get(self)
|
||||
}
|
||||
@ -365,7 +361,7 @@ impl<T> SliceExt for [T] {
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
|
||||
where I: SliceIndex<T>
|
||||
where I: SliceIndex<[T]>
|
||||
{
|
||||
index.get_unchecked(self)
|
||||
}
|
||||
@ -406,7 +402,7 @@ impl<T> SliceExt for [T] {
|
||||
|
||||
#[inline]
|
||||
fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
|
||||
where I: SliceIndex<T>
|
||||
where I: SliceIndex<[T]>
|
||||
{
|
||||
index.get_mut(self)
|
||||
}
|
||||
@ -538,7 +534,7 @@ impl<T> SliceExt for [T] {
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
|
||||
where I: SliceIndex<T>
|
||||
where I: SliceIndex<[T]>
|
||||
{
|
||||
index.get_unchecked_mut(self)
|
||||
}
|
||||
@ -631,7 +627,7 @@ impl<T> SliceExt for [T] {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T, I> ops::Index<I> for [T]
|
||||
where I: SliceIndex<T>
|
||||
where I: SliceIndex<[T]>
|
||||
{
|
||||
type Output = I::Output;
|
||||
|
||||
@ -644,7 +640,7 @@ impl<T, I> ops::Index<I> for [T]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T, I> ops::IndexMut<I> for [T]
|
||||
where I: SliceIndex<T>
|
||||
where I: SliceIndex<[T]>
|
||||
{
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: I) -> &mut I::Output {
|
||||
@ -667,37 +663,37 @@ fn slice_index_order_fail(index: usize, end: usize) -> ! {
|
||||
/// A helper trait used for indexing operations.
|
||||
#[unstable(feature = "slice_get_slice", issue = "35729")]
|
||||
#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
|
||||
pub trait SliceIndex<T> {
|
||||
pub trait SliceIndex<T: ?Sized> {
|
||||
/// The output type returned by methods.
|
||||
type Output: ?Sized;
|
||||
|
||||
/// Returns a shared reference to the output at this location, if in
|
||||
/// bounds.
|
||||
fn get(self, slice: &[T]) -> Option<&Self::Output>;
|
||||
fn get(self, slice: &T) -> Option<&Self::Output>;
|
||||
|
||||
/// Returns a mutable reference to the output at this location, if in
|
||||
/// bounds.
|
||||
fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output>;
|
||||
fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>;
|
||||
|
||||
/// Returns a shared reference to the output at this location, without
|
||||
/// performing any bounds checking.
|
||||
unsafe fn get_unchecked(self, slice: &[T]) -> &Self::Output;
|
||||
unsafe fn get_unchecked(self, slice: &T) -> &Self::Output;
|
||||
|
||||
/// Returns a mutable reference to the output at this location, without
|
||||
/// performing any bounds checking.
|
||||
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut Self::Output;
|
||||
unsafe fn get_unchecked_mut(self, slice: &mut T) -> &mut Self::Output;
|
||||
|
||||
/// Returns a shared reference to the output at this location, panicking
|
||||
/// if out of bounds.
|
||||
fn index(self, slice: &[T]) -> &Self::Output;
|
||||
fn index(self, slice: &T) -> &Self::Output;
|
||||
|
||||
/// Returns a mutable reference to the output at this location, panicking
|
||||
/// if out of bounds.
|
||||
fn index_mut(self, slice: &mut [T]) -> &mut Self::Output;
|
||||
fn index_mut(self, slice: &mut T) -> &mut Self::Output;
|
||||
}
|
||||
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
|
||||
impl<T> SliceIndex<T> for usize {
|
||||
impl<T> SliceIndex<[T]> for usize {
|
||||
type Output = T;
|
||||
|
||||
#[inline]
|
||||
@ -746,7 +742,7 @@ impl<T> SliceIndex<T> for usize {
|
||||
}
|
||||
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
|
||||
impl<T> SliceIndex<T> for ops::Range<usize> {
|
||||
impl<T> SliceIndex<[T]> for ops::Range<usize> {
|
||||
type Output = [T];
|
||||
|
||||
#[inline]
|
||||
@ -807,7 +803,7 @@ impl<T> SliceIndex<T> for ops::Range<usize> {
|
||||
}
|
||||
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
|
||||
impl<T> SliceIndex<T> for ops::RangeTo<usize> {
|
||||
impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
|
||||
type Output = [T];
|
||||
|
||||
#[inline]
|
||||
@ -842,7 +838,7 @@ impl<T> SliceIndex<T> for ops::RangeTo<usize> {
|
||||
}
|
||||
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
|
||||
impl<T> SliceIndex<T> for ops::RangeFrom<usize> {
|
||||
impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
|
||||
type Output = [T];
|
||||
|
||||
#[inline]
|
||||
@ -877,7 +873,7 @@ impl<T> SliceIndex<T> for ops::RangeFrom<usize> {
|
||||
}
|
||||
|
||||
#[stable(feature = "slice-get-slice-impls", since = "1.15.0")]
|
||||
impl<T> SliceIndex<T> for ops::RangeFull {
|
||||
impl<T> SliceIndex<[T]> for ops::RangeFull {
|
||||
type Output = [T];
|
||||
|
||||
#[inline]
|
||||
@ -913,7 +909,7 @@ impl<T> SliceIndex<T> for ops::RangeFull {
|
||||
|
||||
|
||||
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
|
||||
impl<T> SliceIndex<T> for ops::RangeInclusive<usize> {
|
||||
impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
|
||||
type Output = [T];
|
||||
|
||||
#[inline]
|
||||
@ -976,7 +972,7 @@ impl<T> SliceIndex<T> for ops::RangeInclusive<usize> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
|
||||
impl<T> SliceIndex<T> for ops::RangeToInclusive<usize> {
|
||||
impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
|
||||
type Output = [T];
|
||||
|
||||
#[inline]
|
||||
|
@ -22,7 +22,7 @@ use convert::TryFrom;
|
||||
use fmt;
|
||||
use iter::{Map, Cloned, FusedIterator};
|
||||
use mem;
|
||||
use slice;
|
||||
use slice::{self, SliceIndex};
|
||||
|
||||
pub mod pattern;
|
||||
|
||||
@ -1445,6 +1445,8 @@ Section: Trait implementations
|
||||
mod traits {
|
||||
use cmp::Ordering;
|
||||
use ops;
|
||||
use mem;
|
||||
use slice::{self, SliceIndex};
|
||||
use str::eq_slice;
|
||||
|
||||
/// Implements ordering of strings.
|
||||
@ -1527,14 +1529,7 @@ mod traits {
|
||||
type Output = str;
|
||||
#[inline]
|
||||
fn index(&self, index: ops::Range<usize>) -> &str {
|
||||
// is_char_boundary checks that the index is in [0, .len()]
|
||||
if index.start <= index.end &&
|
||||
self.is_char_boundary(index.start) &&
|
||||
self.is_char_boundary(index.end) {
|
||||
unsafe { self.slice_unchecked(index.start, index.end) }
|
||||
} else {
|
||||
super::slice_error_fail(self, index.start, index.end)
|
||||
}
|
||||
index.index(self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1556,14 +1551,7 @@ mod traits {
|
||||
impl ops::IndexMut<ops::Range<usize>> for str {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
|
||||
// is_char_boundary checks that the index is in [0, .len()]
|
||||
if index.start <= index.end &&
|
||||
self.is_char_boundary(index.start) &&
|
||||
self.is_char_boundary(index.end) {
|
||||
unsafe { self.slice_mut_unchecked(index.start, index.end) }
|
||||
} else {
|
||||
super::slice_error_fail(self, index.start, index.end)
|
||||
}
|
||||
index.index_mut(self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1731,8 +1719,276 @@ mod traits {
|
||||
self.index_mut(0...index.end)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "str_checked_slicing", issue = "39932")]
|
||||
impl SliceIndex<str> for ops::RangeFull {
|
||||
type Output = str;
|
||||
#[inline]
|
||||
fn get(self, slice: &str) -> Option<&Self::Output> {
|
||||
Some(slice)
|
||||
}
|
||||
#[inline]
|
||||
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
|
||||
Some(slice)
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
|
||||
slice
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
slice
|
||||
}
|
||||
#[inline]
|
||||
fn index(self, slice: &str) -> &Self::Output {
|
||||
slice
|
||||
}
|
||||
#[inline]
|
||||
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
slice
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "str_checked_slicing", issue = "39932")]
|
||||
impl SliceIndex<str> for ops::Range<usize> {
|
||||
type Output = str;
|
||||
#[inline]
|
||||
fn get(self, slice: &str) -> Option<&Self::Output> {
|
||||
if self.start <= self.end &&
|
||||
slice.is_char_boundary(self.start) &&
|
||||
slice.is_char_boundary(self.end) {
|
||||
Some(unsafe { self.get_unchecked(slice) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
|
||||
if self.start <= self.end &&
|
||||
slice.is_char_boundary(self.start) &&
|
||||
slice.is_char_boundary(self.end) {
|
||||
Some(unsafe { self.get_unchecked_mut(slice) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
|
||||
let ptr = slice.as_ptr().offset(self.start as isize);
|
||||
let len = self.end - self.start;
|
||||
super::from_utf8_unchecked(slice::from_raw_parts(ptr, len))
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
let ptr = slice.as_ptr().offset(self.start as isize);
|
||||
let len = self.end - self.start;
|
||||
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
|
||||
}
|
||||
#[inline]
|
||||
fn index(self, slice: &str) -> &Self::Output {
|
||||
let (start, end) = (self.start, self.end);
|
||||
self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, start, end))
|
||||
}
|
||||
#[inline]
|
||||
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
// is_char_boundary checks that the index is in [0, .len()]
|
||||
// canot reuse `get` as above, because of NLL trouble
|
||||
if self.start <= self.end &&
|
||||
slice.is_char_boundary(self.start) &&
|
||||
slice.is_char_boundary(self.end) {
|
||||
unsafe { self.get_unchecked_mut(slice) }
|
||||
} else {
|
||||
super::slice_error_fail(slice, self.start, self.end)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "str_checked_slicing", issue = "39932")]
|
||||
impl SliceIndex<str> for ops::RangeTo<usize> {
|
||||
type Output = str;
|
||||
#[inline]
|
||||
fn get(self, slice: &str) -> Option<&Self::Output> {
|
||||
if slice.is_char_boundary(self.end) {
|
||||
Some(unsafe { self.get_unchecked(slice) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
|
||||
if slice.is_char_boundary(self.end) {
|
||||
Some(unsafe { self.get_unchecked_mut(slice) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
|
||||
let ptr = slice.as_ptr();
|
||||
super::from_utf8_unchecked(slice::from_raw_parts(ptr, self.end))
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
let ptr = slice.as_ptr();
|
||||
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, self.end))
|
||||
}
|
||||
#[inline]
|
||||
fn index(self, slice: &str) -> &Self::Output {
|
||||
let end = self.end;
|
||||
self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, 0, end))
|
||||
}
|
||||
#[inline]
|
||||
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
if slice.is_char_boundary(self.end) {
|
||||
unsafe { self.get_unchecked_mut(slice) }
|
||||
} else {
|
||||
super::slice_error_fail(slice, 0, self.end)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "str_checked_slicing", issue = "39932")]
|
||||
impl SliceIndex<str> for ops::RangeFrom<usize> {
|
||||
type Output = str;
|
||||
#[inline]
|
||||
fn get(self, slice: &str) -> Option<&Self::Output> {
|
||||
if slice.is_char_boundary(self.start) {
|
||||
Some(unsafe { self.get_unchecked(slice) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
|
||||
if slice.is_char_boundary(self.start) {
|
||||
Some(unsafe { self.get_unchecked_mut(slice) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
|
||||
let ptr = slice.as_ptr().offset(self.start as isize);
|
||||
let len = slice.len() - self.start;
|
||||
super::from_utf8_unchecked(slice::from_raw_parts(ptr, len))
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
let ptr = slice.as_ptr().offset(self.start as isize);
|
||||
let len = slice.len() - self.start;
|
||||
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
|
||||
}
|
||||
#[inline]
|
||||
fn index(self, slice: &str) -> &Self::Output {
|
||||
let (start, end) = (self.start, slice.len());
|
||||
self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, start, end))
|
||||
}
|
||||
#[inline]
|
||||
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
if slice.is_char_boundary(self.start) {
|
||||
unsafe { self.get_unchecked_mut(slice) }
|
||||
} else {
|
||||
super::slice_error_fail(slice, self.start, slice.len())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "str_checked_slicing", issue = "39932")]
|
||||
impl SliceIndex<str> for ops::RangeInclusive<usize> {
|
||||
type Output = str;
|
||||
#[inline]
|
||||
fn get(self, slice: &str) -> Option<&Self::Output> {
|
||||
match self {
|
||||
ops::RangeInclusive::Empty { .. } => 0..0,
|
||||
ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
|
||||
}.get(slice)
|
||||
}
|
||||
#[inline]
|
||||
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
|
||||
match self {
|
||||
ops::RangeInclusive::Empty { .. } => 0..0,
|
||||
ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
|
||||
}.get_mut(slice)
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
|
||||
match self {
|
||||
ops::RangeInclusive::Empty { .. } => 0..0,
|
||||
ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
|
||||
}.get_unchecked(slice)
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
match self {
|
||||
ops::RangeInclusive::Empty { .. } => 0..0,
|
||||
ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
|
||||
}.get_unchecked_mut(slice)
|
||||
}
|
||||
#[inline]
|
||||
fn index(self, slice: &str) -> &Self::Output {
|
||||
match self {
|
||||
ops::RangeInclusive::Empty { .. } => 0..0,
|
||||
ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
|
||||
}.index(slice)
|
||||
}
|
||||
#[inline]
|
||||
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
match self {
|
||||
ops::RangeInclusive::Empty { .. } => 0..0,
|
||||
ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
|
||||
}.index_mut(slice)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[unstable(feature = "str_checked_slicing", issue = "39932")]
|
||||
impl SliceIndex<str> for ops::RangeToInclusive<usize> {
|
||||
type Output = str;
|
||||
#[inline]
|
||||
fn get(self, slice: &str) -> Option<&Self::Output> {
|
||||
if slice.is_char_boundary(self.end + 1) {
|
||||
Some(unsafe { self.get_unchecked(slice) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
|
||||
if slice.is_char_boundary(self.end + 1) {
|
||||
Some(unsafe { self.get_unchecked_mut(slice) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
|
||||
let ptr = slice.as_ptr();
|
||||
super::from_utf8_unchecked(slice::from_raw_parts(ptr, self.end + 1))
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
let ptr = slice.as_ptr();
|
||||
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, self.end + 1))
|
||||
}
|
||||
#[inline]
|
||||
fn index(self, slice: &str) -> &Self::Output {
|
||||
let end = self.end + 1;
|
||||
self.get(slice).unwrap_or_else(|| super::slice_error_fail(slice, 0, end))
|
||||
}
|
||||
#[inline]
|
||||
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
if slice.is_char_boundary(self.end) {
|
||||
unsafe { self.get_unchecked_mut(slice) }
|
||||
} else {
|
||||
super::slice_error_fail(slice, 0, self.end + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Methods for string slices
|
||||
#[allow(missing_docs)]
|
||||
#[doc(hidden)]
|
||||
@ -1782,6 +2038,14 @@ pub trait StrExt {
|
||||
#[rustc_deprecated(since = "1.6.0", reason = "use lines() instead now")]
|
||||
#[allow(deprecated)]
|
||||
fn lines_any(&self) -> LinesAny;
|
||||
#[unstable(feature = "str_checked_slicing", issue = "39932")]
|
||||
fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output>;
|
||||
#[unstable(feature = "str_checked_slicing", issue = "39932")]
|
||||
fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output>;
|
||||
#[unstable(feature = "str_checked_slicing", issue = "39932")]
|
||||
unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output;
|
||||
#[unstable(feature = "str_checked_slicing", issue = "39932")]
|
||||
unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
@ -1971,18 +2235,34 @@ impl StrExt for str {
|
||||
LinesAny(self.lines())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
|
||||
i.get(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
|
||||
i.get_mut(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output {
|
||||
i.get_unchecked(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output {
|
||||
i.get_unchecked_mut(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
|
||||
let ptr = self.as_ptr().offset(begin as isize);
|
||||
let len = end - begin;
|
||||
from_utf8_unchecked(slice::from_raw_parts(ptr, len))
|
||||
(begin..end).get_unchecked(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str {
|
||||
let ptr = self.as_ptr().offset(begin as isize);
|
||||
let len = end - begin;
|
||||
mem::transmute(slice::from_raw_parts_mut(ptr as *mut u8, len))
|
||||
(begin..end).get_unchecked_mut(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
fn main() {
|
||||
fn bar<T>(_: T) {}
|
||||
[0][0u8]; //~ ERROR: the trait bound `u8: std::slice::SliceIndex<{integer}>` is not satisfied
|
||||
[0][0u8]; //~ ERROR: the trait bound `u8: std::slice::SliceIndex<[{integer}]>` is not satisfied
|
||||
|
||||
[0][0]; // should infer to be a usize
|
||||
|
||||
|
@ -19,8 +19,8 @@ pub fn main() {
|
||||
v[3i32]; //~ERROR : std::ops::Index<i32>` is not satisfied
|
||||
s.as_bytes()[3_usize];
|
||||
s.as_bytes()[3];
|
||||
s.as_bytes()[3u8]; //~ERROR : std::slice::SliceIndex<u8>` is not satisfied
|
||||
s.as_bytes()[3i8]; //~ERROR : std::slice::SliceIndex<u8>` is not satisfied
|
||||
s.as_bytes()[3u32]; //~ERROR : std::slice::SliceIndex<u8>` is not satisfied
|
||||
s.as_bytes()[3i32]; //~ERROR : std::slice::SliceIndex<u8>` is not satisfied
|
||||
s.as_bytes()[3u8]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
|
||||
s.as_bytes()[3i8]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
|
||||
s.as_bytes()[3u32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
|
||||
s.as_bytes()[3i32]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
|
||||
}
|
||||
|
@ -20,10 +20,10 @@ fn main() {
|
||||
let x = &[1, 2, 3] as &[i32];
|
||||
x[1i32]; //~ ERROR E0277
|
||||
//~| NOTE slice indices are of type `usize` or ranges of `usize`
|
||||
//~| NOTE trait `std::slice::SliceIndex<i32>` is not implemented for `i32`
|
||||
//~| NOTE trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32`
|
||||
//~| NOTE required because of the requirements on the impl of `std::ops::Index<i32>`
|
||||
x[..1i32]; //~ ERROR E0277
|
||||
//~| NOTE slice indices are of type `usize` or ranges of `usize`
|
||||
//~| NOTE trait `std::slice::SliceIndex<i32>` is not implemented for `std::ops::RangeTo<i32>`
|
||||
//~| NOTE trait `std::slice::SliceIndex<[i32]>` is not implemented for `std::ops::RangeTo<i32>`
|
||||
//~| NOTE requirements on the impl of `std::ops::Index<std::ops::RangeTo<i32>>`
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user