use crate::char as char_mod;
use crate::fmt::{self, Write};
use crate::iter::{Chain, FlatMap, Flatten};
use crate::iter::{Copied, Filter, FusedIterator, Map, TrustedLen};
use crate::iter::{TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use crate::ops::Try;
use crate::option;
use crate::slice::{self, Split as SliceSplit};
use super::from_utf8_unchecked;
use super::pattern::Pattern;
use super::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher};
use super::validations::{next_code_point, next_code_point_reverse};
use super::LinesMap;
use super::{BytesIsNotEmpty, UnsafeBytesToStr};
use super::{CharEscapeDebugContinue, CharEscapeDefault, CharEscapeUnicode};
use super::{IsAsciiWhitespace, IsNotEmpty, IsWhitespace};
#[derive(Clone)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Chars<'a> {
pub(super) iter: slice::Iter<'a, u8>,
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Iterator for Chars<'a> {
type Item = char;
#[inline]
fn next(&mut self) -> Option<char> {
unsafe { next_code_point(&mut self.iter).map(|ch| char::from_u32_unchecked(ch)) }
}
#[inline]
fn count(self) -> usize {
super::count::count_chars(self.as_str())
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.iter.len();
((len + 3) / 4, Some(len))
}
#[inline]
fn last(mut self) -> Option<char> {
self.next_back()
}
}
#[stable(feature = "chars_debug_impl", since = "1.38.0")]
impl fmt::Debug for Chars<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Chars(")?;
f.debug_list().entries(self.clone()).finish()?;
write!(f, ")")?;
Ok(())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> DoubleEndedIterator for Chars<'a> {
#[inline]
fn next_back(&mut self) -> Option<char> {
unsafe { next_code_point_reverse(&mut self.iter).map(|ch| char::from_u32_unchecked(ch)) }
}
}
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for Chars<'_> {}
impl<'a> Chars<'a> {
#[stable(feature = "iter_to_slice", since = "1.4.0")]
#[must_use]
#[inline]
pub fn as_str(&self) -> &'a str {
unsafe { from_utf8_unchecked(self.iter.as_slice()) }
}
}
#[derive(Clone, Debug)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CharIndices<'a> {
pub(super) front_offset: usize,
pub(super) iter: Chars<'a>,
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Iterator for CharIndices<'a> {
type Item = (usize, char);
#[inline]
fn next(&mut self) -> Option<(usize, char)> {
let pre_len = self.iter.iter.len();
match self.iter.next() {
None => None,
Some(ch) => {
let index = self.front_offset;
let len = self.iter.iter.len();
self.front_offset += pre_len - len;
Some((index, ch))
}
}
}
#[inline]
fn count(self) -> usize {
self.iter.count()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
#[inline]
fn last(mut self) -> Option<(usize, char)> {
self.next_back()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> DoubleEndedIterator for CharIndices<'a> {
#[inline]
fn next_back(&mut self) -> Option<(usize, char)> {
self.iter.next_back().map(|ch| {
let index = self.front_offset + self.iter.iter.len();
(index, ch)
})
}
}
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for CharIndices<'_> {}
impl<'a> CharIndices<'a> {
#[stable(feature = "iter_to_slice", since = "1.4.0")]
#[must_use]
#[inline]
pub fn as_str(&self) -> &'a str {
self.iter.as_str()
}
#[inline]
#[must_use]
#[unstable(feature = "char_indices_offset", issue = "83871")]
pub fn offset(&self) -> usize {
self.front_offset
}
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone, Debug)]
pub struct Bytes<'a>(pub(super) Copied<slice::Iter<'a, u8>>);
#[stable(feature = "rust1", since = "1.0.0")]
impl Iterator for Bytes<'_> {
type Item = u8;
#[inline]
fn next(&mut self) -> Option<u8> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
#[inline]
fn count(self) -> usize {
self.0.count()
}
#[inline]
fn last(self) -> Option<Self::Item> {
self.0.last()
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.0.nth(n)
}
#[inline]
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,
{
self.0.any(f)
}
#[inline]
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,
{
self.0.position(predicate)
}
#[inline]
fn rposition<P>(&mut self, predicate: P) -> Option<usize>
where
P: FnMut(Self::Item) -> bool,
{
self.0.rposition(predicate)
}
#[inline]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> u8 {
unsafe { self.0.__iterator_get_unchecked(idx) }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl DoubleEndedIterator for Bytes<'_> {
#[inline]
fn next_back(&mut self) -> Option<u8> {
self.0.next_back()
}
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
self.0.nth_back(n)
}
#[inline]
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
where
P: FnMut(&Self::Item) -> bool,
{
self.0.rfind(predicate)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl ExactSizeIterator for Bytes<'_> {
#[inline]
fn len(&self) -> usize {
self.0.len()
}
#[inline]
fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for Bytes<'_> {}
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl TrustedLen for Bytes<'_> {}
#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
unsafe impl TrustedRandomAccess for Bytes<'_> {}
#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
unsafe impl TrustedRandomAccessNoCoerce for Bytes<'_> {
const MAY_HAVE_SIDE_EFFECT: bool = false;
}
macro_rules! derive_pattern_clone {
(clone $t:ident with |$s:ident| $e:expr) => {
impl<'a, P> Clone for $t<'a, P>
where
P: Pattern<'a, Searcher: Clone>,
{
fn clone(&self) -> Self {
let $s = self;
$e
}
}
};
}
macro_rules! generate_pattern_iterators {
{
forward:
$(#[$forward_iterator_attribute:meta])*
struct $forward_iterator:ident;
reverse:
$(#[$reverse_iterator_attribute:meta])*
struct $reverse_iterator:ident;
stability:
$(#[$common_stability_attribute:meta])*
internal:
$internal_iterator:ident yielding ($iterty:ty);
delegate $($t:tt)*
} => {
$(#[$forward_iterator_attribute])*
$(#[$common_stability_attribute])*
pub struct $forward_iterator<'a, P: Pattern<'a>>(pub(super) $internal_iterator<'a, P>);
$(#[$common_stability_attribute])*
impl<'a, P> fmt::Debug for $forward_iterator<'a, P>
where
P: Pattern<'a, Searcher: fmt::Debug>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple(stringify!($forward_iterator))
.field(&self.0)
.finish()
}
}
$(#[$common_stability_attribute])*
impl<'a, P: Pattern<'a>> Iterator for $forward_iterator<'a, P> {
type Item = $iterty;
#[inline]
fn next(&mut self) -> Option<$iterty> {
self.0.next()
}
}
$(#[$common_stability_attribute])*
impl<'a, P> Clone for $forward_iterator<'a, P>
where
P: Pattern<'a, Searcher: Clone>,
{
fn clone(&self) -> Self {
$forward_iterator(self.0.clone())
}
}
$(#[$reverse_iterator_attribute])*
$(#[$common_stability_attribute])*
pub struct $reverse_iterator<'a, P: Pattern<'a>>(pub(super) $internal_iterator<'a, P>);
$(#[$common_stability_attribute])*
impl<'a, P> fmt::Debug for $reverse_iterator<'a, P>
where
P: Pattern<'a, Searcher: fmt::Debug>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple(stringify!($reverse_iterator))
.field(&self.0)
.finish()
}
}
$(#[$common_stability_attribute])*
impl<'a, P> Iterator for $reverse_iterator<'a, P>
where
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
{
type Item = $iterty;
#[inline]
fn next(&mut self) -> Option<$iterty> {
self.0.next_back()
}
}
$(#[$common_stability_attribute])*
impl<'a, P> Clone for $reverse_iterator<'a, P>
where
P: Pattern<'a, Searcher: Clone>,
{
fn clone(&self) -> Self {
$reverse_iterator(self.0.clone())
}
}
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, P: Pattern<'a>> FusedIterator for $forward_iterator<'a, P> {}
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, P> FusedIterator for $reverse_iterator<'a, P>
where
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
{}
generate_pattern_iterators!($($t)* with $(#[$common_stability_attribute])*,
$forward_iterator,
$reverse_iterator, $iterty);
};
{
double ended; with $(#[$common_stability_attribute:meta])*,
$forward_iterator:ident,
$reverse_iterator:ident, $iterty:ty
} => {
$(#[$common_stability_attribute])*
impl<'a, P> DoubleEndedIterator for $forward_iterator<'a, P>
where
P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>,
{
#[inline]
fn next_back(&mut self) -> Option<$iterty> {
self.0.next_back()
}
}
$(#[$common_stability_attribute])*
impl<'a, P> DoubleEndedIterator for $reverse_iterator<'a, P>
where
P: Pattern<'a, Searcher: DoubleEndedSearcher<'a>>,
{
#[inline]
fn next_back(&mut self) -> Option<$iterty> {
self.0.next()
}
}
};
{
single ended; with $(#[$common_stability_attribute:meta])*,
$forward_iterator:ident,
$reverse_iterator:ident, $iterty:ty
} => {}
}
derive_pattern_clone! {
clone SplitInternal
with |s| SplitInternal { matcher: s.matcher.clone(), ..*s }
}
pub(super) struct SplitInternal<'a, P: Pattern<'a>> {
pub(super) start: usize,
pub(super) end: usize,
pub(super) matcher: P::Searcher,
pub(super) allow_trailing_empty: bool,
pub(super) finished: bool,
}
impl<'a, P> fmt::Debug for SplitInternal<'a, P>
where
P: Pattern<'a, Searcher: fmt::Debug>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SplitInternal")
.field("start", &self.start)
.field("end", &self.end)
.field("matcher", &self.matcher)
.field("allow_trailing_empty", &self.allow_trailing_empty)
.field("finished", &self.finished)
.finish()
}
}
impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
#[inline]
fn get_end(&mut self) -> Option<&'a str> {
if !self.finished {
self.finished = true;
if self.allow_trailing_empty || self.end - self.start > 0 {
let string = unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) };
return Some(string);
}
}
None
}
#[inline]
fn next(&mut self) -> Option<&'a str> {
if self.finished {
return None;
}
let haystack = self.matcher.haystack();
match self.matcher.next_match() {
Some((a, b)) => unsafe {
let elt = haystack.get_unchecked(self.start..a);
self.start = b;
Some(elt)
},
None => self.get_end(),
}
}
#[inline]
fn next_inclusive(&mut self) -> Option<&'a str> {
if self.finished {
return None;
}
let haystack = self.matcher.haystack();
match self.matcher.next_match() {
Some((_, b)) => unsafe {
let elt = haystack.get_unchecked(self.start..b);
self.start = b;
Some(elt)
},
None => self.get_end(),
}
}
#[inline]
fn next_back(&mut self) -> Option<&'a str>
where
P::Searcher: ReverseSearcher<'a>,
{
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;
}
}
}
}
let haystack = self.matcher.haystack();
match self.matcher.next_match_back() {
Some((a, b)) => unsafe {
let elt = haystack.get_unchecked(b..self.end);
self.end = a;
Some(elt)
},
None => unsafe {
self.finished = true;
Some(haystack.get_unchecked(self.start..self.end))
},
}
}
#[inline]
fn next_back_inclusive(&mut self) -> Option<&'a str>
where
P::Searcher: ReverseSearcher<'a>,
{
if self.finished {
return None;
}
if !self.allow_trailing_empty {
self.allow_trailing_empty = true;
match self.next_back_inclusive() {
Some(elt) if !elt.is_empty() => return Some(elt),
_ => {
if self.finished {
return None;
}
}
}
}
let haystack = self.matcher.haystack();
match self.matcher.next_match_back() {
Some((_, b)) => unsafe {
let elt = haystack.get_unchecked(b..self.end);
self.end = b;
Some(elt)
},
None => unsafe {
self.finished = true;
Some(haystack.get_unchecked(self.start..self.end))
},
}
}
#[inline]
fn remainder(&self) -> Option<&'a str> {
if self.finished {
return None;
}
Some(unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) })
}
}
generate_pattern_iterators! {
forward:
struct Split;
reverse:
struct RSplit;
stability:
#[stable(feature = "rust1", since = "1.0.0")]
internal:
SplitInternal yielding (&'a str);
delegate double ended;
}
impl<'a, P: Pattern<'a>> Split<'a, P> {
#[inline]
#[unstable(feature = "str_split_remainder", issue = "77998")]
pub fn remainder(&self) -> Option<&'a str> {
self.0.remainder()
}
}
impl<'a, P: Pattern<'a>> RSplit<'a, P> {
#[inline]
#[unstable(feature = "str_split_remainder", issue = "77998")]
pub fn remainder(&self) -> Option<&'a str> {
self.0.remainder()
}
}
generate_pattern_iterators! {
forward:
struct SplitTerminator;
reverse:
struct RSplitTerminator;
stability:
#[stable(feature = "rust1", since = "1.0.0")]
internal:
SplitInternal yielding (&'a str);
delegate double ended;
}
impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> {
#[inline]
#[unstable(feature = "str_split_remainder", issue = "77998")]
pub fn remainder(&self) -> Option<&'a str> {
self.0.remainder()
}
}
impl<'a, P: Pattern<'a>> RSplitTerminator<'a, P> {
#[inline]
#[unstable(feature = "str_split_remainder", issue = "77998")]
pub fn remainder(&self) -> Option<&'a str> {
self.0.remainder()
}
}
derive_pattern_clone! {
clone SplitNInternal
with |s| SplitNInternal { iter: s.iter.clone(), ..*s }
}
pub(super) struct SplitNInternal<'a, P: Pattern<'a>> {
pub(super) iter: SplitInternal<'a, P>,
pub(super) count: usize,
}
impl<'a, P> fmt::Debug for SplitNInternal<'a, P>
where
P: Pattern<'a, Searcher: fmt::Debug>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SplitNInternal")
.field("iter", &self.iter)
.field("count", &self.count)
.finish()
}
}
impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> {
#[inline]
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()
}
}
}
#[inline]
fn next_back(&mut self) -> Option<&'a str>
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()
}
}
}
#[inline]
fn remainder(&self) -> Option<&'a str> {
self.iter.remainder()
}
}
generate_pattern_iterators! {
forward:
struct SplitN;
reverse:
struct RSplitN;
stability:
#[stable(feature = "rust1", since = "1.0.0")]
internal:
SplitNInternal yielding (&'a str);
delegate single ended;
}
impl<'a, P: Pattern<'a>> SplitN<'a, P> {
#[inline]
#[unstable(feature = "str_split_remainder", issue = "77998")]
pub fn remainder(&self) -> Option<&'a str> {
self.0.remainder()
}
}
impl<'a, P: Pattern<'a>> RSplitN<'a, P> {
#[inline]
#[unstable(feature = "str_split_remainder", issue = "77998")]
pub fn remainder(&self) -> Option<&'a str> {
self.0.remainder()
}
}
derive_pattern_clone! {
clone MatchIndicesInternal
with |s| MatchIndicesInternal(s.0.clone())
}
pub(super) struct MatchIndicesInternal<'a, P: Pattern<'a>>(pub(super) P::Searcher);
impl<'a, P> fmt::Debug for MatchIndicesInternal<'a, P>
where
P: Pattern<'a, Searcher: fmt::Debug>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
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)) })
}
#[inline]
fn next_back(&mut self) -> Option<(usize, &'a str)>
where
P::Searcher: ReverseSearcher<'a>,
{
self.0
.next_match_back()
.map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
}
}
generate_pattern_iterators! {
forward:
struct MatchIndices;
reverse:
struct RMatchIndices;
stability:
#[stable(feature = "str_match_indices", since = "1.5.0")]
internal:
MatchIndicesInternal yielding ((usize, &'a str));
delegate double ended;
}
derive_pattern_clone! {
clone MatchesInternal
with |s| MatchesInternal(s.0.clone())
}
pub(super) struct MatchesInternal<'a, P: Pattern<'a>>(pub(super) P::Searcher);
impl<'a, P> fmt::Debug for MatchesInternal<'a, P>
where
P: Pattern<'a, Searcher: fmt::Debug>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("MatchesInternal").field(&self.0).finish()
}
}
impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> {
#[inline]
fn next(&mut self) -> Option<&'a str> {
self.0.next_match().map(|(a, b)| unsafe {
self.0.haystack().get_unchecked(a..b)
})
}
#[inline]
fn next_back(&mut self) -> Option<&'a str>
where
P::Searcher: ReverseSearcher<'a>,
{
self.0.next_match_back().map(|(a, b)| unsafe {
self.0.haystack().get_unchecked(a..b)
})
}
}
generate_pattern_iterators! {
forward:
struct Matches;
reverse:
struct RMatches;
stability:
#[stable(feature = "str_matches", since = "1.2.0")]
internal:
MatchesInternal yielding (&'a str);
delegate double ended;
}
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Clone, Debug)]
pub struct Lines<'a>(pub(super) Map<SplitInclusive<'a, char>, LinesMap>);
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Iterator for Lines<'a> {
type Item = &'a str;
#[inline]
fn next(&mut self) -> Option<&'a str> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
#[inline]
fn last(mut self) -> Option<&'a str> {
self.next_back()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> DoubleEndedIterator for Lines<'a> {
#[inline]
fn next_back(&mut self) -> Option<&'a str> {
self.0.next_back()
}
}
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for Lines<'_> {}
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.4.0", note = "use lines()/Lines instead now")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Clone, Debug)]
#[allow(deprecated)]
pub struct LinesAny<'a>(pub(super) Lines<'a>);
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl<'a> Iterator for LinesAny<'a> {
type Item = &'a str;
#[inline]
fn next(&mut self) -> Option<&'a str> {
self.0.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl<'a> DoubleEndedIterator for LinesAny<'a> {
#[inline]
fn next_back(&mut self) -> Option<&'a str> {
self.0.next_back()
}
}
#[stable(feature = "fused", since = "1.26.0")]
#[allow(deprecated)]
impl FusedIterator for LinesAny<'_> {}
#[stable(feature = "split_whitespace", since = "1.1.0")]
#[derive(Clone, Debug)]
pub struct SplitWhitespace<'a> {
pub(super) inner: Filter<Split<'a, IsWhitespace>, IsNotEmpty>,
}
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
#[derive(Clone, Debug)]
pub struct SplitAsciiWhitespace<'a> {
pub(super) inner:
Map<Filter<SliceSplit<'a, u8, IsAsciiWhitespace>, BytesIsNotEmpty>, UnsafeBytesToStr>,
}
#[stable(feature = "split_inclusive", since = "1.51.0")]
pub struct SplitInclusive<'a, P: Pattern<'a>>(pub(super) SplitInternal<'a, P>);
#[stable(feature = "split_whitespace", since = "1.1.0")]
impl<'a> Iterator for SplitWhitespace<'a> {
type Item = &'a str;
#[inline]
fn next(&mut self) -> Option<&'a str> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
#[inline]
fn last(mut self) -> Option<&'a str> {
self.next_back()
}
}
#[stable(feature = "split_whitespace", since = "1.1.0")]
impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
#[inline]
fn next_back(&mut self) -> Option<&'a str> {
self.inner.next_back()
}
}
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for SplitWhitespace<'_> {}
impl<'a> SplitWhitespace<'a> {
#[inline]
#[must_use]
#[unstable(feature = "str_split_whitespace_remainder", issue = "77998")]
pub fn remainder(&self) -> Option<&'a str> {
self.inner.iter.remainder()
}
}
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
impl<'a> Iterator for SplitAsciiWhitespace<'a> {
type Item = &'a str;
#[inline]
fn next(&mut self) -> Option<&'a str> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
#[inline]
fn last(mut self) -> Option<&'a str> {
self.next_back()
}
}
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a> {
#[inline]
fn next_back(&mut self) -> Option<&'a str> {
self.inner.next_back()
}
}
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
impl FusedIterator for SplitAsciiWhitespace<'_> {}
impl<'a> SplitAsciiWhitespace<'a> {
#[inline]
#[must_use]
#[unstable(feature = "str_split_whitespace_remainder", issue = "77998")]
pub fn remainder(&self) -> Option<&'a str> {
if self.inner.iter.iter.finished {
return None;
}
Some(unsafe { crate::str::from_utf8_unchecked(&self.inner.iter.iter.v) })
}
}
#[stable(feature = "split_inclusive", since = "1.51.0")]
impl<'a, P: Pattern<'a>> Iterator for SplitInclusive<'a, P> {
type Item = &'a str;
#[inline]
fn next(&mut self) -> Option<&'a str> {
self.0.next_inclusive()
}
}
#[stable(feature = "split_inclusive", since = "1.51.0")]
impl<'a, P: Pattern<'a, Searcher: fmt::Debug>> fmt::Debug for SplitInclusive<'a, P> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SplitInclusive").field("0", &self.0).finish()
}
}
#[stable(feature = "split_inclusive", since = "1.51.0")]
impl<'a, P: Pattern<'a, Searcher: Clone>> Clone for SplitInclusive<'a, P> {
fn clone(&self) -> Self {
SplitInclusive(self.0.clone())
}
}
#[stable(feature = "split_inclusive", since = "1.51.0")]
impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator
for SplitInclusive<'a, P>
{
#[inline]
fn next_back(&mut self) -> Option<&'a str> {
self.0.next_back_inclusive()
}
}
#[stable(feature = "split_inclusive", since = "1.51.0")]
impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {}
impl<'a, P: Pattern<'a>> SplitInclusive<'a, P> {
#[inline]
#[unstable(feature = "str_split_inclusive_remainder", issue = "77998")]
pub fn remainder(&self) -> Option<&'a str> {
self.0.remainder()
}
}
#[derive(Clone)]
#[stable(feature = "encode_utf16", since = "1.8.0")]
pub struct EncodeUtf16<'a> {
pub(super) chars: Chars<'a>,
pub(super) extra: u16,
}
#[stable(feature = "collection_debug", since = "1.17.0")]
impl fmt::Debug for EncodeUtf16<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EncodeUtf16").finish_non_exhaustive()
}
}
#[stable(feature = "encode_utf16", since = "1.8.0")]
impl<'a> Iterator for EncodeUtf16<'a> {
type Item = u16;
#[inline]
fn next(&mut self) -> Option<u16> {
if self.extra != 0 {
let tmp = self.extra;
self.extra = 0;
return Some(tmp);
}
let mut buf = [0; 2];
self.chars.next().map(|ch| {
let n = ch.encode_utf16(&mut buf).len();
if n == 2 {
self.extra = buf[1];
}
buf[0]
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, high) = self.chars.size_hint();
(low, high.and_then(|n| n.checked_mul(2)))
}
}
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for EncodeUtf16<'_> {}
#[stable(feature = "str_escape", since = "1.34.0")]
#[derive(Clone, Debug)]
pub struct EscapeDebug<'a> {
pub(super) inner: Chain<
Flatten<option::IntoIter<char_mod::EscapeDebug>>,
FlatMap<Chars<'a>, char_mod::EscapeDebug, CharEscapeDebugContinue>,
>,
}
#[stable(feature = "str_escape", since = "1.34.0")]
#[derive(Clone, Debug)]
pub struct EscapeDefault<'a> {
pub(super) inner: FlatMap<Chars<'a>, char_mod::EscapeDefault, CharEscapeDefault>,
}
#[stable(feature = "str_escape", since = "1.34.0")]
#[derive(Clone, Debug)]
pub struct EscapeUnicode<'a> {
pub(super) inner: FlatMap<Chars<'a>, char_mod::EscapeUnicode, CharEscapeUnicode>,
}
macro_rules! escape_types_impls {
($( $Name: ident ),+) => {$(
#[stable(feature = "str_escape", since = "1.34.0")]
impl<'a> fmt::Display for $Name<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.clone().try_for_each(|c| f.write_char(c))
}
}
#[stable(feature = "str_escape", since = "1.34.0")]
impl<'a> Iterator for $Name<'a> {
type Item = char;
#[inline]
fn next(&mut self) -> Option<char> { self.inner.next() }
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
#[inline]
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Output = Acc>
{
self.inner.try_fold(init, fold)
}
#[inline]
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
self.inner.fold(init, fold)
}
}
#[stable(feature = "str_escape", since = "1.34.0")]
impl<'a> FusedIterator for $Name<'a> {}
)+}
}
escape_types_impls!(EscapeDebug, EscapeDefault, EscapeUnicode);