Skip to main content

workflow_nw/ipc/
error.rs

1use borsh::{BorshDeserialize, BorshSerialize};
2use serde::{Deserialize, Serialize};
3use thiserror::Error;
4use wasm_bindgen::prelude::JsValue;
5use workflow_core::channel::*;
6
7/// Errors produced by the IPC subsystem.
8#[derive(Error, Debug)]
9pub enum Error {
10    /// A custom, free-form error message.
11    #[error("{0}")]
12    Custom(String),
13
14    /// Underlying I/O error.
15    #[error("I/O error: {0}")]
16    IO(#[from] std::io::Error),
17
18    /// A JavaScript exception captured as a string.
19    #[error("Error: {0}")]
20    JsValue(String),
21
22    /// Failed to send a message over an IPC channel.
23    #[error("IPC channel send error")]
24    ChannelSendError,
25
26    /// Failed to receive a message from an IPC channel.
27    #[error("IPC channel receive error")]
28    ChannelRecvError,
29
30    /// Borsh serialization of a message failed.
31    #[error("BorshSerialize")]
32    BorshSerialize,
33
34    /// Borsh deserialization of a message failed.
35    #[error("BorshDeserialize {0}")]
36    BorshDeserialize(String),
37
38    /// Error contained within an IPC response.
39    #[error(transparent)]
40    IpcResponse(#[from] crate::ipc::error::ResponseError),
41
42    /// Error originating from a WASM callback invocation.
43    #[error(transparent)]
44    CallbackError(#[from] workflow_wasm::callback::CallbackError),
45
46    /// Generic channel error described by a message.
47    #[error("{0}")]
48    ChannelError(String),
49}
50
51impl From<String> for Error {
52    fn from(v: String) -> Self {
53        Self::Custom(v)
54    }
55}
56
57impl From<&str> for Error {
58    fn from(v: &str) -> Self {
59        Self::Custom(v.to_string())
60    }
61}
62
63impl From<JsValue> for Error {
64    fn from(v: JsValue) -> Self {
65        Self::JsValue(format!("{v:?}"))
66    }
67}
68
69impl From<Error> for JsValue {
70    fn from(err: Error) -> JsValue {
71        let s: String = err.to_string();
72        JsValue::from_str(&s)
73    }
74}
75
76impl<T> From<TrySendError<T>> for Error {
77    fn from(_: TrySendError<T>) -> Self {
78        Error::ChannelSendError
79    }
80}
81
82impl From<RecvError> for Error {
83    fn from(_: RecvError) -> Self {
84        Error::ChannelRecvError
85    }
86}
87
88impl<T> From<ChannelError<T>> for Error {
89    fn from(e: ChannelError<T>) -> Error {
90        Error::ChannelError(e.to_string())
91    }
92}
93
94/// Errors returned to the caller as part of an IPC response.
95#[derive(
96    Error, Debug, Clone, Eq, PartialEq, BorshSerialize, BorshDeserialize, Serialize, Deserialize,
97)]
98pub enum ResponseError {
99    /// The connection was closed before a response was received.
100    #[error("connection is closed")]
101    Close,
102    /// The RPC call timed out before completing.
103    #[error("RPC call timed out")]
104    Timeout,
105    /// The response contained no data.
106    #[error("no data")]
107    NoData,
108    /// The requested IPC method handler was not found.
109    #[error("IPC method not found")]
110    NotFound,
111    /// A mutex/lock was poisoned while handling the request.
112    #[error("resource lock error")]
113    PoisonError,
114    /// The request payload was not Borsh-encoded as expected.
115    #[error("not a borsh request")]
116    NonBorshRequest,
117    /// The request payload was not Serde-encoded as expected.
118    #[error("not a serde request")]
119    NonSerdeRequest,
120    /// The request could not be serialized.
121    #[error("request serialization error")]
122    ReqSerialize,
123    /// The request could not be deserialized.
124    #[error("request deserialization error")]
125    ReqDeserialize,
126    /// The response could not be serialized.
127    #[error("response serialization error")]
128    RespSerialize,
129    /// A notification payload could not be deserialized.
130    #[error("request deserialization error")]
131    NotificationDeserialize(String),
132    /// The response could not be deserialized.
133    #[error("response deserialization error")]
134    RespDeserialize(String),
135    /// Raw response data carried alongside the error.
136    #[error("data")]
137    Data(Vec<u8>),
138    /// A custom, free-form error message.
139    #[error("{0}")]
140    Custom(String),
141    /// Underlying WebSocket error
142    #[error("Receiver channel")]
143    ReceiveChannelRx,
144    /// Failed to forward a message into the receiver channel.
145    #[error("Receiver channel send")]
146    ReceiveChannelTx,
147}
148
149impl From<std::io::Error> for ResponseError {
150    fn from(_err: std::io::Error) -> Self {
151        ResponseError::RespSerialize
152    }
153}
154
155// impl<T> From<PoisonError<T>> for ResponseError {
156//     fn from(_error: PoisonError<T>) -> ResponseError {
157//         ResponseError::PoisonError
158//     }
159// }
160
161impl From<String> for ResponseError {
162    fn from(error: String) -> Self {
163        ResponseError::Custom(error)
164    }
165}
166
167impl From<&str> for ResponseError {
168    fn from(error: &str) -> Self {
169        ResponseError::Custom(error.to_string())
170    }
171}