1use std::borrow::Cow;
12
13#[cfg(doctest)]
14#[doc = include_str!("../README.md")]
15mod readme_doctests {}
16
17mod introspection;
18
19pub mod projection;
20
21#[doc(hidden)]
22pub use introspection::__STATUM_LINKED_MACHINES;
23#[doc(hidden)]
24pub use introspection::__STATUM_LINKED_REFERENCE_TYPES;
25#[doc(hidden)]
26pub use introspection::__STATUM_LINKED_RELATIONS;
27#[doc(hidden)]
28pub use introspection::__STATUM_LINKED_VALIDATOR_ENTRIES;
29#[doc(hidden)]
30pub use introspection::__STATUM_LINKED_VIA_ROUTES;
31
32#[doc(hidden)]
33pub mod __private {
34 pub use crate::{
35 Attested, LinkedMachineGraph, LinkedReferenceTypeDescriptor, LinkedRelationBasis, LinkedRelationDescriptor,
36 LinkedRelationKind, LinkedRelationSource, LinkedRelationTarget, LinkedStateDescriptor,
37 LinkedTransitionDescriptor, LinkedTransitionInventory, LinkedValidatorEntryDescriptor,
38 LinkedViaRouteDescriptor, MachinePresentation,
39 MachinePresentationDescriptor, MachineReference, MachineReferenceTarget, MachineRole,
40 RebuildAttempt, RebuildReport, StateFamily, StateFamilyMember, StatePresentation,
41 StaticMachineLinkDescriptor, TransitionPresentation, TransitionPresentationInventory,
42 __STATUM_LINKED_MACHINES, __STATUM_LINKED_REFERENCE_TYPES, __STATUM_LINKED_RELATIONS,
43 __STATUM_LINKED_VALIDATOR_ENTRIES, __STATUM_LINKED_VIA_ROUTES,
44 };
45 pub use futures;
46 pub use linkme;
47
48 #[derive(Debug)]
49 pub struct TransitionToken {
50 _private: u8,
51 }
52
53 impl Default for TransitionToken {
54 fn default() -> Self {
55 Self::new()
56 }
57 }
58
59 impl TransitionToken {
60 pub const fn new() -> Self {
61 Self { _private: 0 }
62 }
63 }
64
65 pub fn attest<T, Via>(inner: T) -> crate::Attested<T, Via> {
66 crate::Attested::new(inner)
67 }
68}
69
70pub use introspection::{
71 linked_machines, linked_reference_types, linked_relations, linked_validator_entries,
72 linked_via_routes, LinkedMachineGraph, LinkedReferenceTypeDescriptor, LinkedRelationBasis,
73 LinkedRelationDescriptor, LinkedRelationKind, LinkedRelationSource, LinkedRelationTarget,
74 LinkedStateDescriptor, LinkedTransitionDescriptor, LinkedTransitionInventory,
75 LinkedValidatorEntryDescriptor, LinkedViaRouteDescriptor, MachineDescriptor, MachineGraph,
76 MachineIntrospection, MachinePresentation, MachineRole, MachinePresentationDescriptor,
77 MachineStateIdentity, MachineTransitionRecorder, RecordedTransition, StateDescriptor,
78 StatePresentation, StaticMachineLinkDescriptor, TransitionDescriptor, TransitionInventory,
79 TransitionPresentation, TransitionPresentationInventory,
80};
81
82#[doc(hidden)]
84pub trait StateFamily {
85 const NAME: &'static str;
87
88 const VARIANT_COUNT: usize;
90}
91
92#[doc(hidden)]
94pub trait StateFamilyMember: StateMarker {
95 const RUST_NAME: &'static str;
97
98 const HAS_DATA: bool;
100}
101
102pub trait StateMarker {
108 type Data;
110}
111
112pub trait UnitState: StateMarker<Data = ()> {}
116
117pub trait DataState: StateMarker {}
121
122#[derive(Clone, Copy, Debug, Eq, PartialEq)]
124pub struct MachineReferenceTarget {
125 pub machine_path: &'static [&'static str],
127 pub state: &'static str,
129}
130
131pub trait MachineReference {
133 const TARGET: MachineReferenceTarget;
135}
136
137pub trait CanTransitionTo<Next> {
141 type Output;
143
144 fn transition_to(self) -> Self::Output;
146}
147
148pub trait CanTransitionWith<Data> {
152 type NextState;
154 type Output;
156
157 fn transition_with_data(self, data: Data) -> Self::Output;
159}
160
161pub trait CanTransitionMap<Next: StateMarker> {
165 type CurrentData;
167 type Output;
169
170 fn transition_map<F>(self, f: F) -> Self::Output
172 where
173 F: FnOnce(Self::CurrentData) -> Next::Data;
174}
175
176#[derive(Debug)]
178pub enum Error {
179 InvalidState,
181}
182
183#[derive(Clone, Debug, Eq, PartialEq)]
188pub enum Branch<A, B> {
189 First(A),
191 Second(B),
193}
194
195#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
203pub struct Attested<T, Via> {
204 inner: T,
205 marker: core::marker::PhantomData<Via>,
206}
207
208impl<T, Via> Attested<T, Via> {
209 #[doc(hidden)]
210 pub fn new(inner: T) -> Self {
211 Self {
212 inner,
213 marker: core::marker::PhantomData,
214 }
215 }
216
217 pub fn into_inner(self) -> T {
219 self.inner
220 }
221
222 #[allow(clippy::should_implement_trait)]
224 pub fn as_ref(&self) -> &T {
225 &self.inner
226 }
227
228 pub fn map_inner<U>(self, f: impl FnOnce(T) -> U) -> Attested<U, Via> {
230 Attested::new(f(self.inner))
231 }
232}
233
234impl<T, Via> AsRef<T> for Attested<T, Via> {
235 fn as_ref(&self) -> &T {
236 &self.inner
237 }
238}
239
240pub type Result<T> = core::result::Result<T, Error>;
257
258#[derive(Clone, Debug, Eq, PartialEq)]
260pub struct Rejection {
261 pub reason_key: &'static str,
263 pub message: Option<Cow<'static, str>>,
265}
266
267impl Rejection {
268 pub const fn new(reason_key: &'static str) -> Self {
270 Self {
271 reason_key,
272 message: None,
273 }
274 }
275
276 pub fn with_message(self, message: impl Into<Cow<'static, str>>) -> Self {
278 Self {
279 message: Some(message.into()),
280 ..self
281 }
282 }
283}
284
285impl From<&'static str> for Rejection {
286 fn from(reason_key: &'static str) -> Self {
287 Self::new(reason_key)
288 }
289}
290
291impl core::fmt::Display for Rejection {
292 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
293 match &self.message {
294 Some(message) => write!(fmt, "{}: {}", self.reason_key, message),
295 None => write!(fmt, "{}", self.reason_key),
296 }
297 }
298}
299
300impl std::error::Error for Rejection {}
301
302pub type Validation<T> = core::result::Result<T, Rejection>;
304
305#[derive(Clone, Debug, Eq, PartialEq)]
307pub struct RebuildAttempt {
308 pub validator: &'static str,
310 pub target_state: &'static str,
312 pub matched: bool,
314 pub reason_key: Option<&'static str>,
316 pub message: Option<Cow<'static, str>>,
318}
319
320#[derive(Debug)]
322pub struct RebuildReport<M> {
323 pub attempts: Vec<RebuildAttempt>,
325 pub result: Result<M>,
327}
328
329impl<M> RebuildReport<M> {
330 pub fn matched_attempt(&self) -> Option<&RebuildAttempt> {
332 self.attempts.iter().find(|attempt| attempt.matched)
333 }
334
335 pub fn into_result(self) -> Result<M> {
337 self.result
338 }
339}
340
341impl<T> From<Error> for core::result::Result<T, Error> {
342 fn from(val: Error) -> Self {
343 Err(val)
344 }
345}
346
347impl core::fmt::Display for Error {
348 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
349 write!(fmt, "{self:?}")
350 }
351}
352
353impl std::error::Error for Error {}