Skip to main content

thruput_rpc_api/
prog_error.rs

1//! Program-level error wrapper.
2
3use std::fmt;
4
5/// Generic error type for RPC program implementations.
6///
7/// Wraps any thread-safe error for use by generated RPC service traits.
8/// Generated dispatchers map a returned `ProgramError` to
9/// [`RpcError::SystemError`](crate::RpcError::SystemError); the underlying
10/// error is not sent to the peer.
11///
12/// # Example
13///
14/// ```no_run
15/// use thruput_rpc_api::ProgramError;
16///
17/// fn load_config() -> Result<Vec<u8>, ProgramError> {
18///     let bytes = std::fs::read("config.bin")?;
19///     Ok(bytes)
20/// }
21/// ```
22#[derive(Debug)]
23pub struct ProgramError(Box<dyn std::error::Error + Send + Sync>);
24
25impl ProgramError {
26    /// Create a new ProgramError from any error type.
27    pub fn new<E>(err: E) -> Self
28    where
29        E: std::error::Error + Send + Sync + 'static,
30    {
31        Self(Box::new(err))
32    }
33
34    /// Create a ProgramError from a string message.
35    pub fn msg(msg: impl Into<String>) -> Self {
36        Self(msg.into().into())
37    }
38}
39
40impl std::error::Error for ProgramError {
41    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
42        self.0.source()
43    }
44}
45
46impl fmt::Display for ProgramError {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        write!(f, "rpc program error: {}", self.0)
49    }
50}
51
52impl From<std::io::Error> for ProgramError {
53    fn from(err: std::io::Error) -> Self {
54        Self::new(err)
55    }
56}
57
58impl From<Box<dyn std::error::Error + Send + Sync>> for ProgramError {
59    fn from(err: Box<dyn std::error::Error + Send + Sync>) -> Self {
60        Self(err)
61    }
62}