mod traits {
use crate::cmp::Ordering;
use crate::ops;
- use crate::slice::{self, SliceIndex};
+ use crate::ptr;
+ use crate::slice::SliceIndex;
/// Implements ordering of strings.
///
///
/// Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`.
#[stable(feature = "str_checked_slicing", since = "1.20.0")]
- impl SliceIndex<str> for ops::RangeFull {
+ unsafe impl SliceIndex<str> for ops::RangeFull {
type Output = str;
#[inline]
fn get(self, slice: &str) -> Option<&Self::Output> {
Some(slice)
}
#[inline]
- unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
+ unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
slice
}
#[inline]
- unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
+ unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
slice
}
#[inline]
/// // &s[3 .. 100];
/// ```
#[stable(feature = "str_checked_slicing", since = "1.20.0")]
- impl SliceIndex<str> for ops::Range<usize> {
+ unsafe impl SliceIndex<str> for ops::Range<usize> {
type Output = str;
#[inline]
fn get(self, slice: &str) -> Option<&Self::Output> {
&& slice.is_char_boundary(self.start)
&& slice.is_char_boundary(self.end)
{
- // SAFETY: just checked that `start` and `end` are on a char boundary.
- Some(unsafe { self.get_unchecked(slice) })
+ // SAFETY: just checked that `start` and `end` are on a char boundary,
+ // and we are passing in a safe reference, so the return value will also be one.
+ // We also checked char boundaries, so this is valid UTF-8.
+ Some(unsafe { &*self.get_unchecked(slice) })
} else {
None
}
&& slice.is_char_boundary(self.end)
{
// SAFETY: just checked that `start` and `end` are on a char boundary.
- Some(unsafe { self.get_unchecked_mut(slice) })
+ // We know the pointer is unique because we got it from `slice`.
+ Some(unsafe { &mut *self.get_unchecked_mut(slice) })
} else {
None
}
}
#[inline]
- unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
+ unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
+ let slice = slice as *const [u8];
// SAFETY: the caller guarantees that `self` is in bounds of `slice`
// which satisfies all the conditions for `add`.
let ptr = unsafe { slice.as_ptr().add(self.start) };
let len = self.end - self.start;
- // SAFETY: as the caller guarantees that `self` is in bounds of `slice`,
- // we can safely construct a subslice with `from_raw_parts` and use it
- // since we return a shared thus immutable reference.
- // The call to `from_utf8_unchecked` is safe since the data comes from
- // a `str` which is guaranteed to be valid utf8, since the caller
- // must guarantee that `self.start` and `self.end` are char boundaries.
- unsafe { super::from_utf8_unchecked(slice::from_raw_parts(ptr, len)) }
+ ptr::slice_from_raw_parts(ptr, len) as *const str
}
#[inline]
- unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
+ unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
+ let slice = slice as *mut [u8];
// SAFETY: see comments for `get_unchecked`.
let ptr = unsafe { slice.as_mut_ptr().add(self.start) };
let len = self.end - self.start;
- // SAFETY: mostly identical to the comments for `get_unchecked`, except that we
- // can return a mutable reference since the caller passed a mutable reference
- // and is thus guaranteed to have exclusive write access to `slice`.
- unsafe { super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, len)) }
+ ptr::slice_from_raw_parts_mut(ptr, len) as *mut str
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
&& slice.is_char_boundary(self.start)
&& slice.is_char_boundary(self.end)
{
- // SAFETY: just checked that `start` and `end` are on a char boundary.
- unsafe { self.get_unchecked_mut(slice) }
+ // SAFETY: just checked that `start` and `end` are on a char boundary,
+ // and we are passing in a safe reference, so the return value will also be one.
+ unsafe { &mut *self.get_unchecked_mut(slice) }
} else {
super::slice_error_fail(slice, self.start, self.end)
}
/// Panics if `end` does not point to the starting byte offset of a
/// character (as defined by `is_char_boundary`), or if `end > len`.
#[stable(feature = "str_checked_slicing", since = "1.20.0")]
- impl SliceIndex<str> for ops::RangeTo<usize> {
+ unsafe 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) {
- // SAFETY: just checked that `end` is on a char boundary.
- Some(unsafe { self.get_unchecked(slice) })
+ // SAFETY: just checked that `end` is on a char boundary,
+ // and we are passing in a safe reference, so the return value will also be one.
+ 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) {
- // SAFETY: just checked that `end` is on a char boundary.
- Some(unsafe { self.get_unchecked_mut(slice) })
+ // SAFETY: just checked that `end` is on a char boundary,
+ // and we are passing in a safe reference, so the return value will also be one.
+ Some(unsafe { &mut *self.get_unchecked_mut(slice) })
} else {
None
}
}
#[inline]
- unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
+ unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
+ let slice = slice as *const [u8];
let ptr = slice.as_ptr();
- // SAFETY: as the caller guarantees that `self` is in bounds of `slice`,
- // we can safely construct a subslice with `from_raw_parts` and use it
- // since we return a shared thus immutable reference.
- // The call to `from_utf8_unchecked` is safe since the data comes from
- // a `str` which is guaranteed to be valid utf8, since the caller
- // must guarantee that `self.end` is a char boundary.
- unsafe { super::from_utf8_unchecked(slice::from_raw_parts(ptr, self.end)) }
+ ptr::slice_from_raw_parts(ptr, self.end) as *const str
}
#[inline]
- unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
+ unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
+ let slice = slice as *mut [u8];
let ptr = slice.as_mut_ptr();
- // SAFETY: mostly identical to `get_unchecked`, except that we can safely
- // return a mutable reference since the caller passed a mutable reference
- // and is thus guaranteed to have exclusive write access to `slice`.
- unsafe { super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, self.end)) }
+ ptr::slice_from_raw_parts_mut(ptr, self.end) as *mut str
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
#[inline]
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
if slice.is_char_boundary(self.end) {
- // SAFETY: just checked that `end` is on a char boundary.
- unsafe { self.get_unchecked_mut(slice) }
+ // SAFETY: just checked that `end` is on a char boundary,
+ // and we are passing in a safe reference, so the return value will also be one.
+ unsafe { &mut *self.get_unchecked_mut(slice) }
} else {
super::slice_error_fail(slice, 0, self.end)
}
/// Panics if `begin` does not point to the starting byte offset of
/// a character (as defined by `is_char_boundary`), or if `begin >= len`.
#[stable(feature = "str_checked_slicing", since = "1.20.0")]
- impl SliceIndex<str> for ops::RangeFrom<usize> {
+ unsafe 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) {
- // SAFETY: just checked that `start` is on a char boundary.
- Some(unsafe { self.get_unchecked(slice) })
+ // SAFETY: just checked that `start` is on a char boundary,
+ // and we are passing in a safe reference, so the return value will also be one.
+ 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) {
- // SAFETY: just checked that `start` is on a char boundary.
- Some(unsafe { self.get_unchecked_mut(slice) })
+ // SAFETY: just checked that `start` is on a char boundary,
+ // and we are passing in a safe reference, so the return value will also be one.
+ Some(unsafe { &mut *self.get_unchecked_mut(slice) })
} else {
None
}
}
#[inline]
- unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
+ unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
+ let slice = slice as *const [u8];
// SAFETY: the caller guarantees that `self` is in bounds of `slice`
// which satisfies all the conditions for `add`.
let ptr = unsafe { slice.as_ptr().add(self.start) };
let len = slice.len() - self.start;
- // SAFETY: as the caller guarantees that `self` is in bounds of `slice`,
- // we can safely construct a subslice with `from_raw_parts` and use it
- // since we return a shared thus immutable reference.
- // The call to `from_utf8_unchecked` is safe since the data comes from
- // a `str` which is guaranteed to be valid utf8, since the caller
- // must guarantee that `self.start` is a char boundary.
- unsafe { super::from_utf8_unchecked(slice::from_raw_parts(ptr, len)) }
+ ptr::slice_from_raw_parts(ptr, len) as *const str
}
#[inline]
- unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
+ unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
+ let slice = slice as *mut [u8];
// SAFETY: identical to `get_unchecked`.
let ptr = unsafe { slice.as_mut_ptr().add(self.start) };
let len = slice.len() - self.start;
- // SAFETY: mostly identical to `get_unchecked`, except that we can safely
- // return a mutable reference since the caller passed a mutable reference
- // and is thus guaranteed to have exclusive write access to `slice`.
- unsafe { super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, len)) }
+ ptr::slice_from_raw_parts_mut(ptr, len) as *mut str
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
#[inline]
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
if slice.is_char_boundary(self.start) {
- // SAFETY: just checked that `start` is on a char boundary.
- unsafe { self.get_unchecked_mut(slice) }
+ // SAFETY: just checked that `start` is on a char boundary,
+ // and we are passing in a safe reference, so the return value will also be one.
+ unsafe { &mut *self.get_unchecked_mut(slice) }
} else {
super::slice_error_fail(slice, self.start, slice.len())
}
/// to the ending byte offset of a character (`end + 1` is either a starting
/// byte offset or equal to `len`), if `begin > end`, or if `end >= len`.
#[stable(feature = "inclusive_range", since = "1.26.0")]
- impl SliceIndex<str> for ops::RangeInclusive<usize> {
+ unsafe impl SliceIndex<str> for ops::RangeInclusive<usize> {
type Output = str;
#[inline]
fn get(self, slice: &str) -> Option<&Self::Output> {
}
}
#[inline]
- unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
+ unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
// SAFETY: the caller must uphold the safety contract for `get_unchecked`.
unsafe { (*self.start()..self.end() + 1).get_unchecked(slice) }
}
#[inline]
- unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
+ unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
// SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
unsafe { (*self.start()..self.end() + 1).get_unchecked_mut(slice) }
}
/// (`end + 1` is either a starting byte offset as defined by
/// `is_char_boundary`, or equal to `len`), or if `end >= len`.
#[stable(feature = "inclusive_range", since = "1.26.0")]
- impl SliceIndex<str> for ops::RangeToInclusive<usize> {
+ unsafe impl SliceIndex<str> for ops::RangeToInclusive<usize> {
type Output = str;
#[inline]
fn get(self, slice: &str) -> Option<&Self::Output> {
if self.end == usize::MAX { None } else { (..self.end + 1).get_mut(slice) }
}
#[inline]
- unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
+ unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
// SAFETY: the caller must uphold the safety contract for `get_unchecked`.
unsafe { (..self.end + 1).get_unchecked(slice) }
}
#[inline]
- unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
+ unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
// SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
unsafe { (..self.end + 1).get_unchecked_mut(slice) }
}
unsafe { Slices { str: self }.slice }
}
- /// Converts a mutable string slice to a mutable byte slice. To convert the
- /// mutable byte slice back into a mutable string slice, use the
- /// [`str::from_utf8_mut`] function.
+ /// Converts a mutable string slice to a mutable byte slice.
///
- /// [`str::from_utf8_mut`]: ./str/fn.from_utf8_mut.html
+ /// # Safety
+ ///
+ /// The caller must ensure that the content of the slice is valid UTF-8
+ /// before the borrow ends and the underlying `str` is used.
+ ///
+ /// Use of a `str` whose contents are not valid UTF-8 is undefined behavior.
///
/// # Examples
///
#[stable(feature = "str_checked_slicing", since = "1.20.0")]
#[inline]
pub unsafe fn get_unchecked<I: SliceIndex<str>>(&self, i: I) -> &I::Output {
- // SAFETY: the caller must uphold the safety contract for `get_unchecked`.
- unsafe { i.get_unchecked(self) }
+ // SAFETY: the caller must uphold the safety contract for `get_unchecked`;
+ // the slice is dereferencable because `self` is a safe reference.
+ // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is.
+ unsafe { &*i.get_unchecked(self) }
}
/// Returns a mutable, unchecked subslice of `str`.
#[stable(feature = "str_checked_slicing", since = "1.20.0")]
#[inline]
pub unsafe fn get_unchecked_mut<I: SliceIndex<str>>(&mut self, i: I) -> &mut I::Output {
- // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
- unsafe { i.get_unchecked_mut(self) }
+ // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`;
+ // the slice is dereferencable because `self` is a safe reference.
+ // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is.
+ unsafe { &mut *i.get_unchecked_mut(self) }
}
/// Creates a string slice from another string slice, bypassing safety
#[rustc_deprecated(since = "1.29.0", reason = "use `get_unchecked(begin..end)` instead")]
#[inline]
pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
- // SAFETY: the caller must uphold the safety contract for `get_unchecked`.
- unsafe { (begin..end).get_unchecked(self) }
+ // SAFETY: the caller must uphold the safety contract for `get_unchecked`;
+ // the slice is dereferencable because `self` is a safe reference.
+ // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is.
+ unsafe { &*(begin..end).get_unchecked(self) }
}
/// Creates a string slice from another string slice, bypassing safety
#[rustc_deprecated(since = "1.29.0", reason = "use `get_unchecked_mut(begin..end)` instead")]
#[inline]
pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str {
- // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
- unsafe { (begin..end).get_unchecked_mut(self) }
+ // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`;
+ // the slice is dereferencable because `self` is a safe reference.
+ // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is.
+ unsafe { &mut *(begin..end).get_unchecked_mut(self) }
}
/// Divide one string slice into two at an index.
/// Simple patterns:
///
/// ```
- /// let s = "Löwe 老虎 Léopard";
+ /// let s = "Löwe 老虎 Léopard Gepardi";
///
/// assert_eq!(s.find('L'), Some(0));
/// assert_eq!(s.find('é'), Some(14));
- /// assert_eq!(s.find("Léopard"), Some(13));
+ /// assert_eq!(s.find("pard"), Some(17));
/// ```
///
/// More complex patterns using point-free style and closures:
pat.into_searcher(self).next_match().map(|(i, _)| i)
}
- /// Returns the byte index of the last character of this string slice that
- /// matches the pattern.
+ /// Returns the byte index for the first character of the rightmost match of the pattern in
+ /// this string slice.
///
/// Returns [`None`] if the pattern doesn't match.
///
/// Simple patterns:
///
/// ```
- /// let s = "Löwe 老虎 Léopard";
+ /// let s = "Löwe 老虎 Léopard Gepardi";
///
/// assert_eq!(s.rfind('L'), Some(13));
/// assert_eq!(s.rfind('é'), Some(14));
+ /// assert_eq!(s.rfind("pard"), Some(24));
/// ```
///
/// More complex patterns with closures:
// We can treat each byte as character here: all multibyte characters
// start with a byte that is not in the ascii range, so we will stop
// there already.
- self.bytes().all(|b| b.is_ascii())
+ self.as_bytes().is_ascii()
}
/// Checks that two strings are an ASCII case-insensitive match.