Hey, I'm trying to implement a state machine, and I would like to pass a generic struct of data to its "update()" function that might potentially have mutable and const references, and I keep getting various kinds of lifetime issues. I'm new to rust, so I have very superficial understanding of lifetimes, and I find it hard to reason about what happens. Here's the snippet of code I was playing around with:
pub trait State<T, C> {
fn on_enter(&mut self, _persistent_data: &mut T) {}
fn on_exit(&mut self, _persistent_data: &mut T) {}
fn update(&mut self, persistent_data: &mut T, context: &mut C) -> UpdateResult<T, C>;
}
pub enum UpdateResult<T, C> {
KeepUpdating,
Transition(Box<dyn State<T, C>>),
Stop
}
pub struct StateMachine<T, C> {
persistent_data: T,
active_state: Option<Box<dyn State<T, C>>>,
}
impl<T, C> StateMachine<T, C> {
pub fn new(persistent_data: T) -> Self {
Self {
persistent_data,
active_state: None,
}
}
pub fn push(&mut self, state: Box<dyn State<T, C>>) {
self.pop();
self.active_state = Some(state);
self.active_state.as_deref_mut().unwrap().on_enter(&mut self.persistent_data);
}
pub fn pop(&mut self) {
if let Some(state) = self.active_state.as_deref_mut() {
state.on_exit(&mut self.persistent_data);
self.active_state = None;
}
}
pub fn update(&mut self, context: &mut C) {
if let Some(state) = self.active_state.as_deref_mut() {
match state.update(&mut self.persistent_data, context) {
UpdateResult::Transition(new_state) => {
self.push(new_state);
self.update(context);
},
UpdateResult::Stop => self.active_state = None,
UpdateResult::KeepUpdating => ()
}
}
}
}
struct PersistentData {
}
struct DataAccessorState<C> {
phantom_data: std::marker::PhantomData<C>
}
impl<C> DataAccessorState<C> {
fn new() -> Self {
Self {
phantom_data: std::marker::PhantomData
}
}
}
struct Data {
}
trait DataRefTrait {
fn get_data(&self) -> &Data;
}
struct DataRefTraitImpl<'a> {
data_ref: &'a Data
}
impl<'a> DataRefTrait for DataRefTraitImpl<'a> {
fn get_data(&self) -> &Data {
self.data_ref
}
}
impl<C: DataRefTrait> State<PersistentData, C> for DataAccessorState<C> {
fn update(&mut self, _persistent_data: &mut PersistentData, context: &mut C) -> UpdateResult<PersistentData, C> {
let _data = context.get_data();
UpdateResult::Stop
}
}
fn main() {
let mut state_machine = StateMachine::new(PersistentData {});
state_machine.push(Box::new(DataAccessorState::new()));
let data = Data {};
state_machine.update(&mut DataRefTraitImpl { data_ref: &data });
}
Could someone help me make sense of the errors I'm getting, and prod me in the direction on how to handle this?