1#![allow(clippy::module_name_repetitions)]
2use std::fmt;
3
4use bigerror::ThinContext;
5use tokio::time::Instant;
6use uuid::Uuid;
7
8pub mod builder;
9pub mod ingress;
10pub mod manager;
11pub mod node;
12pub mod notification;
13pub mod queue;
14pub mod storage;
15pub mod timeout;
16
17#[cfg(test)]
18mod test_support;
19
20pub use builder::RexBuilder;
21pub use manager::{
22 HashKind, Signal, SignalExt, SignalQueue, SmContext, StateMachine, StateMachineExt,
23 StateMachineManager,
24};
25pub use notification::{
26 GetTopic, Notification, NotificationManager, NotificationProcessor, NotificationQueue,
27 Operation, Request, RequestInner, RexMessage, RexTopic, Subscriber, UnaryRequest,
28};
29pub use timeout::Timeout;
30
31pub trait State: fmt::Debug + Send + PartialEq + Copy {
35 type Input: Send + Sync + 'static + fmt::Debug;
36}
37
38pub trait Kind: fmt::Debug + Send + Sized {
42 type State: State<Input = Self::Input> + AsRef<Self>;
43 type Input: Send + Sync + 'static + fmt::Debug;
44
45 fn new_state(&self) -> Self::State;
46 fn failed_state(&self) -> Self::State;
47 fn completed_state(&self) -> Self::State;
48 fn is_terminal(state: Self::State) -> bool {
50 let kind = state.as_ref();
51 kind.completed_state() == state || kind.failed_state() == state
52 }
53}
54
55pub trait Rex: Kind + HashKind
71where
72 Self::State: AsRef<Self>,
73{
74 type Message: RexMessage;
75 fn state_input(&self, state: Self::State) -> Option<Self::Input>;
76 fn timeout_input(&self, instant: Instant) -> Option<Self::Input>;
77}
78
79#[derive(Debug, Hash, Eq, PartialEq, Copy, Clone)]
82pub struct StateId<K: Kind> {
83 pub kind: K,
84 pub uuid: Uuid,
85}
86
87impl<K> std::ops::Deref for StateId<K>
88where
89 K: Kind,
90{
91 type Target = K;
92
93 fn deref(&self) -> &Self::Target {
94 &self.kind
95 }
96}
97
98impl<K> fmt::Display for StateId<K>
99where
100 K: Kind,
101{
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 write!(
104 f,
105 "{:?}<{}>",
106 self.kind,
107 (!self.is_nil())
108 .then(|| bs58::encode(self.uuid).into_string())
109 .unwrap_or_else(|| "NIL".to_string())
110 )
111 }
112}
113
114impl<K: Kind> StateId<K> {
115 pub const fn new(kind: K, uuid: Uuid) -> Self {
116 Self { kind, uuid }
117 }
118
119 pub fn new_rand(kind: K) -> Self {
120 Self::new(kind, Uuid::new_v4())
121 }
122
123 pub const fn nil(kind: K) -> Self {
124 Self::new(kind, Uuid::nil())
125 }
126 pub fn is_nil(&self) -> bool {
127 self.uuid == Uuid::nil()
128 }
129 #[cfg(test)]
132 pub const fn new_with_u128(kind: K, v: u128) -> Self {
133 Self {
134 kind,
135 uuid: Uuid::from_u128(v),
136 }
137 }
138}
139
140#[derive(ThinContext)]
141pub struct RexError;