use crate::{StringIter, pattern::{Pattern, Never, PatRef, Sep}, prelude::SetSep};
struct SplitGuardFirst<P: Pattern>{
flag: bool,
pat: P,
}
impl<P: Pattern> SplitGuardFirst<P> {
fn new(pat: P) -> Self{
Self {
flag: !pat.sep().is_retained(),
pat
}
}
}
impl<P: Pattern> Pattern for SplitGuardFirst<P> {
type Err = P::Err;
fn matches(&mut self, c: char, s: &str) -> Result<bool, Self::Err> {
if self.flag == false {
let _ = self.pat.matches(c, s);
self.flag = true;
Ok(false)
} else {
self.pat.matches(c, s)
}
}
fn len(&self) -> core::num::NonZeroUsize { self.pat.len() }
fn sep(&self) -> crate::pattern::Sep { self.pat.sep() }
}
struct SplitGuard<P: Pattern>{
flag: bool,
pat: P,
}
impl<P: Pattern> SplitGuard<P> {
fn new(pat: P) -> Self{
Self {
flag: !pat.sep().is_retained(),
pat
}
}
}
impl<P: Pattern> Pattern for SplitGuard<P> {
type Err = P::Err;
fn matches(&mut self, c: char, s: &str) -> Result<bool, Self::Err> {
if self.flag == false {
self.flag = true;
Ok(false)
} else {
self.pat.matches(c, s)
}
}
fn len(&self) -> core::num::NonZeroUsize { self.pat.len() }
fn sep(&self) -> crate::pattern::Sep { self.pat.sep() }
}
impl<'t> StringIter<'t> {
pub fn into_substrs(self, pat: impl Pattern<Err=Never>) -> SplitIter<'t, impl Pattern<Err=Never>>{
if pat.sep() == Sep::Conjoin {
panic!("Cannot safely split with the conjoined pattern.");
}
SplitIter { str: self, pat, count: 0 }
}
pub fn into_splits(self, pat: impl Pattern<Err = Never>) -> SplitIter<'t, impl Pattern<Err = Never>>{
SplitIter { str: self, pat: pat.sep_with(Sep::Split), count: 0 }
}
}
#[derive(Debug, Clone)]
pub struct SplitIter<'t, F: Pattern<Err = Never>>{
pub(crate) str: StringIter<'t>,
pub(crate) pat: F,
pub(crate) count: usize,
}
impl<'t, F> Iterator for SplitIter<'t, F> where F: Pattern<Err = Never>{
type Item = &'t str;
fn next(&mut self) -> Option<Self::Item> {
let pat = PatRef(&mut self.pat);
if self.count == 0 {
self.count += 1;
self.str.next_slice(SplitGuardFirst::new(pat))
} else {
self.count += 1;
self.str.next_slice(SplitGuard::new(pat))
}
}
}
impl<'t, F> DoubleEndedIterator for SplitIter<'t, F> where F: Pattern<Err = Never>{
fn next_back(&mut self) -> Option<Self::Item> {
let pat = PatRef(&mut self.pat);
if self.count == 0 {
self.count += 1;
self.str.next_slice_back(SplitGuardFirst::new(pat))
} else {
self.count += 1;
self.str.next_slice_back(SplitGuard::new(pat))
}
}
}