use std::cell::RefCell;
struct MemoryHistoryState {
current: String,
history: Vec<String>,
future: Vec<String>,
}
pub struct MemoryHistory {
state: RefCell<MemoryHistoryState>,
}
impl Default for MemoryHistory {
fn default() -> Self {
Self::with_initial_path("/")
}
}
impl MemoryHistory {
pub fn with_initial_path(path: impl ToString) -> Self {
Self {
state: MemoryHistoryState{
current: path.to_string().parse().unwrap_or_else(|err| {
panic!("index route does not exist:\n{err}\n use MemoryHistory::with_initial_path to set a custom path")
}),
history: Vec::new(),
future: Vec::new(),
}.into(),
}
}
}
impl MemoryHistory {
pub fn current_route(&self) -> String {
self.state.borrow().current.clone()
}
pub fn can_go_back(&self) -> bool {
!self.state.borrow().history.is_empty()
}
pub fn go_back(&self) {
let mut write = self.state.borrow_mut();
if let Some(last) = write.history.pop() {
let old = std::mem::replace(&mut write.current, last);
write.future.push(old);
}
}
pub fn can_go_forward(&self) -> bool {
!self.state.borrow().future.is_empty()
}
pub fn go_forward(&self) {
let mut write = self.state.borrow_mut();
if let Some(next) = write.future.pop() {
let old = std::mem::replace(&mut write.current, next);
write.history.push(old);
}
}
pub fn push(&self, new: String) {
let mut write = self.state.borrow_mut();
if write.current == new {
return;
}
let old = std::mem::replace(&mut write.current, new);
write.history.push(old);
write.future.clear();
}
pub fn replace(&self, path: String) {
let mut write = self.state.borrow_mut();
write.current = path;
}
}