synaptic_graph/
command.rs1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4use crate::send::Send;
5use crate::State;
6
7pub struct Command<S: State> {
22 pub(crate) update: Option<S>,
24 pub(crate) goto: Option<CommandGoto>,
26 pub(crate) interrupt_value: Option<Value>,
28 pub(crate) resume_value: Option<Value>,
30}
31
32impl<S: State> std::fmt::Debug for Command<S> {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 f.debug_struct("Command")
35 .field("has_update", &self.update.is_some())
36 .field("goto", &self.goto)
37 .field("interrupt_value", &self.interrupt_value)
38 .field("resume_value", &self.resume_value)
39 .finish()
40 }
41}
42
43impl<S: State> Clone for Command<S> {
44 fn clone(&self) -> Self {
45 Self {
46 update: self.update.clone(),
47 goto: self.goto.clone(),
48 interrupt_value: self.interrupt_value.clone(),
49 resume_value: self.resume_value.clone(),
50 }
51 }
52}
53
54impl<S: State> Command<S> {
55 pub fn goto(node: impl Into<String>) -> Self {
57 Self {
58 update: None,
59 goto: Some(CommandGoto::One(node.into())),
60 interrupt_value: None,
61 resume_value: None,
62 }
63 }
64
65 pub fn goto_with_update(node: impl Into<String>, update: S) -> Self {
67 Self {
68 update: Some(update),
69 goto: Some(CommandGoto::One(node.into())),
70 interrupt_value: None,
71 resume_value: None,
72 }
73 }
74
75 pub fn send(targets: Vec<Send>) -> Self {
77 Self {
78 update: None,
79 goto: Some(CommandGoto::Many(targets)),
80 interrupt_value: None,
81 resume_value: None,
82 }
83 }
84
85 pub fn update(state: S) -> Self {
87 Self {
88 update: Some(state),
89 goto: None,
90 interrupt_value: None,
91 resume_value: None,
92 }
93 }
94
95 pub fn resume(value: Value) -> Self {
100 Self {
101 update: None,
102 goto: None,
103 interrupt_value: None,
104 resume_value: Some(value),
105 }
106 }
107
108 pub fn end() -> Self {
110 Self {
111 update: None,
112 goto: Some(CommandGoto::One(crate::END.to_string())),
113 interrupt_value: None,
114 resume_value: None,
115 }
116 }
117}
118
119#[derive(Debug, Clone)]
121pub enum CommandGoto {
122 One(String),
124 Many(Vec<Send>),
126}
127
128#[derive(Clone)]
133pub enum NodeOutput<S: State> {
134 State(S),
136 Command(Command<S>),
138}
139
140impl<S: State + std::fmt::Debug> std::fmt::Debug for NodeOutput<S> {
141 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142 match self {
143 NodeOutput::State(s) => f.debug_tuple("NodeOutput::State").field(s).finish(),
144 NodeOutput::Command(c) => f.debug_tuple("NodeOutput::Command").field(c).finish(),
145 }
146 }
147}
148
149impl<S: State> From<S> for NodeOutput<S> {
151 fn from(state: S) -> Self {
152 NodeOutput::State(state)
153 }
154}
155
156#[derive(Debug, Clone)]
158pub enum GraphResult<S> {
159 Complete(S),
161 Interrupted {
163 state: S,
164 interrupt_value: Value,
166 },
167}
168
169impl<S> GraphResult<S> {
170 pub fn state(&self) -> &S {
172 match self {
173 GraphResult::Complete(s) => s,
174 GraphResult::Interrupted { state, .. } => state,
175 }
176 }
177
178 pub fn into_state(self) -> S {
180 match self {
181 GraphResult::Complete(s) => s,
182 GraphResult::Interrupted { state, .. } => state,
183 }
184 }
185
186 pub fn is_complete(&self) -> bool {
188 matches!(self, GraphResult::Complete(_))
189 }
190
191 pub fn is_interrupted(&self) -> bool {
193 matches!(self, GraphResult::Interrupted { .. })
194 }
195
196 pub fn interrupt_value(&self) -> Option<&Value> {
198 match self {
199 GraphResult::Interrupted {
200 interrupt_value, ..
201 } => Some(interrupt_value),
202 _ => None,
203 }
204 }
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
211pub struct Interrupt {
212 pub value: Value,
213}
214
215pub fn interrupt<S: State>(value: Value) -> NodeOutput<S> {
231 NodeOutput::Command(Command {
232 update: None,
233 goto: None,
234 interrupt_value: Some(value),
235 resume_value: None,
236 })
237}