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 =
116 state_count
117 .checked_mul(event_count)
118 .ok_or(FastStateMachineBuildError::TransitionTableOverflow {
119 state_count,
120 event_count,
121 })?;
122
123 let mut initial_states = vec![false; state_count];
124 for state in self.initial_states {
125 if state >= state_count {
126 return Err(FastStateMachineBuildError::InitialStateOutOfRange { state, state_count });
127 }
128 initial_states[state] = true;
129 }
130
131 let mut final_states = vec![false; state_count];
132 for state in self.final_states {
133 if state >= state_count {
134 return Err(FastStateMachineBuildError::FinalStateOutOfRange { state, state_count });
135 }
136 final_states[state] = true;
137 }
138
139 let mut transitions = vec![usize::MAX; transition_count];
140 for (source, event, target) in self.transitions {
141 if source >= state_count {
142 return Err(FastStateMachineBuildError::TransitionSourceOutOfRange {
143 source_state: source,
144 state_count,
145 });
146 }
147 if event >= event_count {
148 return Err(FastStateMachineBuildError::TransitionEventOutOfRange { event, event_count });
149 }
150 if target >= state_count {
151 return Err(FastStateMachineBuildError::TransitionTargetOutOfRange { target, state_count });
152 }
153
154 let index = source
155 .checked_mul(event_count)
156 .and_then(|base| base.checked_add(event))
157 .expect("validated transition index must fit usize");
158
159 match transitions[index] {
160 usize::MAX => transitions[index] = target,
161 existing if existing == target => {}
162 existing => {
163 return Err(FastStateMachineBuildError::DuplicateTransition {
164 source_state: source,
165 event,
166 existing_target: existing,
167 new_target: target,
168 });
169 }
170 }
171 }
172
173 Ok(FastStateMachine {
174 state_count,
175 event_count,
176 initial_states,
177 final_states,
178 transitions,
179 cas: FastCas::with_policy(self.cas_policy),
180 })
181 }
182}
183
184impl Default for FastStateMachineBuilder {
185 fn default() -> Self {
186 Self::new()
187 }
188}