loong_contracts/
task_state.rs1use serde::{Deserialize, Serialize};
2
3use crate::contracts::{HarnessOutcome, TaskIntent};
4use crate::fault::Fault;
5
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14pub enum TaskState {
15 Runnable(TaskIntent),
16 InSend { task_id: String },
17 InReply { task_id: String },
18 Completed(HarnessOutcome),
19 Faulted(Fault),
20}
21
22impl TaskState {
23 pub fn task_id(&self) -> Option<&str> {
24 match self {
25 Self::Runnable(intent) => Some(&intent.task_id),
26 Self::InSend { task_id } | Self::InReply { task_id } => Some(task_id),
27 Self::Completed(_) | Self::Faulted(_) => None,
28 }
29 }
30
31 pub fn is_terminal(&self) -> bool {
32 matches!(self, Self::Completed(_) | Self::Faulted(_))
33 }
34
35 pub fn transition_to_in_send(self) -> Result<Self, String> {
36 #[allow(clippy::wildcard_enum_match_arm)]
37 match self {
38 Self::Runnable(intent) => Ok(Self::InSend {
39 task_id: intent.task_id,
40 }),
41 other => Err(format!(
42 "invalid transition: cannot move to InSend from {other:?}"
43 )),
44 }
45 }
46
47 pub fn transition_to_in_reply(self) -> Result<Self, String> {
48 #[allow(clippy::wildcard_enum_match_arm)]
49 match self {
50 Self::InSend { task_id } => Ok(Self::InReply { task_id }),
51 other => Err(format!(
52 "invalid transition: cannot move to InReply from {other:?}"
53 )),
54 }
55 }
56
57 pub fn transition_to_completed(self, outcome: HarnessOutcome) -> Result<Self, String> {
58 #[allow(clippy::wildcard_enum_match_arm)]
59 match self {
60 Self::InReply { .. } => Ok(Self::Completed(outcome)),
61 other => Err(format!(
62 "invalid transition: cannot move to Completed from {other:?}"
63 )),
64 }
65 }
66
67 pub fn transition_to_faulted(self, fault: Fault) -> Self {
68 if self.is_terminal() {
69 self } else {
71 Self::Faulted(fault)
72 }
73 }
74}