1use 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#[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
62impl<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}