use crate::{error::NoError, motion::Timed};
use arrayvec::ArrayVec;
pub trait Reversible {
type ReversalError;
fn reversed(&self) -> Result<Self, Self::ReversalError>
where
Self: Sized;
}
pub trait Backtrack<State, Action> {
type BacktrackError;
fn flip_endpoints(
&self,
initial_reverse_state: &State,
final_reverse_state: &State,
) -> Result<(State, State), Self::BacktrackError>;
fn backtrack(
&self,
parent_forward_state: &State,
parent_reverse_state: &State,
reverse_action: &Action,
child_reverse_state: &State,
) -> Result<(Action, State), Self::BacktrackError>;
}
impl Reversible for () {
type ReversalError = NoError;
fn reversed(&self) -> Result<(), Self::ReversalError> {
Ok(())
}
}
pub fn flip_endpoint_times<State: Clone + Timed>(
initial_reverse_state: &State,
final_reverse_state: &State,
) -> Result<(State, State), NoError> {
let delta_t = initial_reverse_state.time() - final_reverse_state.time();
let mut initial_forward_state = final_reverse_state.clone();
initial_forward_state.set_time(initial_forward_state.time() + delta_t);
let mut final_forward_state = initial_reverse_state.clone();
final_forward_state.set_time(final_forward_state.time() + delta_t);
Ok((initial_forward_state, final_forward_state))
}
pub fn backtrack_times<State: Clone + Timed, const N: usize>(
parent_forward_state: &State,
parent_reverse_state: &State,
reverse_action: &ArrayVec<State, N>,
child_reverse_state: &State,
) -> Result<(ArrayVec<State, N>, State), NoError> {
let dt = parent_forward_state.time() - parent_reverse_state.time();
let mut child_forward_state = child_reverse_state.clone();
child_forward_state.set_time(child_forward_state.time() + dt);
let mut forward_action = reverse_action.clone();
let swap_endpoints = !forward_action.is_empty();
if swap_endpoints {
forward_action.pop();
}
forward_action.reverse();
for wp in &mut forward_action {
wp.set_time(wp.time() + dt);
}
if swap_endpoints {
forward_action.push(parent_forward_state.clone());
}
Ok((forward_action, child_forward_state))
}