1use std::{fmt, fmt::Debug};
31
32use borsh::{BorshDeserialize, BorshSerialize};
33use chrono::SecondsFormat;
34use rialo_cli_representable::Representable;
35use serde::{Deserialize, Serialize};
36
37use crate::RexError;
38
39#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, BorshSerialize, BorshDeserialize)]
41pub enum FilterResult {
42 Success(Vec<u8>),
43 Error(String),
44}
45
46impl FilterResult {
47 pub fn is_success(&self) -> bool {
49 matches!(self, FilterResult::Success(_))
50 }
51
52 pub fn is_error(&self) -> bool {
54 matches!(self, FilterResult::Error(_))
55 }
56
57 pub fn as_success(&self) -> Option<&Vec<u8>> {
59 if let FilterResult::Success(ref bytes) = self {
60 Some(bytes)
61 } else {
62 None
63 }
64 }
65
66 pub fn as_error(&self) -> Option<&String> {
68 if let FilterResult::Error(ref err) = self {
69 Some(err)
70 } else {
71 None
72 }
73 }
74}
75
76impl fmt::Display for FilterResult {
77 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78 match self {
79 FilterResult::Success(bytes) => write!(f, "Success: {:?}", bytes),
80 FilterResult::Error(err) => write!(f, "Error: {}", err),
81 }
82 }
83}
84
85impl From<Result<Vec<u8>, String>> for FilterResult {
86 fn from(result: Result<Vec<u8>, String>) -> Self {
87 match result {
88 Ok(bytes) => FilterResult::Success(bytes),
89 Err(err) => FilterResult::Error(err),
90 }
91 }
92}
93
94#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, BorshSerialize, BorshDeserialize)]
97pub enum RexData {
98 Raw(Vec<u8>),
100 Filtered(Vec<FilterResult>),
102}
103
104impl RexData {
105 pub fn is_raw(&self) -> bool {
107 matches!(self, RexData::Raw(_))
108 }
109
110 pub fn is_filtered(&self) -> bool {
112 matches!(self, RexData::Filtered(_))
113 }
114
115 pub fn as_raw(&self) -> Option<&Vec<u8>> {
117 if let RexData::Raw(ref data) = self {
118 Some(data)
119 } else {
120 None
121 }
122 }
123
124 pub fn as_filtered(&self) -> Option<&Vec<FilterResult>> {
126 if let RexData::Filtered(ref results) = self {
127 Some(results)
128 } else {
129 None
130 }
131 }
132
133 pub fn len(&self) -> usize {
135 match self {
136 RexData::Raw(data) => data.len(),
137 RexData::Filtered(results) => results
138 .iter()
139 .map(|r| match r {
140 FilterResult::Success(bytes) => bytes.len(),
141 FilterResult::Error(err) => err.len(),
142 })
143 .sum(),
144 }
145 }
146
147 pub fn is_empty(&self) -> bool {
149 self.len() == 0
150 }
151}
152
153#[derive(
157 Clone,
158 Debug,
159 Eq,
160 PartialEq,
161 Serialize,
162 Deserialize,
163 BorshSerialize,
164 BorshDeserialize,
165 Representable,
166)]
167#[representable(human_readable = "rex_response_human_readable")]
168pub struct RexResponse {
169 pub response: RexData,
171 pub timestamp: String,
173}
174
175fn rex_response_human_readable(response: &RexResponse) -> String {
176 let mut out = String::new();
177 out.push_str(&format!(
178 "Response: {:?}, Timestamp (from TEE): {}",
179 response.response, response.timestamp
180 ));
181 out
182}
183
184impl RexResponse {
185 pub fn new(response: RexData) -> Self {
187 Self {
188 response,
189 timestamp: chrono::Utc::now().to_rfc3339_opts(SecondsFormat::Micros, true),
192 }
193 }
194
195 pub fn into_successful_responses(self) -> Vec<Vec<u8>> {
201 match self.response {
202 RexData::Raw(data) => vec![data],
203 RexData::Filtered(results) => results
204 .into_iter()
205 .filter_map(|r| {
206 if let FilterResult::Success(bytes) = r {
207 Some(bytes)
208 } else {
209 None
210 }
211 })
212 .collect(),
213 }
214 }
215}
216
217#[derive(
221 Clone,
222 Debug,
223 Eq,
224 PartialEq,
225 Serialize,
226 Deserialize,
227 BorshSerialize,
228 BorshDeserialize,
229 Representable,
230)]
231#[serde(tag = "status", content = "contents")]
232#[serde(rename_all = "kebab-case")]
233#[non_exhaustive]
234#[representable(human_readable = "rex_output_human_readable")]
235pub enum RexOutput {
236 Success(RexResponse),
238 RexError(RexError),
240 UnserializableResponse(String),
242}
243
244fn rex_output_human_readable(output: &RexOutput) -> String {
245 match output {
246 RexOutput::Success(resp) => {
247 let len = resp.response.len();
248 format!("Success: {} bytes @ {}", len, resp.timestamp)
249 }
250 RexOutput::RexError(err) => format!("RexError: {}", err),
251 RexOutput::UnserializableResponse(msg) => {
252 format!("UnserializableResponse: {}", msg)
253 }
254 }
255}
256
257impl RexOutput {
258 pub fn is_success(&self) -> bool {
260 matches!(self, RexOutput::Success(_))
261 }
262
263 pub fn is_rex_error(&self) -> bool {
265 matches!(self, RexOutput::RexError(_))
266 }
267
268 pub fn is_unserializable_response(&self) -> bool {
270 matches!(self, RexOutput::UnserializableResponse(_))
271 }
272
273 pub fn as_success(&self) -> Option<&RexResponse> {
275 if let RexOutput::Success(ref response) = self {
276 Some(response)
277 } else {
278 None
279 }
280 }
281
282 pub fn as_rex_error(&self) -> Option<&RexError> {
284 if let RexOutput::RexError(ref error) = self {
285 Some(error)
286 } else {
287 None
288 }
289 }
290
291 pub fn into_success_payload(self) -> Option<Vec<Vec<u8>>> {
294 match self {
295 RexOutput::Success(response) => Some(response.into_successful_responses()),
296 _ => None,
297 }
298 }
299}
300
301impl From<Result<RexResponse, RexError>> for RexOutput {
302 fn from(result: Result<RexResponse, RexError>) -> Self {
303 match result {
304 Ok(response) => RexOutput::Success(response),
305 Err(error) => RexOutput::RexError(error),
306 }
307 }
308}
309
310impl From<RexError> for RexOutput {
311 fn from(error: RexError) -> Self {
312 RexOutput::RexError(error)
313 }
314}
315
316#[cfg(test)]
317mod test {
318 use serde_json::json;
319
320 use super::*;
321
322 #[test]
323 fn test_rex_result_success_serialization() {
324 let rex_data = RexResponse::new(RexData::Raw(
325 serde_json::to_vec(&json!({"data": 42, "message": "test"})).unwrap(),
326 ));
327 let result = RexOutput::Success(rex_data.clone());
328 let json = serde_json::to_value(&result).unwrap();
329
330 assert_eq!(
331 json,
332 json!({
333 "status": "success",
334 "contents": rex_data
335 })
336 );
337 }
338
339 #[test]
340 fn test_rex_result_error_serialization() {
341 let error = RexError::HttpStatusError {
342 status: 404,
343 reason: String::from("HTTP Status Code 404 Not Found"),
344 };
345
346 let result = RexOutput::RexError(error.clone());
347 let json = serde_json::to_value(&result).unwrap();
348
349 assert_eq!(
350 json,
351 json!({
352 "status": "rex-error",
353 "contents": error
354 })
355 );
356 }
357
358 #[test]
359 fn test_rex_result_unserializable_serialization() {
360 let result = RexOutput::UnserializableResponse("Failed to parse response".to_string());
361 let json = serde_json::to_value(&result).unwrap();
362
363 assert_eq!(
364 json,
365 json!({
366 "status": "unserializable-response",
367 "contents": "Failed to parse response"
368 })
369 );
370 }
371
372 #[test]
373 fn test_rex_result_deserialization() {
374 let expected = RexResponse::new(RexData::Raw(
376 serde_json::to_vec(&json!({"data": 123 })).unwrap(),
377 ));
378 let expected_clone = expected.clone();
379 let json = json!({
380 "status": "success",
381 "contents": expected_clone
382 });
383 let result: RexOutput = serde_json::from_value(json).unwrap();
384 assert_eq!(result, RexOutput::Success(expected_clone));
385
386 let error = RexError::HttpStatusError {
388 status: 500,
389 reason: "Internal Server Error".to_string(),
390 };
391 let json = json!({
392 "status": "rex-error",
393 "contents": error.clone()
394 });
395 let result: RexOutput = serde_json::from_value(json).unwrap();
396 assert_eq!(result, RexOutput::RexError(error));
397
398 let json = json!({
400 "status": "unserializable-response",
401 "contents": "Parse error"
402 });
403 let result: RexOutput = serde_json::from_value(json).unwrap();
404 assert_eq!(
405 result,
406 RexOutput::UnserializableResponse("Parse error".to_string())
407 );
408 }
409
410 #[test]
411 fn test_rex_result_roundtrip() {
412 let rex_response = RexResponse::new(RexData::Raw(
413 serde_json::to_vec(&json!({"key": "value", "number": 42})).unwrap(),
414 ));
415 let error = RexError::HttpStatusError {
416 status: 403,
417 reason: "Forbidden".to_string(),
418 };
419 let test_cases = vec![
420 RexOutput::Success(rex_response),
421 RexOutput::RexError(error),
422 RexOutput::UnserializableResponse("Invalid JSON".to_string()),
423 ];
424
425 for original in test_cases {
426 let serialized = serde_json::to_string(&original).unwrap();
427 let deserialized: RexOutput = serde_json::from_str(&serialized).unwrap();
428 assert_eq!(original, deserialized);
429 }
430 }
431
432 #[test]
433 fn test_rex_result_complex_nested_values() {
434 let complex_value = json!({
435 "nested": {
436 "array": [1, 2, 3],
437 "object": {"key": "value"},
438 "null": null,
439 "bool": true
440 }
441 });
442 let rex_response =
443 RexResponse::new(RexData::Raw(serde_json::to_vec(&complex_value).unwrap()));
444
445 let result = RexOutput::Success(rex_response.clone());
446 let json = serde_json::to_value(&result).unwrap();
447
448 assert_eq!(json["status"], "success");
449 assert_eq!(json["contents"], json!(rex_response));
450 }
451
452 #[test]
453 fn test_rex_result_empty_values() {
454 let rex_response = RexResponse::new(RexData::Raw(serde_json::to_vec(&json!({})).unwrap()));
456 let result = RexOutput::Success(rex_response.clone());
457 let json = serde_json::to_value(&result).unwrap();
458 assert_eq!(
459 json,
460 json!({
461 "status": "success",
462 "contents": rex_response
463 })
464 );
465
466 let result = RexOutput::UnserializableResponse("".to_string());
468 let json = serde_json::to_value(&result).unwrap();
469 assert_eq!(
470 json,
471 json!({
472 "status": "unserializable-response",
473 "contents": ""
474 })
475 );
476 }
477}