artifactize_core/agent/session/
outcome.rs1use crate::agent::verdict::ValidatedResult;
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6#[derive(Debug, Clone, Default)]
7pub enum End {
8 #[default]
9 Empty,
10 Completed(ValidatedResult),
12 Failed {
13 code: Option<crate::agent::error::Code>,
14 message: Option<String>,
15 },
16}
17#[derive(Debug, Clone, Default)]
18pub enum Answer {
19 #[default]
20 Empty,
21 Completed(String),
22 Failed {
23 code: Option<crate::agent::error::Code>,
24 message: Option<String>,
25 },
26}
27#[derive(Serialize, Deserialize)]
28#[serde(rename_all = "camelCase")]
29struct Wire<T> {
30 #[serde(skip_serializing_if = "Option::is_none")]
31 result: Option<T>,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 text: Option<String>,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 error_code: Option<crate::agent::error::Code>,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 error: Option<String>,
38}
39impl<T> Default for Wire<T> {
41 fn default() -> Self {
42 Self {
43 result: None,
44 text: None,
45 error_code: None,
46 error: None,
47 }
48 }
49}
50impl End {
51 pub fn result(&self) -> Option<&ValidatedResult> {
52 if let Self::Completed(value) = self {
53 Some(value)
54 } else {
55 None
56 }
57 }
58 pub fn failure(&self) -> Option<(Option<crate::agent::error::Code>, &str)> {
59 if let Self::Failed {
60 code,
61 message: Some(message),
62 } = self
63 {
64 Some((*code, message))
65 } else {
66 None
67 }
68 }
69}
70impl Answer {
71 pub fn text(&self) -> Option<&str> {
72 if let Self::Completed(value) = self {
73 Some(value)
74 } else {
75 None
76 }
77 }
78 pub fn failure(&self) -> Option<(Option<crate::agent::error::Code>, &str)> {
79 if let Self::Failed {
80 code,
81 message: Some(message),
82 } = self
83 {
84 Some((*code, message))
85 } else {
86 None
87 }
88 }
89}
90impl Serialize for End {
91 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
92 let wire = match self {
93 Self::Empty => Wire::default(),
94 Self::Completed(value) => Wire {
95 result: Some(value.clone()),
96 ..Wire::default()
97 },
98 Self::Failed { code, message } => Wire {
99 error_code: *code,
100 error: message.clone(),
101 ..Wire::default()
102 },
103 };
104 wire.serialize(serializer)
105 }
106}
107impl<'de> Deserialize<'de> for End {
108 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
109 let wire = Wire::<ValidatedResult>::deserialize(deserializer)?;
110 match (wire.result, wire.error_code, wire.error) {
111 (Some(value), None, None) => Ok(Self::Completed(value)),
112 (Some(_), _, _) => Err(serde::de::Error::custom(
113 "review end cannot succeed and fail",
114 )),
115 (None, None, None) => Ok(Self::Empty),
116 (None, code, message) => Ok(Self::Failed { code, message }),
117 }
118 }
119}
120impl Serialize for Answer {
121 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
122 let wire: Wire<Value> = match self {
123 Self::Empty => Wire::default(),
124 Self::Completed(value) => Wire {
125 text: Some(value.clone()),
126 ..Wire::default()
127 },
128 Self::Failed { code, message } => Wire {
129 error_code: *code,
130 error: message.clone(),
131 ..Wire::default()
132 },
133 };
134 wire.serialize(serializer)
135 }
136}
137impl<'de> Deserialize<'de> for Answer {
138 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
139 let wire = Wire::<Value>::deserialize(deserializer)?;
140 match (wire.text, wire.error_code, wire.error) {
141 (Some(value), None, None) => Ok(Self::Completed(value)),
142 (Some(_), _, _) => Err(serde::de::Error::custom("answer cannot succeed and fail")),
143 (None, None, None) => Ok(Self::Empty),
144 (None, code, message) => Ok(Self::Failed { code, message }),
145 }
146 }
147}
148#[cfg(test)]
149mod tests {
150 use super::*;
151 #[test]
152 fn original_success_error_and_empty_envelopes_round_trip() {
153 use crate::agent::error::Code;
154 use serde_json::json;
155
156 let empty: End = serde_json::from_value(json!({})).unwrap();
157 assert!(matches!(empty, End::Empty));
158 let completed: End = serde_json::from_value(json!({"result":{"verdict":"GREEN"}})).unwrap();
159 assert_eq!(completed.result().unwrap().verdict.as_str(), "GREEN");
160 let failed: End =
161 serde_json::from_value(json!({"errorCode":"TIMEOUT","error":"timed out"})).unwrap();
162 assert_eq!(failed.failure(), Some((Some(Code::Timeout), "timed out")));
163 for (end, expected) in [
164 (empty, json!({})),
165 (completed, json!({"result":{"verdict":"GREEN"}})),
166 (failed, json!({"errorCode":"TIMEOUT","error":"timed out"})),
167 ] {
168 assert_eq!(serde_json::to_value(end).unwrap(), expected);
169 }
170
171 let empty: Answer = serde_json::from_value(json!({})).unwrap();
172 assert!(matches!(empty, Answer::Empty));
173 let completed: Answer = serde_json::from_value(json!({"text":"answer"})).unwrap();
174 assert_eq!(completed.text(), Some("answer"));
175 let failed: Answer =
176 serde_json::from_value(json!({"errorCode":"TIMEOUT","error":"timed out"})).unwrap();
177 assert_eq!(failed.failure(), Some((Some(Code::Timeout), "timed out")));
178 for (answer, expected) in [
179 (empty, json!({})),
180 (completed, json!({"text":"answer"})),
181 (failed, json!({"errorCode":"TIMEOUT","error":"timed out"})),
182 ] {
183 assert_eq!(serde_json::to_value(answer).unwrap(), expected);
184 }
185 assert!(
186 serde_json::from_value::<Answer>(serde_json::json!({"text":"answer","error":"failed"}))
187 .is_err()
188 );
189 assert!(
190 serde_json::from_value::<End>(
191 serde_json::json!({"result":{"verdict":"RED"},"error":"failed"})
192 )
193 .is_err()
194 );
195 assert!(serde_json::from_value::<End>(serde_json::json!({"result":{}})).is_err());
196 }
197}