Auto merge of #26241 - SimonSapin:derefmut-for-string, r=alexcrichton
See https://github.com/rust-lang/rfcs/issues/1157
This commit is contained in:
@@ -1116,6 +1116,23 @@ mod traits {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable slice of the given string from the byte range
|
||||
/// [`begin`..`end`).
|
||||
#[stable(feature = "derefmut_for_string", since = "1.2.0")]
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a slice of the string from the beginning to byte
|
||||
/// `end`.
|
||||
///
|
||||
@@ -1138,6 +1155,21 @@ mod traits {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable slice of the string from the beginning to byte
|
||||
/// `end`.
|
||||
#[stable(feature = "derefmut_for_string", since = "1.2.0")]
|
||||
impl ops::IndexMut<ops::RangeTo<usize>> for str {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut str {
|
||||
// is_char_boundary checks that the index is in [0, .len()]
|
||||
if self.is_char_boundary(index.end) {
|
||||
unsafe { self.slice_mut_unchecked(0, index.end) }
|
||||
} else {
|
||||
super::slice_error_fail(self, 0, index.end)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a slice of the string from `begin` to its end.
|
||||
///
|
||||
/// Equivalent to `self[begin .. self.len()]`.
|
||||
@@ -1159,6 +1191,21 @@ mod traits {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a slice of the string from `begin` to its end.
|
||||
#[stable(feature = "derefmut_for_string", since = "1.2.0")]
|
||||
impl ops::IndexMut<ops::RangeFrom<usize>> for str {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
|
||||
// is_char_boundary checks that the index is in [0, .len()]
|
||||
if self.is_char_boundary(index.start) {
|
||||
let len = self.len();
|
||||
unsafe { self.slice_mut_unchecked(index.start, len) }
|
||||
} else {
|
||||
super::slice_error_fail(self, index.start, self.len())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl ops::Index<ops::RangeFull> for str {
|
||||
type Output = str;
|
||||
@@ -1168,6 +1215,14 @@ mod traits {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "derefmut_for_string", since = "1.2.0")]
|
||||
impl ops::IndexMut<ops::RangeFull> for str {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Methods for string slices
|
||||
@@ -1204,6 +1259,7 @@ pub trait StrExt {
|
||||
fn char_len(&self) -> usize;
|
||||
fn slice_chars<'a>(&'a self, begin: usize, end: usize) -> &'a str;
|
||||
unsafe fn slice_unchecked<'a>(&'a self, begin: usize, end: usize) -> &'a str;
|
||||
unsafe fn slice_mut_unchecked<'a>(&'a mut self, begin: usize, end: usize) -> &'a mut str;
|
||||
fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool;
|
||||
fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool
|
||||
where P::Searcher: ReverseSearcher<'a>;
|
||||
@@ -1223,6 +1279,7 @@ pub trait StrExt {
|
||||
where P::Searcher: ReverseSearcher<'a>;
|
||||
fn find_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>;
|
||||
fn split_at(&self, mid: usize) -> (&str, &str);
|
||||
fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str);
|
||||
fn slice_shift_char<'a>(&'a self) -> Option<(char, &'a str)>;
|
||||
fn subslice_offset(&self, inner: &str) -> usize;
|
||||
fn as_ptr(&self) -> *const u8;
|
||||
@@ -1379,6 +1436,14 @@ impl StrExt for str {
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str {
|
||||
mem::transmute(Slice {
|
||||
data: self.as_ptr().offset(begin as isize),
|
||||
len: end - begin,
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
|
||||
pat.is_prefix_of(self)
|
||||
@@ -1527,6 +1592,20 @@ impl StrExt for str {
|
||||
}
|
||||
}
|
||||
|
||||
fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
|
||||
// is_char_boundary checks that the index is in [0, .len()]
|
||||
if self.is_char_boundary(mid) {
|
||||
let len = self.len();
|
||||
unsafe {
|
||||
let self2: &mut str = mem::transmute_copy(&self);
|
||||
(self.slice_mut_unchecked(0, mid),
|
||||
self2.slice_mut_unchecked(mid, len))
|
||||
}
|
||||
} else {
|
||||
slice_error_fail(self, 0, mid)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn slice_shift_char(&self) -> Option<(char, &str)> {
|
||||
if self.is_empty() {
|
||||
|
||||
Reference in New Issue
Block a user