use crate::state::NavigationState;
use crate::time::{Instant, Utc};
pub const MAX_HISTORY: usize = 16;
#[derive(Debug, Clone)]
pub(super) struct History {
states: [NavigationState; MAX_HISTORY],
len: usize,
}
impl History {
pub(super) const fn starting_with(state: &NavigationState) -> Self {
Self {
states: [*state; MAX_HISTORY],
len: 1,
}
}
pub(super) fn current(&self) -> &NavigationState {
self.states
.get(self.len.saturating_sub(1))
.unwrap_or(&self.states[0])
}
pub(super) fn record(&mut self, state: &NavigationState) {
if state.valid_at() <= self.current().valid_at() {
self.replace_current(state);
return;
}
if self.len == MAX_HISTORY {
for index in 1..MAX_HISTORY {
if let Some(&next) = self.states.get(index) {
if let Some(slot) = self.states.get_mut(index.wrapping_sub(1)) {
*slot = next;
}
}
}
self.len = MAX_HISTORY.saturating_sub(1);
}
if let Some(slot) = self.states.get_mut(self.len) {
*slot = *state;
self.len = self.len.saturating_add(1);
}
}
pub(super) fn restart_with(&mut self, state: &NavigationState) {
if let Some(slot) = self.states.get_mut(0) {
*slot = *state;
}
self.len = 1;
}
pub(super) fn reaching(&self, moment: Instant<Utc>) -> Option<&[NavigationState]> {
let held = self.states.get(..self.len)?;
let start = held.iter().rposition(|state| state.valid_at() <= moment)?;
held.get(start..)
}
fn replace_current(&mut self, state: &NavigationState) {
if let Some(slot) = self.states.get_mut(self.len.saturating_sub(1)) {
*slot = *state;
}
}
}