diff --git a/src/action/action_meta.rs b/src/action/action_meta.rs index 93dcc05..5147344 100644 --- a/src/action/action_meta.rs +++ b/src/action/action_meta.rs @@ -11,6 +11,8 @@ pub type RecursionDepth = u32; #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ActionMeta { id: ActionId, + /// Previously applied action. + prev: ActionId, /// Recursion depth of a given action. depth: RecursionDepth, } @@ -18,18 +20,20 @@ pub struct ActionMeta { impl ActionMeta { pub const ZERO: Self = Self { id: ActionId::ZERO, + prev: ActionId::ZERO, depth: 0, }; #[inline(always)] - pub(crate) fn new(id: ActionId, depth: RecursionDepth) -> Self { - Self { id, depth } + pub(crate) fn new(id: ActionId, prev: ActionId, depth: RecursionDepth) -> Self { + Self { id, prev, depth } } #[inline(always)] pub fn zero_custom(time: Timestamp) -> Self { Self { id: ActionId::new_unchecked(time.into()), + prev: ActionId::new_unchecked(time.into()), depth: 0, } } @@ -45,6 +49,12 @@ impl ActionMeta { self.depth } + /// Time of previously applied action. + #[inline(always)] + pub fn prev_time(&self) -> Timestamp { + self.prev.into() + } + #[inline(always)] pub fn time(&self) -> Timestamp { self.id.into() diff --git a/src/action/enabling_condition.rs b/src/action/enabling_condition.rs index 88b04a7..fc30d5f 100644 --- a/src/action/enabling_condition.rs +++ b/src/action/enabling_condition.rs @@ -1,8 +1,10 @@ +#[allow(unused_variables)] pub trait EnablingCondition { /// Enabling condition for the Action. /// - /// Checks if the given action is enabled for a given state. - fn is_enabled(&self, #[allow(unused_variables)] state: &State) -> bool { + /// Checks if the given action is enabled for a given state and timestamp. + fn is_enabled(&self, state: &State, time: crate::Timestamp) -> bool { true } } + diff --git a/src/store.rs b/src/store.rs index b5225f2..7022740 100644 --- a/src/store.rs +++ b/src/store.rs @@ -1,8 +1,8 @@ use std::sync::OnceLock; use crate::{ - ActionId, ActionMeta, ActionWithMeta, Effects, EnablingCondition, Instant, Reducer, SystemTime, - TimeService, + ActionId, ActionMeta, ActionWithMeta, Effects, EnablingCondition, Instant, Reducer, SubStore, + SystemTime, TimeService, }; /// Wraps around State and allows only immutable borrow, @@ -138,10 +138,9 @@ where where T: Into + EnablingCondition, { - if !action.is_enabled(self.state()) { + if !action.is_enabled(self.state(), self.last_action_id.into()) { return false; } - self.dispatch_enabled(action.into()); true @@ -153,15 +152,18 @@ where /// to reducer and then effects. /// /// If action is not enabled, we return false and do nothing. - pub fn sub_dispatch(&mut self, action: A) -> bool + pub fn sub_dispatch(&mut self, action: A) -> bool where - A: Into + EnablingCondition, - SubAction: Into, + A: Into<>::SubAction> + EnablingCondition, + >::SubAction: Into, + Self: SubStore, { - if !action.is_enabled(self.state()) { + if !action.is_enabled( + >::state(self), + self.last_action_id.into(), + ) { return false; } - self.dispatch_enabled(action.into().into()); true @@ -173,14 +175,17 @@ where let time_passed = monotonic_time .duration_since(self.monotonic_time) .as_nanos(); - self.monotonic_time = monotonic_time; - self.last_action_id = self.last_action_id.next(time_passed as u64); - let action_with_meta = - ActionMeta::new(self.last_action_id, self.recursion_depth).with_action(action); + let prev = self.last_action_id; + let curr = prev.next(time_passed as u64); + + self.last_action_id = curr; self.recursion_depth += 1; + let action_with_meta = + ActionMeta::new(curr, prev, self.recursion_depth).with_action(action); + self.dispatch_reducer(&action_with_meta); self.dispatch_effects(action_with_meta); diff --git a/src/sub_store.rs b/src/sub_store.rs index 17b1514..6417a93 100644 --- a/src/sub_store.rs +++ b/src/sub_store.rs @@ -10,5 +10,5 @@ pub trait SubStore { fn state_and_service(&mut self) -> (&SubState, &mut Self::Service); fn dispatch(&mut self, action: A) -> bool where - A: Into + crate::EnablingCondition; + A: Into + crate::EnablingCondition; }