// ignore-tidy-filelength
-// ignore-tidy-undocumented-unsafe
//! String manipulation.
//!
#![stable(feature = "rust1", since = "1.0.0")]
use self::pattern::Pattern;
-use self::pattern::{Searcher, SearchStep, ReverseSearcher, DoubleEndedSearcher};
+use self::pattern::{DoubleEndedSearcher, ReverseSearcher, SearchStep, Searcher};
use crate::char;
use crate::fmt::{self, Write};
-use crate::iter::{Map, Cloned, FusedIterator, TrustedLen, TrustedRandomAccess, Filter};
-use crate::iter::{Flatten, FlatMap, Chain};
-use crate::slice::{self, SliceIndex, Split as SliceSplit};
+use crate::iter::{Chain, FlatMap, Flatten};
+use crate::iter::{Cloned, Filter, FusedIterator, Map, TrustedLen, TrustedRandomAccess};
use crate::mem;
use crate::ops::Try;
use crate::option;
+use crate::slice::{self, SliceIndex, Split as SliceSplit};
pub mod pattern;
-#[unstable(feature = "str_internals", issue = "0")]
+#[unstable(feature = "str_internals", issue = "none")]
#[allow(missing_docs)]
pub mod lossy;
#[inline]
fn from_str(s: &str) -> Result<bool, ParseBoolError> {
match s {
- "true" => Ok(true),
+ "true" => Ok(true),
"false" => Ok(false),
- _ => Err(ParseBoolError { _priv: () }),
+ _ => Err(ParseBoolError { _priv: () }),
}
}
}
/// [`from_str`]: ../../std/primitive.bool.html#method.from_str
#[derive(Debug, Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct ParseBoolError { _priv: () }
+pub struct ParseBoolError {
+ _priv: (),
+}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for ParseBoolError {
/// assert_eq!(1, error.valid_up_to());
/// ```
#[stable(feature = "utf8_error", since = "1.5.0")]
- pub fn valid_up_to(&self) -> usize { self.valid_up_to }
+ pub fn valid_up_to(&self) -> usize {
+ self.valid_up_to
+ }
/// Provides more information about the failure:
///
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
run_utf8_validation(v)?;
+ // SAFETY: just ran validation
Ok(unsafe { from_utf8_unchecked(v) })
}
#[stable(feature = "str_mut_extras", since = "1.20.0")]
pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
run_utf8_validation(v)?;
+ // SAFETY: just ran validation
Ok(unsafe { from_utf8_unchecked_mut(v) })
}
impl fmt::Display for Utf8Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(error_len) = self.error_len {
- write!(f, "invalid utf-8 sequence of {} bytes from index {}",
- error_len, self.valid_up_to)
+ write!(
+ f,
+ "invalid utf-8 sequence of {} bytes from index {}",
+ error_len, self.valid_up_to
+ )
} else {
write!(f, "incomplete utf-8 byte sequence from index {}", self.valid_up_to)
}
#[derive(Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Chars<'a> {
- iter: slice::Iter<'a, u8>
+ iter: slice::Iter<'a, u8>,
}
/// Returns the initial codepoint accumulator for the first byte.
/// The first byte is special, only want bottom 5 bits for width 2, 4 bits
/// for width 3, and 3 bits for width 4.
#[inline]
-fn utf8_first_byte(byte: u8, width: u32) -> u32 { (byte & (0x7F >> width)) as u32 }
+fn utf8_first_byte(byte: u8, width: u32) -> u32 {
+ (byte & (0x7F >> width)) as u32
+}
/// Returns the value of `ch` updated with continuation byte `byte`.
#[inline]
-fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 { (ch << 6) | (byte & CONT_MASK) as u32 }
+fn utf8_acc_cont_byte(ch: u32, byte: u8) -> u32 {
+ (ch << 6) | (byte & CONT_MASK) as u32
+}
/// Checks whether the byte is a UTF-8 continuation byte (i.e., starts with the
/// bits `10`).
#[inline]
-fn utf8_is_cont_byte(byte: u8) -> bool { (byte & !CONT_MASK) == TAG_CONT_U8 }
+fn utf8_is_cont_byte(byte: u8) -> bool {
+ (byte & !CONT_MASK) == TAG_CONT_U8
+}
#[inline]
fn unwrap_or_0(opt: Option<&u8>) -> u8 {
/// Reads the next code point out of a byte iterator (assuming a
/// UTF-8-like encoding).
-#[unstable(feature = "str_internals", issue = "0")]
+#[unstable(feature = "str_internals", issue = "none")]
#[inline]
pub fn next_code_point<'a, I: Iterator<Item = &'a u8>>(bytes: &mut I) -> Option<u32> {
// Decode UTF-8
let x = *bytes.next()?;
if x < 128 {
- return Some(x as u32)
+ return Some(x as u32);
}
// Multibyte case follows
/// UTF-8-like encoding).
#[inline]
fn next_code_point_reverse<'a, I>(bytes: &mut I) -> Option<u32>
- where I: DoubleEndedIterator<Item = &'a u8>,
+where
+ I: DoubleEndedIterator<Item = &'a u8>,
{
// Decode UTF-8
let w = match *bytes.next_back()? {
#[inline]
fn next(&mut self) -> Option<char> {
next_code_point(&mut self.iter).map(|ch| {
- // str invariant says `ch` is a valid Unicode Scalar Value
- unsafe {
- char::from_u32_unchecked(ch)
- }
+ // SAFETY: str invariant says `ch` is a valid Unicode Scalar Value
+ unsafe { char::from_u32_unchecked(ch) }
})
}
#[inline]
fn next_back(&mut self) -> Option<char> {
next_code_point_reverse(&mut self.iter).map(|ch| {
- // str invariant says `ch` is a valid Unicode Scalar Value
- unsafe {
- char::from_u32_unchecked(ch)
- }
+ // SAFETY: str invariant says `ch` is a valid Unicode Scalar Value
+ unsafe { char::from_u32_unchecked(ch) }
})
}
}
#[stable(feature = "iter_to_slice", since = "1.4.0")]
#[inline]
pub fn as_str(&self) -> &'a str {
+ // SAFETY: `Chars` is only made from a str, which guarantees the iter is valid utf8
unsafe { from_utf8_unchecked(self.iter.as_slice()) }
}
}
}
#[inline]
- fn all<F>(&mut self, f: F) -> bool where F: FnMut(Self::Item) -> bool {
+ fn all<F>(&mut self, f: F) -> bool
+ where
+ F: FnMut(Self::Item) -> bool,
+ {
self.0.all(f)
}
#[inline]
- fn any<F>(&mut self, f: F) -> bool where F: FnMut(Self::Item) -> bool {
+ fn any<F>(&mut self, f: F) -> bool
+ where
+ F: FnMut(Self::Item) -> bool,
+ {
self.0.any(f)
}
#[inline]
- fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where
- P: FnMut(&Self::Item) -> bool
+ fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
+ where
+ P: FnMut(&Self::Item) -> bool,
{
self.0.find(predicate)
}
#[inline]
- fn position<P>(&mut self, predicate: P) -> Option<usize> where
- P: FnMut(Self::Item) -> bool
+ fn position<P>(&mut self, predicate: P) -> Option<usize>
+ where
+ P: FnMut(Self::Item) -> bool,
{
self.0.position(predicate)
}
#[inline]
- fn rposition<P>(&mut self, predicate: P) -> Option<usize> where
- P: FnMut(Self::Item) -> bool
+ fn rposition<P>(&mut self, predicate: P) -> Option<usize>
+ where
+ P: FnMut(Self::Item) -> bool,
{
self.0.rposition(predicate)
}
}
#[inline]
- fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> where
- P: FnMut(&Self::Item) -> bool
+ fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
+ where
+ P: FnMut(&Self::Item) -> bool,
{
self.0.rfind(predicate)
}
unsafe fn get_unchecked(&mut self, i: usize) -> u8 {
self.0.get_unchecked(i)
}
- fn may_have_side_effect() -> bool { false }
+ fn may_have_side_effect() -> bool {
+ false
+ }
}
/// This macro generates a Clone impl for string pattern API
$e
}
}
- }
+ };
}
/// This macro generates two public iterator structs
} => {}
}
-derive_pattern_clone!{
+derive_pattern_clone! {
clone SplitInternal
with |s| SplitInternal { matcher: s.matcher.clone(), ..*s }
}
fn get_end(&mut self) -> Option<&'a str> {
if !self.finished && (self.allow_trailing_empty || self.end - self.start > 0) {
self.finished = true;
+ // SAFETY: `self.start` and `self.end` always lie on unicode boundaries
unsafe {
let string = self.matcher.haystack().get_unchecked(self.start..self.end);
Some(string)
#[inline]
fn next(&mut self) -> Option<&'a str> {
- if self.finished { return None }
+ if self.finished {
+ return None;
+ }
let haystack = self.matcher.haystack();
match self.matcher.next_match() {
+ // SAFETY: `Searcher` guarantees that `a` and `b` lie on unicode boundaries
Some((a, b)) => unsafe {
let elt = haystack.get_unchecked(self.start..a);
self.start = b;
#[inline]
fn next_back(&mut self) -> Option<&'a str>
- where P::Searcher: ReverseSearcher<'a>
+ where
+ P::Searcher: ReverseSearcher<'a>,
{
- if self.finished { return None }
+ if self.finished {
+ return None;
+ }
if !self.allow_trailing_empty {
self.allow_trailing_empty = true;
match self.next_back() {
Some(elt) if !elt.is_empty() => return Some(elt),
- _ => if self.finished { return None }
+ _ => {
+ if self.finished {
+ return None;
+ }
+ }
}
}
let haystack = self.matcher.haystack();
match self.matcher.next_match_back() {
+ // SAFETY: `Searcher` guarantees that `a` and `b` lie on unicode boundaries
Some((a, b)) => unsafe {
let elt = haystack.get_unchecked(b..self.end);
self.end = a;
Some(elt)
},
+ // SAFETY: `self.start` and `self.end` always lie on unicode boundaries
None => unsafe {
self.finished = true;
Some(haystack.get_unchecked(self.start..self.end))
delegate double ended;
}
-derive_pattern_clone!{
+derive_pattern_clone! {
clone SplitNInternal
with |s| SplitNInternal { iter: s.iter.clone(), ..*s }
}
fn next(&mut self) -> Option<&'a str> {
match self.count {
0 => None,
- 1 => { self.count = 0; self.iter.get_end() }
- _ => { self.count -= 1; self.iter.next() }
+ 1 => {
+ self.count = 0;
+ self.iter.get_end()
+ }
+ _ => {
+ self.count -= 1;
+ self.iter.next()
+ }
}
}
#[inline]
fn next_back(&mut self) -> Option<&'a str>
- where P::Searcher: ReverseSearcher<'a>
+ where
+ P::Searcher: ReverseSearcher<'a>,
{
match self.count {
0 => None,
- 1 => { self.count = 0; self.iter.get_end() }
- _ => { self.count -= 1; self.iter.next_back() }
+ 1 => {
+ self.count = 0;
+ self.iter.get_end()
+ }
+ _ => {
+ self.count -= 1;
+ self.iter.next_back()
+ }
}
}
}
delegate single ended;
}
-derive_pattern_clone!{
+derive_pattern_clone! {
clone MatchIndicesInternal
with |s| MatchIndicesInternal(s.0.clone())
}
P: Pattern<'a, Searcher: fmt::Debug>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_tuple("MatchIndicesInternal")
- .field(&self.0)
- .finish()
+ f.debug_tuple("MatchIndicesInternal").field(&self.0).finish()
}
}
impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> {
#[inline]
fn next(&mut self) -> Option<(usize, &'a str)> {
- self.0.next_match().map(|(start, end)| unsafe {
- (start, self.0.haystack().get_unchecked(start..end))
- })
+ // SAFETY: `Searcher` guaratees that `start` and `end` lie on unicode boundaries
+ self.0
+ .next_match()
+ .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
}
#[inline]
fn next_back(&mut self) -> Option<(usize, &'a str)>
- where P::Searcher: ReverseSearcher<'a>
+ where
+ P::Searcher: ReverseSearcher<'a>,
{
- self.0.next_match_back().map(|(start, end)| unsafe {
- (start, self.0.haystack().get_unchecked(start..end))
- })
+ // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries
+ self.0
+ .next_match_back()
+ .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
}
}
delegate double ended;
}
-derive_pattern_clone!{
+derive_pattern_clone! {
clone MatchesInternal
with |s| MatchesInternal(s.0.clone())
}
P: Pattern<'a, Searcher: fmt::Debug>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_tuple("MatchesInternal")
- .field(&self.0)
- .finish()
+ f.debug_tuple("MatchesInternal").field(&self.0).finish()
}
}
impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> {
#[inline]
fn next(&mut self) -> Option<&'a str> {
+ // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries
self.0.next_match().map(|(a, b)| unsafe {
// Indices are known to be on utf8 boundaries
self.0.haystack().get_unchecked(a..b)
#[inline]
fn next_back(&mut self) -> Option<&'a str>
- where P::Searcher: ReverseSearcher<'a>
+ where
+ P::Searcher: ReverseSearcher<'a>,
{
+ // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries
self.0.next_match_back().map(|(a, b)| unsafe {
// Indices are known to be on utf8 boundaries
self.0.haystack().get_unchecked(a..b)
let old_offset = index;
macro_rules! err {
($error_len: expr) => {
- return Err(Utf8Error {
- valid_up_to: old_offset,
- error_len: $error_len,
- })
- }
+ return Err(Utf8Error { valid_up_to: old_offset, error_len: $error_len });
+ };
}
- macro_rules! next { () => {{
- index += 1;
- // we needed data, but there was none: error!
- if index >= len {
- err!(None)
- }
- v[index]
- }}}
+ macro_rules! next {
+ () => {{
+ index += 1;
+ // we needed data, but there was none: error!
+ if index >= len {
+ err!(None)
+ }
+ v[index]
+ }};
+ }
let first = v[index];
if first >= 128 {
// UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
// %xF4 %x80-8F 2( UTF8-tail )
match w {
- 2 => if next!() & !CONT_MASK != TAG_CONT_U8 {
- err!(Some(1))
- },
+ 2 => {
+ if next!() & !CONT_MASK != TAG_CONT_U8 {
+ err!(Some(1))
+ }
+ }
3 => {
match (first, next!()) {
- (0xE0 , 0xA0 ..= 0xBF) |
- (0xE1 ..= 0xEC, 0x80 ..= 0xBF) |
- (0xED , 0x80 ..= 0x9F) |
- (0xEE ..= 0xEF, 0x80 ..= 0xBF) => {}
- _ => err!(Some(1))
+ (0xE0, 0xA0..=0xBF)
+ | (0xE1..=0xEC, 0x80..=0xBF)
+ | (0xED, 0x80..=0x9F)
+ | (0xEE..=0xEF, 0x80..=0xBF) => {}
+ _ => err!(Some(1)),
}
if next!() & !CONT_MASK != TAG_CONT_U8 {
err!(Some(2))
}
4 => {
match (first, next!()) {
- (0xF0 , 0x90 ..= 0xBF) |
- (0xF1 ..= 0xF3, 0x80 ..= 0xBF) |
- (0xF4 , 0x80 ..= 0x8F) => {}
- _ => err!(Some(1))
+ (0xF0, 0x90..=0xBF) | (0xF1..=0xF3, 0x80..=0xBF) | (0xF4, 0x80..=0x8F) => {}
+ _ => err!(Some(1)),
}
if next!() & !CONT_MASK != TAG_CONT_U8 {
err!(Some(2))
err!(Some(3))
}
}
- _ => err!(Some(1))
+ _ => err!(Some(1)),
}
index += 1;
} else {
if align != usize::max_value() && align.wrapping_sub(index) % usize_bytes == 0 {
let ptr = v.as_ptr();
while index < blocks_end {
+ // SAFETY: since `align - index` and `ascii_block_size` are multiples of
+ // `usize_bytes`, `ptr.add(index)` is always aligned with a `usize` so we
+ // may cast directly to a `const` pointer.
unsafe {
let block = ptr.add(index) as *const usize;
// break if there is a nonascii byte
// https://tools.ietf.org/html/rfc3629
static UTF8_CHAR_WIDTH: [u8; 256] = [
-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F
-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x3F
-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x5F
-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x7F
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0x9F
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0xBF
-0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // 0xDF
-3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, // 0xEF
-4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0, // 0xFF
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, // 0x1F
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, // 0x3F
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, // 0x5F
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, // 0x7F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, // 0x9F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, // 0xBF
+ 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, // 0xDF
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xEF
+ 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xFF
];
/// Given a first byte, determines how many bytes are in this UTF-8 character.
-#[unstable(feature = "str_internals", issue = "0")]
+#[unstable(feature = "str_internals", issue = "none")]
#[inline]
pub fn utf8_char_width(b: u8) -> usize {
UTF8_CHAR_WIDTH[b as usize] as usize
self.as_bytes() == other.as_bytes()
}
#[inline]
- fn ne(&self, other: &str) -> bool { !(*self).eq(other) }
+ fn ne(&self, other: &str) -> bool {
+ !(*self).eq(other)
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
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) {
+ if self.start <= self.end
+ && 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) })
} 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) {
+ if self.start <= self.end
+ && 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_mut(slice) })
} else {
None
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
// is_char_boundary checks that the index is in [0, .len()]
// cannot 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) {
+ if self.start <= self.end
+ && 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) }
} else {
super::slice_error_fail(slice, self.start, self.end)
#[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) })
} 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) })
} else {
None
}
#[inline]
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
- // is_char_boundary checks that the index is in [0, .len()]
if slice.is_char_boundary(self.end) {
+ // SAFETY: just checked that `end` is on a char boundary
unsafe { self.get_unchecked_mut(slice) }
} else {
super::slice_error_fail(slice, 0, self.end)
#[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) })
} 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) })
} else {
None
}
#[inline]
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
- // is_char_boundary checks that the index is in [0, .len()]
if slice.is_char_boundary(self.start) {
+ // SAFETY: just checked that `start` is on a char boundary
unsafe { self.get_unchecked_mut(slice) }
} else {
super::slice_error_fail(slice, self.start, slice.len())
type Output = str;
#[inline]
fn get(self, slice: &str) -> Option<&Self::Output> {
- if *self.end() == usize::max_value() { None }
- else { (*self.start()..self.end()+1).get(slice) }
+ if *self.end() == usize::max_value() {
+ None
+ } else {
+ (*self.start()..self.end() + 1).get(slice)
+ }
}
#[inline]
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
- if *self.end() == usize::max_value() { None }
- else { (*self.start()..self.end()+1).get_mut(slice) }
+ if *self.end() == usize::max_value() {
+ None
+ } else {
+ (*self.start()..self.end() + 1).get_mut(slice)
+ }
}
#[inline]
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
- (*self.start()..self.end()+1).get_unchecked(slice)
+ (*self.start()..self.end() + 1).get_unchecked(slice)
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
- (*self.start()..self.end()+1).get_unchecked_mut(slice)
+ (*self.start()..self.end() + 1).get_unchecked_mut(slice)
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
- if *self.end() == usize::max_value() { str_index_overflow_fail(); }
- (*self.start()..self.end()+1).index(slice)
+ if *self.end() == usize::max_value() {
+ str_index_overflow_fail();
+ }
+ (*self.start()..self.end() + 1).index(slice)
}
#[inline]
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
- if *self.end() == usize::max_value() { str_index_overflow_fail(); }
- (*self.start()..self.end()+1).index_mut(slice)
+ if *self.end() == usize::max_value() {
+ str_index_overflow_fail();
+ }
+ (*self.start()..self.end() + 1).index_mut(slice)
}
}
type Output = str;
#[inline]
fn get(self, slice: &str) -> Option<&Self::Output> {
- if self.end == usize::max_value() { None }
- else { (..self.end+1).get(slice) }
+ if self.end == usize::max_value() { None } else { (..self.end + 1).get(slice) }
}
#[inline]
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
- if self.end == usize::max_value() { None }
- else { (..self.end+1).get_mut(slice) }
+ if self.end == usize::max_value() { None } else { (..self.end + 1).get_mut(slice) }
}
#[inline]
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
- (..self.end+1).get_unchecked(slice)
+ (..self.end + 1).get_unchecked(slice)
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
- (..self.end+1).get_unchecked_mut(slice)
+ (..self.end + 1).get_unchecked_mut(slice)
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
- if self.end == usize::max_value() { str_index_overflow_fail(); }
- (..self.end+1).index(slice)
+ if self.end == usize::max_value() {
+ str_index_overflow_fail();
+ }
+ (..self.end + 1).index(slice)
}
#[inline]
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
- if self.end == usize::max_value() { str_index_overflow_fail(); }
- (..self.end+1).index_mut(slice)
+ if self.end == usize::max_value() {
+ str_index_overflow_fail();
+ }
+ (..self.end + 1).index_mut(slice)
}
}
}
}
// 2. begin <= end
- assert!(begin <= end, "begin <= end ({} <= {}) when slicing `{}`{}",
- begin, end, s_trunc, ellipsis);
+ assert!(
+ begin <= end,
+ "begin <= end ({} <= {}) when slicing `{}`{}",
+ begin,
+ end,
+ s_trunc,
+ ellipsis
+ );
// 3. character boundary
let index = if !s.is_char_boundary(begin) { begin } else { end };
}
// `char_start` must be less than len and a char boundary
let ch = s[char_start..].chars().next().unwrap();
- let char_range = char_start .. char_start + ch.len_utf8();
- panic!("byte index {} is not a char boundary; it is inside {:?} (bytes {:?}) of `{}`{}",
- index, ch, char_range, s_trunc, ellipsis);
+ let char_range = char_start..char_start + ch.len_utf8();
+ panic!(
+ "byte index {} is not a char boundary; it is inside {:?} (bytes {:?}) of `{}`{}",
+ index, ch, char_range, s_trunc, ellipsis
+ );
}
#[lang = "str"]
// 0 and len are always ok.
// Test for 0 explicitly so that it can optimize out the check
// easily and skip reading string data for that case.
- if index == 0 || index == self.len() { return true; }
+ if index == 0 || index == self.len() {
+ return true;
+ }
match self.as_bytes().get(index) {
None => false,
// This is bit magic equivalent to: b < 128 || b >= 192
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")]
#[inline(always)]
- // SAFETY: const sound because we transmute two types with the same layout
#[allow(unused_attributes)]
#[allow_internal_unstable(const_fn_union)]
pub const fn as_bytes(&self) -> &[u8] {
str: &'a str,
slice: &'a [u8],
}
+ // SAFETY: const sound because we transmute two types with the same layout
unsafe { Slices { str: self }.slice }
}
i.get_mut(self)
}
- /// Returns a unchecked subslice of `str`.
+ /// Returns an unchecked subslice of `str`.
///
/// This is the unchecked alternative to indexing the `str`.
///
pub fn split_at(&self, mid: usize) -> (&str, &str) {
// is_char_boundary checks that the index is in [0, .len()]
if self.is_char_boundary(mid) {
- unsafe {
- (self.get_unchecked(0..mid),
- self.get_unchecked(mid..self.len()))
- }
+ // SAFETY: just checked that `mid` is on a char boundary
+ unsafe { (self.get_unchecked(0..mid), self.get_unchecked(mid..self.len())) }
} else {
slice_error_fail(self, 0, mid)
}
if self.is_char_boundary(mid) {
let len = self.len();
let ptr = self.as_mut_ptr();
+ // SAFETY: just checked that `mid` is on a char boundary
unsafe {
- (from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)),
- from_utf8_unchecked_mut(slice::from_raw_parts_mut(
- ptr.add(mid),
- len - mid
- )))
+ (
+ from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)),
+ from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr.add(mid), len - mid)),
+ )
}
} else {
slice_error_fail(self, 0, mid)
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn chars(&self) -> Chars<'_> {
- Chars{iter: self.as_bytes().iter()}
+ Chars { iter: self.as_bytes().iter() }
}
/// Returns an iterator over the [`char`]s of a string slice, and their
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
#[inline]
pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_> {
- let inner = self
- .as_bytes()
- .split(IsAsciiWhitespace)
- .filter(BytesIsNotEmpty)
- .map(UnsafeBytesToStr);
+ let inner =
+ self.as_bytes().split(IsAsciiWhitespace).filter(BytesIsNotEmpty).map(UnsafeBytesToStr);
SplitAsciiWhitespace { inner }
}
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
- SplitTerminator(SplitInternal {
- allow_trailing_empty: false,
- ..self.split(pat).0
- })
+ SplitTerminator(SplitInternal { allow_trailing_empty: false, ..self.split(pat).0 })
}
/// An iterator over substrings of `self`, separated by characters
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> {
- SplitN(SplitNInternal {
- iter: self.split(pat).0,
- count: n,
- })
+ SplitN(SplitNInternal { iter: self.split(pat).0, count: n })
}
/// An iterator over substrings of this string slice, separated by a
#[rustc_deprecated(
since = "1.33.0",
reason = "superseded by `trim_start`",
- suggestion = "trim_start",
+ suggestion = "trim_start"
)]
pub fn trim_left(&self) -> &str {
self.trim_start()
#[rustc_deprecated(
since = "1.33.0",
reason = "superseded by `trim_end`",
- suggestion = "trim_end",
+ suggestion = "trim_end"
)]
pub fn trim_right(&self) -> &str {
self.trim_end()
if let Some((a, b)) = matcher.next_reject() {
i = a;
j = b; // Remember earliest known match, correct it below if
- // last match is different
+ // last match is different
}
if let Some((_, b)) = matcher.next_reject_back() {
j = b;
}
+ // SAFETY: `Searcher` is known to return valid indices
unsafe {
- // Searcher is known to return valid indices
self.get_unchecked(i..j)
}
}
if let Some((a, _)) = matcher.next_reject() {
i = a;
}
+ // SAFETY: `Searcher` is known to return valid indices
unsafe {
- // Searcher is known to return valid indices
self.get_unchecked(i..self.len())
}
}
pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a str> {
let mut matcher = prefix.into_searcher(self);
if let SearchStep::Match(start, len) = matcher.next() {
- debug_assert_eq!(start, 0, "The first search step from Searcher \
- must include the first character");
+ debug_assert_eq!(
+ start, 0,
+ "The first search step from Searcher \
+ must include the first character"
+ );
unsafe {
// Searcher is known to return valid indices.
Some(self.get_unchecked(len..))
{
let mut matcher = suffix.into_searcher(self);
if let SearchStep::Match(start, end) = matcher.next_back() {
- debug_assert_eq!(end, self.len(), "The first search step from ReverseSearcher \
- must include the last character");
+ debug_assert_eq!(
+ end,
+ self.len(),
+ "The first search step from ReverseSearcher \
+ must include the last character"
+ );
unsafe {
// Searcher is known to return valid indices.
Some(self.get_unchecked(..start))
if let Some((_, b)) = matcher.next_reject_back() {
j = b;
}
+ // SAFETY: `Searcher` is known to return valid indices
unsafe {
- // Searcher is known to return valid indices
self.get_unchecked(0..j)
}
}
#[rustc_deprecated(
since = "1.33.0",
reason = "superseded by `trim_start_matches`",
- suggestion = "trim_start_matches",
+ suggestion = "trim_start_matches"
)]
pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
self.trim_start_matches(pat)
#[rustc_deprecated(
since = "1.33.0",
reason = "superseded by `trim_end_matches`",
- suggestion = "trim_end_matches",
+ suggestion = "trim_end_matches"
)]
pub fn trim_right_matches<'a, P>(&'a self, pat: P) -> &'a str
where
/// ```
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
pub fn make_ascii_uppercase(&mut self) {
+ // SAFETY: safe because we transmute two types with the same layout
let me = unsafe { self.as_bytes_mut() };
me.make_ascii_uppercase()
}
/// ```
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
pub fn make_ascii_lowercase(&mut self) {
+ // SAFETY: safe because we transmute two types with the same layout
let me = unsafe { self.as_bytes_mut() };
me.make_ascii_lowercase()
}
pub fn escape_debug(&self) -> EscapeDebug<'_> {
let mut chars = self.chars();
EscapeDebug {
- inner: chars.next()
+ inner: chars
+ .next()
.map(|first| first.escape_debug_ext(true))
.into_iter()
.flatten()
- .chain(chars.flat_map(CharEscapeDebugContinue))
+ .chain(chars.flat_map(CharEscapeDebugContinue)),
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Default for &str {
/// Creates an empty str
- fn default() -> Self { "" }
+ fn default() -> Self {
+ ""
+ }
}
#[stable(feature = "default_mut_str", since = "1.28.0")]
impl Default for &mut str {
/// Creates an empty mutable str
- fn default() -> Self { unsafe { from_utf8_unchecked_mut(&mut []) } }
+ // SAFETY: `str` is guranteed to be UTF-8
+ fn default() -> Self {
+ unsafe { from_utf8_unchecked_mut(&mut []) }
+ }
}
/// An iterator over the non-whitespace substrings of a string,
#[derive(Clone)]
struct UnsafeBytesToStr impl<'a> Fn = |bytes: &'a [u8]| -> &'a str {
+ // SAFETY: not safe
unsafe { from_utf8_unchecked(bytes) }
};
}
pub struct EscapeDebug<'a> {
inner: Chain<
Flatten<option::IntoIter<char::EscapeDebug>>,
- FlatMap<Chars<'a>, char::EscapeDebug, CharEscapeDebugContinue>
+ FlatMap<Chars<'a>, char::EscapeDebug, CharEscapeDebugContinue>,
>,
}