rpc: Add an RpcError type.
This could have been a trait instead, but I don't know whether that's smart or not. There is a lot of opportunity for refactoring here.
This commit is contained in:
parent
dec23c1cf6
commit
dce9c530ec
|
@ -4396,6 +4396,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tor-error",
|
||||
"typetag",
|
||||
]
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ once_cell = "1"
|
|||
paste = "1"
|
||||
serde = { version = "1.0.103", features = ["derive"] }
|
||||
thiserror = "1"
|
||||
tor-error = { path = "../tor-error/", version = "0.4.1" }
|
||||
typetag = "0.2.7"
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -11,14 +11,11 @@ use futures::future::BoxFuture;
|
|||
use once_cell::sync::Lazy;
|
||||
|
||||
use crate::typeid::ConstTypeId_;
|
||||
use crate::{Command, Context, Object};
|
||||
use crate::{Command, Context, Object, RpcError};
|
||||
|
||||
/// The return type from an RPC function.
|
||||
#[doc(hidden)]
|
||||
pub type RpcResult = Result<
|
||||
Box<dyn erased_serde::Serialize + Send + 'static>,
|
||||
Box<dyn erased_serde::Serialize + Send + 'static>,
|
||||
>;
|
||||
pub type RpcResult = Result<Box<dyn erased_serde::Serialize + Send + 'static>, RpcError>;
|
||||
|
||||
// A boxed future holding the result of an RPC command.
|
||||
type RpcResultFuture = BoxFuture<'static, RpcResult>;
|
||||
|
@ -81,8 +78,7 @@ impl InvokeEntry_ {
|
|||
/// }
|
||||
///
|
||||
/// rpc::rpc_invoke_fn!{
|
||||
/// // XXXX wrong error type.
|
||||
///
|
||||
|
||||
/// // Note that the return type of this function must be a Result, and must be
|
||||
/// // `Serialize + Send + 'static`.
|
||||
/// async fn example(obj: ExampleObject, cmd: ExampleCommand, ctx) -> Result<ExampleResult, String> {
|
||||
|
@ -129,7 +125,7 @@ macro_rules! rpc_invoke_fn {
|
|||
$name(obj, cmd, ctx).map(|r| {
|
||||
let r: $crate::RpcResult = match r {
|
||||
Ok(v) => Ok(Box::new(v)),
|
||||
Err(e) => Err(Box::new(e))
|
||||
Err(e) => Err($crate::RpcError::from(e))
|
||||
};
|
||||
r
|
||||
}).boxed()
|
||||
|
@ -227,7 +223,7 @@ mod test {
|
|||
|
||||
rpc_invoke_fn! {
|
||||
/// Hello there
|
||||
async fn invoke(_obj: Animal, cmd: SayHi, _ctx) -> Result<Hello, String> {
|
||||
async fn invoke(_obj: Animal, cmd: SayHi, _ctx) -> Result<Hello, crate::RpcError> {
|
||||
Ok(Hello{ name: format!("{:?}", cmd) })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
//! Error-related functionality for RPC functions.
|
||||
|
||||
/// An error type returned by failing RPC commands.
|
||||
#[derive(serde::Serialize)]
|
||||
pub struct RpcError {
|
||||
/// A human-readable message.
|
||||
message: String,
|
||||
/// An error code inspired by json-rpc.
|
||||
code: i32,
|
||||
/// The ErrorKind of this error.
|
||||
#[serde(serialize_with = "ser_kind")]
|
||||
kind: tor_error::ErrorKind,
|
||||
/// An underlying serializable object, if any, to be sent along with the
|
||||
/// error.
|
||||
data: Option<Box<dyn erased_serde::Serialize + Send>>,
|
||||
}
|
||||
|
||||
impl<T> From<T> for RpcError
|
||||
where
|
||||
T: std::error::Error + tor_error::HasKind + serde::Serialize + Send + 'static,
|
||||
{
|
||||
fn from(value: T) -> Self {
|
||||
let message = value.to_string();
|
||||
let code = -12345; // TODO RPC: this is wrong.
|
||||
let kind = value.kind();
|
||||
let boxed: Box<dyn erased_serde::Serialize + Send> = Box::new(value);
|
||||
let data = Some(boxed);
|
||||
RpcError {
|
||||
message,
|
||||
code,
|
||||
kind,
|
||||
data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ser_kind<S: serde::Serializer>(kind: &tor_error::ErrorKind, s: S) -> Result<S::Ok, S::Error> {
|
||||
// TODO RPC: this format is wrong and temporary.
|
||||
s.serialize_str(&format!("{:?}", kind))
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for RpcError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("RpcError")
|
||||
.field("message", &self.message)
|
||||
.field("code", &self.code)
|
||||
.field("kind", &self.kind)
|
||||
.field("data", &self.data.as_ref().map(|_| "..."))
|
||||
.finish()
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
mod cmd;
|
||||
pub mod dispatch;
|
||||
mod err;
|
||||
mod obj;
|
||||
#[doc(hidden)]
|
||||
pub mod typeid;
|
||||
|
@ -13,6 +14,7 @@ use std::sync::Arc;
|
|||
|
||||
pub use cmd::Command;
|
||||
pub use dispatch::invoke_command;
|
||||
pub use err::RpcError;
|
||||
pub use obj::{Object, ObjectId};
|
||||
|
||||
#[doc(hidden)]
|
||||
|
|
Loading…
Reference in New Issue