use super::{BacktrackingState, Record, ReferencingBacktrackingIterator, CopyingBacktrackingIterator};
use self::BacktrackingState::{Progressing, Backtracking};
pub struct BacktrackingRecorder<Iter> where Iter: Iterator {
pub(crate) iterator: Iter,
pub(crate) backtracking_vec: Vec<Iter::Item>,
pub(crate) state: BacktrackingState,
}
impl<Iter> BacktrackingRecorder<Iter> where Iter: Iterator {
pub fn new(iterator: Iter) -> Self {
BacktrackingRecorder {
iterator,
backtracking_vec: vec![],
state: Progressing,
}
}
pub fn referencing<'record>(&'record mut self) -> ReferencingBacktrackingIterator<'record, Iter> {
ReferencingBacktrackingIterator::new(self)
}
pub fn copying<'record>(&'record mut self) -> CopyingBacktrackingIterator<'record, Iter> where Iter::Item: Clone {
CopyingBacktrackingIterator::new(self)
}
pub fn drain_history(&mut self) -> Vec<Iter::Item> {
self.backtracking_vec.drain(..).collect()
}
}
impl<Iter, Item> IntoIterator for BacktrackingRecorder<Iter> where Iter: Iterator<Item=Item> + IntoIterator<Item=Item> {
type Item = Item;
type IntoIter = std::iter::Chain<std::vec::IntoIter<Item>, Iter::IntoIter>;
fn into_iter(self) -> Self::IntoIter {
self.backtracking_vec.into_iter().chain(self.iterator)
}
}
impl<Iter> Record for BacktrackingRecorder<Iter> where Iter: Iterator {
type RefPoint = usize;
fn get_ref_point(&self) -> usize {
match self.state {
Progressing => self.backtracking_vec.len(),
Backtracking { position } => position,
}
}
fn forget_before(&mut self, position: usize) {
if position <= self.backtracking_vec.len() {
let kept = self.backtracking_vec.split_off(position);
self.backtracking_vec = kept;
}
}
fn forget(&mut self) {
self.backtracking_vec.clear();
}
}