use core::iter::FusedIterator;
use core::{fmt, mem};
pub struct SplitInclusiveMut<'a, T, P>
where P: FnMut(&T) -> bool
{
v: &'a mut [T],
pred: P,
finished: bool,
}
impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitInclusiveMut<'a, T, P> {
pub(super) fn new(slice: &'a mut [T], pred: P) -> Self {
Self { v: slice, pred, finished: false }
}
}
impl<T: fmt::Debug, P> fmt::Debug for SplitInclusiveMut<'_, T, P>
where P: FnMut(&T) -> bool
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SplitInclusiveMut")
.field("v", &self.v)
.field("finished", &self.finished)
.finish()
}
}
impl<'a, T, P> Iterator for SplitInclusiveMut<'a, T, P>
where P: FnMut(&T) -> bool
{
type Item = &'a mut [T];
fn next(&mut self) -> Option<&'a mut [T]> {
if self.finished {
return None;
}
let idx_opt = {
let pred = &mut self.pred;
self.v.iter().position(|x| (*pred)(x))
};
let idx = idx_opt.map(|idx| idx + 1).unwrap_or(self.v.len());
if idx == self.v.len() {
self.finished = true;
}
let tmp = mem::replace(&mut self.v, &mut []);
let (head, tail) = tmp.split_at_mut(idx);
self.v = tail;
Some(head)
}
fn size_hint(&self) -> (usize, Option<usize>) {
if self.finished { (0, Some(0)) } else { (1, Some(self.v.len() + 1)) }
}
}
impl<'a, T, P> DoubleEndedIterator for SplitInclusiveMut<'a, T, P>
where P: FnMut(&T) -> bool
{
fn next_back(&mut self) -> Option<&'a mut [T]> {
if self.finished {
return None;
}
let idx_opt = if self.v.is_empty() {
None
} else {
let pred = &mut self.pred;
let remainder = &self.v[..(self.v.len() - 1)];
remainder.iter().rposition(|x| (*pred)(x))
};
let idx = idx_opt.map(|idx| idx + 1).unwrap_or(0);
if idx == 0 {
self.finished = true;
}
let tmp = mem::replace(&mut self.v, &mut []);
let (head, tail) = tmp.split_at_mut(idx);
self.v = head;
Some(tail)
}
}
impl<T, P> FusedIterator for SplitInclusiveMut<'_, T, P> where P: FnMut(&T) -> bool {}
pub struct SplitInclusive<'a, T, P>
where P: FnMut(&T) -> bool
{
v: &'a [T],
pred: P,
finished: bool,
}
impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitInclusive<'a, T, P> {
pub(super) fn new(slice: &'a [T], pred: P) -> Self {
Self { v: slice, pred, finished: false }
}
}
impl<T: fmt::Debug, P> fmt::Debug for SplitInclusive<'_, T, P>
where P: FnMut(&T) -> bool
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SplitInclusive")
.field("v", &self.v)
.field("finished", &self.finished)
.finish()
}
}
impl<T, P> Clone for SplitInclusive<'_, T, P>
where P: Clone + FnMut(&T) -> bool
{
fn clone(&self) -> Self {
SplitInclusive { v: self.v, pred: self.pred.clone(), finished: self.finished }
}
}
impl<'a, T, P> Iterator for SplitInclusive<'a, T, P>
where P: FnMut(&T) -> bool
{
type Item = &'a [T];
fn next(&mut self) -> Option<&'a [T]> {
if self.finished {
return None;
}
let idx =
self.v.iter().position(|x| (self.pred)(x)).map(|idx| idx + 1).unwrap_or(self.v.len());
if idx == self.v.len() {
self.finished = true;
}
let ret = Some(&self.v[..idx]);
self.v = &self.v[idx..];
ret
}
fn size_hint(&self) -> (usize, Option<usize>) {
if self.finished { (0, Some(0)) } else { (1, Some(self.v.len() + 1)) }
}
}
impl<'a, T, P> DoubleEndedIterator for SplitInclusive<'a, T, P>
where P: FnMut(&T) -> bool
{
fn next_back(&mut self) -> Option<&'a [T]> {
if self.finished {
return None;
}
let remainder = if self.v.is_empty() { &[] } else { &self.v[..(self.v.len() - 1)] };
let idx = remainder.iter().rposition(|x| (self.pred)(x)).map(|idx| idx + 1).unwrap_or(0);
if idx == 0 {
self.finished = true;
}
let ret = Some(&self.v[idx..]);
self.v = &self.v[..idx];
ret
}
}
impl<T, P> FusedIterator for SplitInclusive<'_, T, P> where P: FnMut(&T) -> bool {}