mrpc/
error.rs

1use rmpv::Value;
2use std::io;
3use thiserror::Error;
4
5/// Errors that can occur during RPC operations.
6#[derive(Error, Debug)]
7pub enum RpcError {
8    /// Error occurred during I/O operations.
9    #[error("I/O error: {0}")]
10    Io(io::Error),
11
12    /// Error occurred during MessagePack serialization.
13    #[error("Serialization error: {0}")]
14    Serialization(#[from] rmpv::encode::Error),
15
16    /// Error occurred during MessagePack deserialization.
17    #[error("Deserialization error: {0}")]
18    Deserialization(#[from] rmpv::decode::Error),
19
20    /// Error related to the RPC protocol.
21    #[error("Protocol error: {0}")]
22    Protocol(String),
23
24    /// Error returned by the RPC service implementation.
25    #[error("Service error: {0}")]
26    Service(ServiceError),
27
28    #[error("Connection disconnected")]
29    Disconnect,
30
31    /// Error occurred while trying to establish a connection.
32    #[error("Failed to connect to {0}")]
33    Connect(String),
34}
35
36/// An error that occurred during the execution of an RPC service method.
37///
38/// It consists of a name, which identifies the type of error, and a value, which can contain
39/// additional error details. This error type is used to convey service-specific errors back to the
40/// client. When sent over the RPC protocol, this error will be serialized into a map with "name"
41/// and "value" keys.
42#[derive(Error, Debug)]
43pub struct ServiceError {
44    pub name: String,
45    pub value: Value,
46}
47
48impl std::fmt::Display for ServiceError {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        write!(f, "Service error {}: {:?}", self.name, self.value)
51    }
52}
53
54impl From<ServiceError> for Value {
55    fn from(error: ServiceError) -> Self {
56        Value::Map(vec![
57            (
58                Value::String("name".into()),
59                Value::String(error.name.into()),
60            ),
61            (Value::String("value".into()), error.value),
62        ])
63    }
64}
65
66impl From<std::io::Error> for RpcError {
67    fn from(error: std::io::Error) -> Self {
68        if error.kind() == std::io::ErrorKind::UnexpectedEof {
69            RpcError::Disconnect
70        } else {
71            RpcError::Io(error)
72        }
73    }
74}
75
76pub type Result<T> = std::result::Result<T, RpcError>;