use crate::{
iter::{ConstIntoIter, IsIteratorKind},
string::{self, Pattern, PatternNorm, RSplit, Split},
};
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub const fn split_terminator<'a, 'p, P>(this: &'a str, delim: P) -> SplitTerminator<'a, 'p, P>
where
P: Pattern<'p>,
{
let delim_norm = PatternNorm::new(delim);
SplitTerminator {
inner: string::split(this, delim),
terminator_visited: !string::ends_with(this, delim),
skip_iterating: this.is_empty() && !delim_norm.as_str().is_empty(),
}
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub const fn rsplit_terminator<'a, 'p, P>(this: &'a str, delim: P) -> RSplitTerminator<'a, 'p, P>
where
P: Pattern<'p>,
{
let delim_norm = PatternNorm::new(delim);
RSplitTerminator {
inner: string::rsplit(this, delim),
terminator_visited: !string::ends_with(this, delim),
skip_iterating: this.is_empty() && !delim_norm.as_str().is_empty(),
}
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct SplitTerminator<'a, 'p, P: Pattern<'p>> {
inner: Split<'a, 'p, P>,
terminator_visited: bool,
skip_iterating: bool,
}
impl<'a, 'p, P: Pattern<'p>> ConstIntoIter for SplitTerminator<'a, 'p, P> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a str;
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, 'p, P: Pattern<'p>> SplitTerminator<'a, 'p, P> {
iterator_shared! {
is_forward = true,
item = &'a str,
iter_forward = SplitTerminator<'a, 'p, P>,
next(self){
if self.skip_iterating {
return None
}
let mut ret = self.inner.next();
if self.inner.is_finished() {
if let Some(x) = ret && x.is_empty() && !self.terminator_visited {
ret = None;
}
self.terminator_visited = true;
}
ret
},
fields = {inner.copy(), terminator_visited, skip_iterating},
}
pub const fn remainder(&self) -> &'a str {
self.inner.remainder()
}
}
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iter")))]
pub struct RSplitTerminator<'a, 'p, P: Pattern<'p>> {
inner: RSplit<'a, 'p, P>,
terminator_visited: bool,
skip_iterating: bool,
}
impl<'a, 'p, P: Pattern<'p>> ConstIntoIter for RSplitTerminator<'a, 'p, P> {
type Kind = IsIteratorKind;
type IntoIter = Self;
type Item = &'a str;
const ITEMS_NEED_DROP: bool = false;
}
impl<'a, 'p, P: Pattern<'p>> RSplitTerminator<'a, 'p, P> {
iterator_shared! {
is_forward = true,
item = &'a str,
iter_forward = RSplitTerminator<'a, 'p, P>,
next(self) {
if self.skip_iterating {
return None
}
if !self.terminator_visited {
_ = self.inner.next();
self.terminator_visited = true;
}
self.inner.next()
},
fields = {inner.copy(), terminator_visited, skip_iterating},
}
pub const fn remainder(&self) -> &'a str {
self.inner.remainder()
}
}