use serde::{Deserialize, Serialize}; use serde_json::value::RawValue; use std::fmt; /// Convenience type for displaying errors. #[derive(Clone, Debug, PartialEq)] pub struct Mismatch { /// Expected value. pub expected: T, /// Actual value. pub got: T, } impl fmt::Display for Mismatch { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_fmt(format_args!("Expected: {}, Got: {}", self.expected, self.got)) } } /// Error that occurs when a call failed. #[derive(Debug, thiserror::Error)] pub enum CallError { /// Invalid params in the call. #[error("Invalid params in the call")] InvalidParams, /// The call failed (let jsonrpsee assign default error code and error message). #[error("RPC Call failed: {0}")] Failed(Box), /// Custom error with specific JSON-RPC error code, message and data. #[error("RPC Call failed: code: {code}, message: {message}, data: {data:?}")] Custom { /// JSON-RPC error code code: i32, /// Short description of the error. message: String, /// A primitive or structured value that contains additional information about the error. data: Option>, }, } /// Error type. #[derive(Debug, thiserror::Error)] pub enum Error { /// Error that occurs when a call failed. #[error("Server call failed: {0}")] Call(#[from] CallError), /// Networking error or error on the low-level protocol layer. #[error("Networking or low-level protocol error: {0}")] Transport(#[source] Box), /// JSON-RPC request error. #[error("JSON-RPC request error: {0:?}")] Request(String), /// Frontend/backend channel error. #[error("Frontend/backend channel error: {0}")] Internal(#[from] futures_channel::mpsc::SendError), /// Invalid response, #[error("Invalid response: {0}")] InvalidResponse(Mismatch), /// The background task has been terminated. #[error("The background task been terminated because: {0}; restart required")] RestartNeeded(String), /// Failed to parse the data. #[error("Parse error: {0}")] ParseError(#[from] serde_json::Error), /// Invalid subscription ID. #[error("Invalid subscription ID")] InvalidSubscriptionId, /// Invalid request ID. #[error("Invalid request ID")] InvalidRequestId, /// Client received a notification with an unregistered method #[error("Unregistered notification method")] UnregisteredNotification(String), /// A request with the same request ID has already been registered. #[error("A request with the same request ID has already been registered")] DuplicateRequestId, /// Method was already registered. #[error("Method: {0} was already registered")] MethodAlreadyRegistered(String), /// Method with that name has not yet been registered. #[error("Method: {0} has not yet been registered")] MethodNotFound(String), /// Subscribe and unsubscribe method names are the same. #[error("Cannot use the same method name for subscribe and unsubscribe, used: {0}")] SubscriptionNameConflict(String), /// Subscription got closed. #[error("Subscription closed: {0:?}")] SubscriptionClosed(SubscriptionClosedError), /// Request timeout #[error("Request timeout")] RequestTimeout, /// Configured max number of request slots exceeded. #[error("Configured max number of request slots exceeded")] MaxSlotsExceeded, /// Attempted to stop server that is already stopped. #[error("Attempted to stop server that is already stopped")] AlreadyStopped, /// List passed into `set_allowed_origins` was empty #[error("Must set at least one allowed value for the {0} header")] EmptyAllowList(&'static str), /// Custom error. #[error("Custom error: {0}")] Custom(String), } /// Error type with a special `subscription_closed` field to detect that /// a subscription has been closed to distinguish valid items produced /// by the server on the subscription stream from an error. #[derive(Deserialize, Serialize, Debug)] pub struct SubscriptionClosedError { subscription_closed: String, } impl From for SubscriptionClosedError { fn from(msg: String) -> Self { Self { subscription_closed: msg } } } /// Generic transport error. #[derive(Debug, thiserror::Error)] pub enum GenericTransportError { /// Request was too large. #[error("The request was too big")] TooLarge, /// Malformed request #[error("Malformed request")] Malformed, /// Concrete transport error. #[error("Transport error: {0}")] Inner(T), } impl From for Error { fn from(io_err: std::io::Error) -> Error { Error::Transport(Box::new(io_err)) } } impl From for Error { fn from(handshake_err: soketto::handshake::Error) -> Error { Error::Transport(Box::new(handshake_err)) } } impl From for Error { fn from(conn_err: soketto::connection::Error) -> Error { Error::Transport(Box::new(conn_err)) } } impl From for Error { fn from(hyper_err: hyper::Error) -> Error { Error::Transport(Box::new(hyper_err)) } }