eryon_core/state/
halt.rs

1/*
2    Appellation: halting <module>
3    Contrib: FL03 <jo3mccain@icloud.com>
4*/
5use crate::state::{State, Stated};
6
7mod impl_enum;
8mod impl_halt;
9
10pub trait Haltable<Q> {
11    type State: Stated<Item = Q>;
12
13    private!();
14
15    fn is_halted(&self) -> bool;
16}
17
18#[doc(hidden)]
19pub trait HaltableExt<Q>: Haltable<Q> {
20    fn get(self) -> Option<Q>;
21
22    fn get_mut(&mut self) -> Option<&mut Q>;
23
24    fn map<U, F>(self, f: F) -> Option<U>
25    where
26        F: FnOnce(Q) -> U,
27        Self: Sized,
28    {
29        self.get().map(f)
30    }
31}
32
33#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
34#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
35pub struct Halt<Q>(pub Q);
36
37/// [HaltState] extends the [State] by allowing for an 'imaginary' state that is not actually
38/// part of the machine's state space.
39#[derive(
40    Clone,
41    Copy,
42    Debug,
43    Eq,
44    Hash,
45    Ord,
46    PartialEq,
47    PartialOrd,
48    strum::EnumDiscriminants,
49    strum::EnumIs,
50)]
51#[cfg_attr(
52    feature = "serde",
53    derive(serde::Deserialize, serde::Serialize),
54    strum_discriminants(derive(serde::Deserialize, serde::Serialize))
55)]
56#[strum_discriminants(name(HaltTag), derive(Hash, Ord, PartialOrd))]
57pub enum HaltState<Q = usize> {
58    Halt(Halt<Q>),
59    State(State<Q>),
60}
61
62/*
63 ************* Implementations *************
64*/
65impl<Q> Haltable<Q> for Halt<Q> {
66    type State = State<Q>;
67
68    seal!();
69
70    fn is_halted(&self) -> bool {
71        true
72    }
73}
74
75impl<Q> Haltable<Q> for State<Halt<Q>> {
76    type State = State<Q>;
77
78    seal!();
79
80    fn is_halted(&self) -> bool {
81        true
82    }
83}
84impl<Q> Haltable<Q> for State<Option<Q>> {
85    type State = State<Q>;
86
87    seal!();
88
89    fn is_halted(&self) -> bool {
90        self.get().is_none()
91    }
92}
93
94impl<Q> Haltable<Q> for Option<State<Q>> {
95    type State = State<Q>;
96
97    seal!();
98
99    fn is_halted(&self) -> bool {
100        self.is_none()
101    }
102}
103
104impl<Q> HaltableExt<Q> for Halt<Q> {
105    fn get(self) -> Option<Q> {
106        Some(self.0)
107    }
108
109    fn get_mut(&mut self) -> Option<&mut Q> {
110        Some(&mut self.0)
111    }
112}
113
114impl<Q> HaltableExt<Q> for Option<State<Q>> {
115    fn get(self) -> Option<Q> {
116        self.map(|state| state.value())
117    }
118
119    fn get_mut(&mut self) -> Option<&mut Q> {
120        self.as_mut().map(|state| state.get_mut())
121    }
122}
123
124impl<Q> HaltableExt<Q> for State<Option<Q>> {
125    fn get(self) -> Option<Q> {
126        self.value()
127    }
128
129    fn get_mut(&mut self) -> Option<&mut Q> {
130        self.get_mut().as_mut()
131    }
132}