qubit_state_machine/fast/
fast_state_machine_builder.rs1use crate::FastCasPolicy;
14
15use super::{
16 FastStateMachine,
17 FastStateMachineBuildError,
18};
19use qubit_cas::FastCas;
20
21pub const FAST_STATE_MACHINE_DEFAULT_CAS_POLICY: FastCasPolicy = FastCasPolicy::spin(16);
26
27#[derive(Debug, Clone)]
29pub struct FastStateMachineBuilder {
30 state_count: Option<usize>,
31 event_count: Option<usize>,
32 initial_states: Vec<usize>,
33 final_states: Vec<usize>,
34 transitions: Vec<(usize, usize, usize)>,
35 cas_policy: FastCasPolicy,
36}
37
38impl FastStateMachineBuilder {
39 pub fn new() -> Self {
41 Self {
42 state_count: None,
43 event_count: None,
44 initial_states: Vec::new(),
45 final_states: Vec::new(),
46 transitions: Vec::new(),
47 cas_policy: FAST_STATE_MACHINE_DEFAULT_CAS_POLICY,
48 }
49 }
50
51 pub const fn state_count(mut self, count: usize) -> Self {
53 self.state_count = Some(count);
54 self
55 }
56
57 pub const fn event_count(mut self, count: usize) -> Self {
59 self.event_count = Some(count);
60 self
61 }
62
63 pub fn initial_state(mut self, state: usize) -> Self {
65 self.initial_states.push(state);
66 self
67 }
68
69 pub fn initial_states(mut self, states: &[usize]) -> Self {
71 self.initial_states.extend(states.iter().copied());
72 self
73 }
74
75 pub fn final_state(mut self, state: usize) -> Self {
77 self.final_states.push(state);
78 self
79 }
80
81 pub fn final_states(mut self, states: &[usize]) -> Self {
83 self.final_states.extend(states.iter().copied());
84 self
85 }
86
87 pub fn transition(mut self, source: usize, event: usize, target: usize) -> Self {
89 self.transitions.push((source, event, target));
90 self
91 }
92
93 pub const fn cas_policy(mut self, cas_policy: FastCasPolicy) -> Self {
95 self.cas_policy = cas_policy;
96 self
97 }
98
99 pub fn build(self) -> Result<FastStateMachine, FastStateMachineBuildError> {
101 let state_count = self
102 .state_count
103 .ok_or(FastStateMachineBuildError::StateCountNotConfigured)?;
104 let event_count = self
105 .event_count
106 .ok_or(FastStateMachineBuildError::EventCountNotConfigured)?;
107
108 if state_count == 0 {
109 return Err(FastStateMachineBuildError::InvalidStateCount { count: state_count });
110 }
111 if event_count == 0 {
112 return Err(FastStateMachineBuildError::InvalidEventCount { count: event_count });
113 }
114
115 let transition_count = state_count.checked_mul(event_count).ok_or(
116 FastStateMachineBuildError::TransitionTableOverflow {
117 state_count,
118 event_count,
119 },
120 )?;
121
122 let mut initial_states = vec![false; state_count];
123 for state in self.initial_states {
124 if state >= state_count {
125 return Err(FastStateMachineBuildError::InitialStateOutOfRange {
126 state,
127 state_count,
128 });
129 }
130 initial_states[state] = true;
131 }
132
133 let mut final_states = vec![false; state_count];
134 for state in self.final_states {
135 if state >= state_count {
136 return Err(FastStateMachineBuildError::FinalStateOutOfRange {
137 state,
138 state_count,
139 });
140 }
141 final_states[state] = true;
142 }
143
144 let mut transitions = vec![usize::MAX; transition_count];
145 for (source, event, target) in self.transitions {
146 if source >= state_count {
147 return Err(FastStateMachineBuildError::TransitionSourceOutOfRange {
148 source_state: source,
149 state_count,
150 });
151 }
152 if event >= event_count {
153 return Err(FastStateMachineBuildError::TransitionEventOutOfRange {
154 event,
155 event_count,
156 });
157 }
158 if target >= state_count {
159 return Err(FastStateMachineBuildError::TransitionTargetOutOfRange {
160 target,
161 state_count,
162 });
163 }
164
165 let index = source
166 .checked_mul(event_count)
167 .and_then(|base| base.checked_add(event))
168 .expect("validated transition index must fit usize");
169
170 match transitions[index] {
171 usize::MAX => transitions[index] = target,
172 existing if existing == target => {}
173 existing => {
174 return Err(FastStateMachineBuildError::DuplicateTransition {
175 source_state: source,
176 event,
177 existing_target: existing,
178 new_target: target,
179 });
180 }
181 }
182 }
183
184 Ok(FastStateMachine {
185 state_count,
186 event_count,
187 initial_states,
188 final_states,
189 transitions,
190 cas: FastCas::with_policy(self.cas_policy),
191 })
192 }
193}
194
195impl Default for FastStateMachineBuilder {
196 fn default() -> Self {
197 Self::new()
198 }
199}