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}