seda_sdk_rs/promise.rs
1//! This module defines the `PromiseStatus` enum, which represents the status of a promise
2//! in the Seda runtime SDK. It can either be fulfilled with a result or rejected with an
3//! error message. The enum provides methods to handle the promise status and convert it from
4//! a [`core::result::Result`] type.
5
6use std::fmt::Debug;
7
8use serde::{Deserialize, Serialize};
9
10use crate::bytes::ToBytes;
11
12/// Represents the status of a promise, which can either be fulfilled or rejected.
13/// This enum is returned by the host VM after executing a promise action.
14// TODO: Fulfilled and Rejected could now just be our Bytes type.
15#[derive(Serialize, Deserialize, Clone, Debug)]
16pub enum PromiseStatus {
17 /// The promise completed successfully contains the bytes of the result if any.
18 Fulfilled(Option<Vec<u8>>),
19
20 /// There was an error executing this promise.
21 /// The error is represented as bytes, which can be a string or any other serialized form.
22 // TODO: Is there ever a case where Rejected isn't a string?
23 // HTTP rejections could be an object(but encoded in a string).
24 // Could private the type and then have methods or something.
25 Rejected(Vec<u8>),
26}
27
28impl PromiseStatus {
29 /// Helper function that immediately assumes that the promise has been
30 /// fulfilled and returns the value.
31 ///
32 /// # Panics
33 ///
34 /// Panics if the promise is not fulfilled.
35 ///
36 /// # Examples
37 ///
38 /// ```
39 /// use seda_sdk_rs::{promise::PromiseStatus, bytes::ToBytes};
40 /// let promise = PromiseStatus::Fulfilled(Some("Hello, world!".to_bytes().eject()));
41 /// assert_eq!(promise.fulfilled(), b"Hello, world!");
42 /// ```
43 pub fn fulfilled(self) -> Vec<u8> {
44 if let Self::Fulfilled(Some(value)) = self {
45 return value;
46 }
47
48 panic!("Promise is not fulfilled: {:?}", &self);
49 }
50
51 /// Parses the fulfilled value of the promise into the desired type.
52 ///
53 /// # Panics
54 ///
55 /// Panics if the promise is not fulfilled.
56 ///
57 /// # Errors
58 ///
59 /// Returns an error if the conversion from bytes to the desired type fails.
60 ///
61 /// # Examples
62 ///
63 /// ```
64 /// use seda_sdk_rs::{promise::PromiseStatus, bytes::ToBytes};
65 /// use serde_json::Value;
66 ///
67 /// let value = serde_json::json!({"key": "value"});
68 /// let promise = PromiseStatus::Fulfilled(Some(serde_json::to_vec(&value).unwrap()));
69 ///
70 /// let parsed: Value = promise.parse().unwrap();
71 /// assert_eq!(parsed, value);
72 /// ```
73 pub fn parse<T>(self) -> Result<T, serde_json::Error>
74 where
75 T: serde::de::DeserializeOwned,
76 {
77 let value = self.fulfilled();
78
79 serde_json::from_slice(&value)
80 }
81}
82
83impl<T: ToBytes, E: std::error::Error> From<Result<T, E>> for PromiseStatus {
84 fn from(value: Result<T, E>) -> Self {
85 match value {
86 Ok(fulfilled) => PromiseStatus::Fulfilled(Some(fulfilled.to_bytes().eject())),
87 Err(rejection) => PromiseStatus::Rejected(rejection.to_string().to_bytes().eject()),
88 }
89 }
90}
91
92impl<T: ToBytes, E: std::error::Error> From<Result<Option<T>, E>> for PromiseStatus {
93 fn from(value: Result<Option<T>, E>) -> Self {
94 match value {
95 Ok(fulfilled) => PromiseStatus::Fulfilled(fulfilled.map(|inner| inner.to_bytes().eject())),
96 Err(rejection) => PromiseStatus::Rejected(rejection.to_string().to_bytes().eject()),
97 }
98 }
99}