Skip to main content

workflow_terminal/
error.rs

1//!
2//! Errors produced by [`workflow_terminal`](super)
3//!
4
5use downcast::DowncastError;
6use std::sync::PoisonError;
7use thiserror::Error;
8use wasm_bindgen::JsValue;
9use workflow_core::channel::{ChannelError, RecvError, SendError, TrySendError};
10
11#[derive(Debug, Error)]
12/// Errors produced by the terminal subsystem.
13pub enum Error {
14    /// A general-purpose error carrying a custom message.
15    #[error("{0}")]
16    Custom(String),
17    /// An error originating from JavaScript, captured as a string.
18    #[error("{0}")]
19    JsValue(String),
20    /// A lock was poisoned because another thread panicked while holding it.
21    #[error("Poison Error: {0}")]
22    PoisonError(String),
23    /// Receiving from a channel failed because it was closed.
24    #[error("Channel Receive Error")]
25    RecvError,
26    /// Sending on a channel failed.
27    #[error("Channel Send Error: {0}")]
28    SendError(String),
29    /// A non-blocking channel send failed (channel full or closed).
30    #[error("Channel TrySend Error: {0}")]
31    TrySendError(String),
32    /// An error originating from the DOM layer.
33    #[error(transparent)]
34    DomError(#[from] workflow_dom::error::Error),
35    /// A generic channel error.
36    #[error("Channel error: {0}")]
37    ChannelError(String),
38    /// An underlying I/O error.
39    #[error(transparent)]
40    Io(#[from] std::io::Error),
41    /// A downcast to a concrete type failed.
42    #[error("{0}")]
43    DowncastError(String),
44    /// The requested command verb was not registered.
45    #[error("command not found: {0}")]
46    CommandNotFound(String),
47    /// The user aborted the current operation (e.g. via Ctrl+C).
48    #[error("aborting...")]
49    UserAbort,
50    /// An error originating from a WASM callback.
51    #[error(transparent)]
52    CallbackError(#[from] workflow_wasm::callback::CallbackError),
53}
54
55impl From<String> for Error {
56    fn from(v: String) -> Self {
57        Self::Custom(v)
58    }
59}
60impl From<&str> for Error {
61    fn from(v: &str) -> Self {
62        Self::Custom(v.to_string())
63    }
64}
65
66impl From<JsValue> for Error {
67    fn from(v: JsValue) -> Self {
68        Self::JsValue(format!("{v:?}"))
69    }
70}
71
72impl<T> From<PoisonError<T>> for Error
73where
74    T: std::fmt::Debug,
75{
76    fn from(err: PoisonError<T>) -> Error {
77        Error::PoisonError(format!("{err:?}"))
78    }
79}
80
81impl From<RecvError> for Error {
82    fn from(_err: RecvError) -> Error {
83        Error::RecvError
84    }
85}
86
87impl<T> From<TrySendError<T>> for Error
88where
89    T: std::fmt::Debug,
90{
91    fn from(err: TrySendError<T>) -> Error {
92        Error::TrySendError(format!("{err:?}"))
93    }
94}
95
96impl<T> From<SendError<T>> for Error
97where
98    T: std::fmt::Debug,
99{
100    fn from(err: SendError<T>) -> Error {
101        Error::SendError(format!("{err:?}"))
102    }
103}
104
105impl From<Error> for String {
106    fn from(err: Error) -> String {
107        match err {
108            Error::Custom(s) => s,
109            _ => err.to_string(),
110        }
111    }
112}
113
114impl From<Error> for JsValue {
115    fn from(err: Error) -> JsValue {
116        let s: String = err.into();
117        JsValue::from_str(&s)
118    }
119}
120
121impl<T> From<ChannelError<T>> for Error {
122    fn from(err: ChannelError<T>) -> Error {
123        Error::ChannelError(err.to_string())
124    }
125}
126
127impl<T> From<DowncastError<T>> for Error {
128    fn from(err: DowncastError<T>) -> Error {
129        Error::DowncastError(err.to_string())
130    }
131}