pub trait RpcErrCodec:
Send
+ Sized
+ 'static
+ Unpin {
// Required methods
fn encode<C: Codec>(&self, codec: &C) -> EncodedErr;
fn decode<C: Codec>(codec: &C, buf: Result<u32, &[u8]>) -> Result<Self, ()>;
fn fmt(&self, f: &mut Formatter<'_>) -> Result;
}Expand description
Serialize and Deserialize trait for custom RpcError
There is only two forms for rpc transport layer, u32 and String, choose one of them.
Because Rust does not allow overlapping impl, we only imple RpcErrCodec trait by default for the following types:
- ()
- from i8 to u32
- String
- nix::errno::Errno
If you use other type as error, you can implement manually:
§Example with serde_derive
use serde_derive::{Serialize, Deserialize};
use razor_stream::{Codec, error::{RpcErrCodec, RpcIntErr, EncodedErr}};
use strum::Display;
#[derive(Serialize, Deserialize, Debug)]
pub enum MyError {
NoSuchFile,
TooManyRequest,
}
impl RpcErrCodec for MyError {
#[inline(always)]
fn encode<C: Codec>(&self, codec: &C) -> EncodedErr {
match codec.encode(self) {
Ok(buf)=>EncodedErr::Buf(buf),
Err(())=>EncodedErr::Rpc(RpcIntErr::Encode),
}
}
#[inline(always)]
fn decode<C: Codec>(codec: &C, buf: Result<u32, &[u8]>) -> Result<Self, ()> {
if let Err(b) = buf {
return codec.decode(b);
} else {
Err(())
}
}
#[inline(always)]
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f)
}
}§Example with num_enum
use num_enum::TryFromPrimitive;
use razor_stream::{Codec, error::{RpcErrCodec, RpcIntErr, EncodedErr}};
// Define your error codes as a C-like enum with explicit values
// You can use num_enum's TryFromPrimitive for safer deserialization
#[derive(Debug, Clone, Copy, PartialEq, TryFromPrimitive)]
#[repr(u32)]
pub enum MyRpcErrorCode {
/// Service is not available
ServiceUnavailable = 1,
/// Request timed out
RequestTimeout = 2,
/// Invalid parameter
InvalidParameter = 3,
/// Resource not found
NotFound = 4,
}
impl RpcErrCodec for MyRpcErrorCode {
#[inline(always)]
fn encode<C: Codec>(&self, _codec: &C) -> EncodedErr {
// Manual conversion to u32 (no IntoPrimitive needed)
let code: u32 = *self as u32;
EncodedErr::Num(code)
}
#[inline(always)]
fn decode<C: Codec>(_codec: &C, buf: Result<u32, &[u8]>) -> Result<Self, ()> {
if let Ok(code) = buf {
// Using num_enum for safe deserialization (TryFromPrimitive)
return MyRpcErrorCode::try_from(code).map_err(|_| ());
}
Err(())
}
#[inline(always)]
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f)
}
}Required Methods§
fn encode<C: Codec>(&self, codec: &C) -> EncodedErr
fn decode<C: Codec>(codec: &C, buf: Result<u32, &[u8]>) -> Result<Self, ()>
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.