use super::BacktrackingRecorder;
use super::BacktrackingState::*;
pub struct ReferencingBacktrackingIterator<'record, Iter> where Iter: Iterator {
recorder: &'record mut BacktrackingRecorder<Iter>,
}
impl<'record, Iter> ReferencingBacktrackingIterator<'record, Iter> where Iter: Iterator {
pub(crate) fn new(recorder: &'record mut BacktrackingRecorder<Iter>) -> Self {
ReferencingBacktrackingIterator {
recorder,
}
}
}
impl<'record, Iter> Iterator for ReferencingBacktrackingIterator<'record, Iter> where Iter: Iterator, Iter::Item: 'record {
type Item = &'record Iter::Item;
fn next(&mut self) -> Option<&'record Iter::Item> {
macro_rules! unsafe_backtracking_index {
($index:expr) => {
unsafe {
&*(&self.recorder.backtracking_vec[$index] as *const Iter::Item)
}
};
}
use crate::{Backtracking, Progressing};
match self.recorder.state {
Progressing => {
if let Some(val) = self.recorder.iterator.next() {
self.recorder.backtracking_vec.push(val);
Some(unsafe_backtracking_index!(self.recorder.backtracking_vec.len() - 1))
} else {
None
}
},
Backtracking { position } => {
if position >= self.recorder.backtracking_vec.len() {
self.recorder.state = Progressing;
self.next()
} else {
let new_position = position + 1;
self.recorder.state = Backtracking { position: new_position };
Some(unsafe_backtracking_index!(position))
}
},
}
}
}
use super::BacktrackingIterator;
impl<'record, Iter> BacktrackingIterator for ReferencingBacktrackingIterator<'record, Iter> where Iter: Iterator {
type RefPoint = usize;
fn get_ref_point(&self) -> usize {
match self.recorder.state {
Progressing => self.recorder.backtracking_vec.len(),
Backtracking { position } => position,
}
}
fn get_oldest_point(&self) -> usize {
0_usize
}
fn backtrack(&mut self, position: usize) {
self.recorder.state = Backtracking { position };
}
}
use super::Walkbackable;
impl<'history, 'record, Iter: 'history> Walkbackable<'history> for ReferencingBacktrackingIterator<'record, Iter> where Iter: Iterator, 'history : 'record {
type RefPoint = usize;
type Item = &'record Iter::Item;
type Walkback = ReferencingWalkback<'record, Iter>;
fn walk_back(&'history self) -> ReferencingWalkback<'record, Iter> where {
ReferencingWalkback::new(self)
}
}
pub struct ReferencingWalkback<'record, Iter> where Iter: Iterator {
backtracker: &'record BacktrackingRecorder<Iter>,
reverse_position: usize,
}
impl<'record, Iter> ReferencingWalkback<'record, Iter>
where Iter: Iterator, Iter::Item: 'record {
fn new<'history>(backtracker: &'history ReferencingBacktrackingIterator<'record, Iter>) -> Self where 'history : 'record {
let history_len = backtracker.recorder.backtracking_vec.len();
ReferencingWalkback {
backtracker: backtracker.recorder,
reverse_position: history_len,
}
}
}
use super::Walkback;
impl<'history, 'record, Iter> Walkback<'history> for ReferencingWalkback<'record, Iter>
where Iter: Iterator, 'history : 'record {
type RefPoint = usize;
fn get_ref_point(&self) -> usize {
self.reverse_position
}
}
impl<'history, 'record, Iter> Iterator for ReferencingWalkback<'record, Iter>
where Iter: Iterator, Iter::Item: 'record, 'history : 'record {
type Item = &'record Iter::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.reverse_position == 0 {
None
} else {
let new_position = self.reverse_position - 1_usize;
let val = &self.backtracker.backtracking_vec[new_position];
self.reverse_position = new_position;
Some(val)
}
}
}