Skip to content

Commit

Permalink
refactor: change json-rpc trait names, relax bounds (#1921)
Browse files Browse the repository at this point in the history
* refactor: change json-rpc trait names, relax bounds

* fix: missed one in a feature

* fix: alphabetize imports
  • Loading branch information
prestwich authored Jan 18, 2025
1 parent f257bf4 commit 21e1dc4
Show file tree
Hide file tree
Showing 19 changed files with 184 additions and 152 deletions.
4 changes: 2 additions & 2 deletions crates/json-rpc/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{ErrorPayload, RpcReturn};
use crate::{ErrorPayload, RpcRecv};
use serde_json::value::RawValue;

/// An RPC error.
Expand Down Expand Up @@ -55,7 +55,7 @@ pub enum RpcError<E, ErrResp = Box<RawValue>> {

impl<E, ErrResp> RpcError<E, ErrResp>
where
ErrResp: RpcReturn,
ErrResp: RpcRecv,
{
/// Instantiate a new `ErrorResp` from an error response.
pub const fn err_resp(err: ErrorPayload<ErrResp>) -> Self {
Expand Down
63 changes: 46 additions & 17 deletions crates/json-rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
#[macro_use]
extern crate tracing;

use serde::{de::DeserializeOwned, Serialize};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::fmt::Debug;

mod common;
Expand Down Expand Up @@ -105,33 +105,62 @@ pub use result::{
transform_response, transform_result, try_deserialize_ok, BorrowedRpcResult, RpcResult,
};

/// An object that can be used as a JSON-RPC parameter.
/// An object that can be sent over RPC.
///
/// This marker trait is blanket-implemented for every qualifying type. It is
/// used to indicate that a type can be used as a JSON-RPC parameter.
pub trait RpcParam: Serialize + Clone + Debug + Send + Sync + Unpin {}
/// used to indicate that a type can be sent in the body of a JSON-RPC message.
pub trait RpcSend: Serialize + Clone + Debug + Send + Sync + Unpin {}

impl<T> RpcParam for T where T: Serialize + Clone + Debug + Send + Sync + Unpin {}
impl<T> RpcSend for T where T: Serialize + Clone + Debug + Send + Sync + Unpin {}

/// An object that can be used as a JSON-RPC return value.
/// An object that can be received over RPC.
///
/// This marker trait is blanket-implemented for every qualifying type. It is
/// used to indicate that a type can be used as a JSON-RPC return value.
/// used to indicate that a type can be received in the body of a JSON-RPC
/// message.
///
/// # Note
///
/// We add the `'static` lifetime bound to indicate that the type can't borrow.
/// This is a simplification that makes it easier to use the types in client
/// code. It is not suitable for use in server code.
pub trait RpcReturn: DeserializeOwned + Debug + Send + Sync + Unpin + 'static {}
/// We add the `'static` lifetime to the supertraits to indicate that the type
/// can't borrow. This is a simplification that makes it easier to use the
/// types in client code. Servers may prefer borrowing, using the [`RpcBorrow`]
/// trait.
pub trait RpcRecv: DeserializeOwned + Debug + Send + Sync + Unpin + 'static {}

impl<T> RpcReturn for T where T: DeserializeOwned + Debug + Send + Sync + Unpin + 'static {}
impl<T> RpcRecv for T where T: DeserializeOwned + Debug + Send + Sync + Unpin + 'static {}

/// An object that can be used as a JSON-RPC parameter and return value.
/// An object that can be received over RPC, borrowing from the the
/// deserialization context.
///
/// This marker trait is blanket-implemented for every qualifying type. It is
/// used to indicate that a type can be used as both a JSON-RPC parameter and
/// return value.
pub trait RpcObject: RpcParam + RpcReturn {}
/// used to indicate that a type can be borrowed from the body of a wholly or
/// partially serialized JSON-RPC message.
pub trait RpcBorrow<'de>: Deserialize<'de> + Debug + Send + Sync + Unpin {}

impl<T> RpcObject for T where T: RpcParam + RpcReturn {}
impl<'de, T> RpcBorrow<'de> for T where T: Deserialize<'de> + Debug + Send + Sync + Unpin {}

/// An object that can be both sent and received over RPC.
///
/// This marker trait is blanket-implemented for every qualifying type. It is
/// used to indicate that a type can be both sent and received in the body of a
/// JSON-RPC message.
///
/// # Note
///
/// We add the `'static` lifetime to the supertraits to indicate that the type
/// can't borrow. This is a simplification that makes it easier to use the
/// types in client code. Servers may prefer borrowing, using the
/// [`BorrowedRpcObject`] trait.
pub trait RpcObject: RpcSend + RpcRecv {}

impl<T> RpcObject for T where T: RpcSend + RpcRecv {}

/// An object that can be both sent and received over RPC, borrowing from the
/// the deserialization context.
///
/// This marker trait is blanket-implemented for every qualifying type. It is
/// used to indicate that a type can be both sent and received in the body of a
/// JSON-RPC message, and can borrow from the deserialization context.
pub trait BorrowedRpcObject<'de>: RpcBorrow<'de> + RpcSend {}

impl<'de, T> BorrowedRpcObject<'de> for T where T: RpcBorrow<'de> + RpcSend {}
15 changes: 8 additions & 7 deletions crates/json-rpc/src/request.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{common::Id, RpcObject, RpcParam};
use crate::{common::Id, RpcBorrow, RpcSend};
use alloy_primitives::{keccak256, B256};
use serde::{
de::{DeserializeOwned, MapAccess},
Expand Down Expand Up @@ -105,7 +105,7 @@ pub type PartiallySerializedRequest = Request<Box<RawValue>>;

impl<Params> Request<Params>
where
Params: RpcParam,
Params: RpcSend,
{
/// Serialize the request parameters as a boxed [`RawValue`].
///
Expand All @@ -126,7 +126,7 @@ where
impl<Params> Request<&Params>
where
Params: ToOwned,
Params::Owned: RpcParam,
Params::Owned: RpcSend,
{
/// Clone the request, including the request parameters.
pub fn into_owned_params(self) -> Request<Params::Owned> {
Expand Down Expand Up @@ -164,7 +164,7 @@ where
// `jsonrpc` field
impl<Params> Serialize for Request<Params>
where
Params: RpcParam,
Params: RpcSend,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand All @@ -188,7 +188,7 @@ where

impl<'de, Params> Deserialize<'de> for Request<Params>
where
Params: RpcObject,
Params: RpcBorrow<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand All @@ -197,7 +197,7 @@ where
struct Visitor<Params>(PhantomData<Params>);
impl<'de, Params> serde::de::Visitor<'de> for Visitor<Params>
where
Params: RpcObject,
Params: RpcBorrow<'de>,
{
type Value = Request<Params>;

Expand Down Expand Up @@ -297,7 +297,7 @@ pub struct SerializedRequest {

impl<Params> std::convert::TryFrom<Request<Params>> for SerializedRequest
where
Params: RpcParam,
Params: RpcSend,
{
type Error = serde_json::Error;

Expand Down Expand Up @@ -390,6 +390,7 @@ impl Serialize for SerializedRequest {
#[cfg(test)]
mod test {
use super::*;
use crate::RpcObject;

fn test_inner<T: RpcObject + PartialEq>(t: T) {
let ser = serde_json::to_string(&t).unwrap();
Expand Down
10 changes: 5 additions & 5 deletions crates/json-rpc/src/response/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::{
marker::PhantomData,
};

use crate::RpcObject;
use crate::RpcSend;

const INTERNAL_ERROR: Cow<'static, str> = Cow::Borrowed("Internal error");

Expand Down Expand Up @@ -68,15 +68,15 @@ impl<E> ErrorPayload<E> {
/// and additional data.
pub const fn internal_error_with_obj(data: E) -> Self
where
E: RpcObject,
E: RpcSend,
{
Self { code: -32603, message: INTERNAL_ERROR, data: Some(data) }
}

/// Create a new error payload for an internal error with a custom message
pub const fn internal_error_with_message_and_obj(message: Cow<'static, str>, data: E) -> Self
where
E: RpcObject,
E: RpcSend,
{
Self { code: -32603, message, data: Some(data) }
}
Expand Down Expand Up @@ -129,7 +129,7 @@ impl<E> ErrorPayload<E> {

impl<T> From<T> for ErrorPayload<T>
where
T: std::error::Error + RpcObject,
T: std::error::Error + RpcSend,
{
fn from(value: T) -> Self {
Self { code: -32603, message: INTERNAL_ERROR, data: Some(value) }
Expand All @@ -138,7 +138,7 @@ where

impl<E> ErrorPayload<E>
where
E: RpcObject,
E: RpcSend,
{
/// Serialize the inner data into a [`RawValue`].
pub fn serialize_payload(&self) -> serde_json::Result<ErrorPayload> {
Expand Down
10 changes: 5 additions & 5 deletions crates/json-rpc/src/response/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{common::Id, RpcObject};
use crate::{common::Id, RpcSend};
use serde::{
de::{DeserializeOwned, MapAccess, Visitor},
ser::SerializeMap,
Expand Down Expand Up @@ -85,7 +85,7 @@ impl<Payload, ErrData> Response<Payload, ErrData> {
/// Create a new error response for an internal error with additional data.
pub const fn internal_error_with_obj(id: Id, data: ErrData) -> Self
where
ErrData: RpcObject,
ErrData: RpcSend,
{
Self { id, payload: ResponsePayload::Failure(ErrorPayload::internal_error_with_obj(data)) }
}
Expand All @@ -98,7 +98,7 @@ impl<Payload, ErrData> Response<Payload, ErrData> {
data: ErrData,
) -> Self
where
ErrData: RpcObject,
ErrData: RpcSend,
{
Self {
id,
Expand All @@ -121,8 +121,8 @@ impl<Payload, ErrData> Response<Payload, ErrData> {

impl<Payload, ErrData> Response<Payload, ErrData>
where
Payload: RpcObject,
ErrData: RpcObject,
Payload: RpcSend,
ErrData: RpcSend,
{
/// Serialize the payload of this response.
pub fn serialize_payload(&self) -> serde_json::Result<Response> {
Expand Down
10 changes: 5 additions & 5 deletions crates/json-rpc/src/response/payload.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{ErrorPayload, RpcObject};
use crate::{ErrorPayload, RpcSend};
use serde::{de::DeserializeOwned, Deserialize};
use serde_json::value::{to_raw_value, RawValue};
use std::borrow::{Borrow, Cow};
Expand Down Expand Up @@ -78,7 +78,7 @@ impl<Payload, ErrData> ResponsePayload<Payload, ErrData> {
/// and additional data.
pub const fn internal_error_with_obj(data: ErrData) -> Self
where
ErrData: RpcObject,
ErrData: RpcSend,
{
Self::Failure(ErrorPayload::internal_error_with_obj(data))
}
Expand All @@ -90,7 +90,7 @@ impl<Payload, ErrData> ResponsePayload<Payload, ErrData> {
data: ErrData,
) -> Self
where
ErrData: RpcObject,
ErrData: RpcSend,
{
Self::Failure(ErrorPayload::internal_error_with_message_and_obj(message, data))
}
Expand Down Expand Up @@ -124,8 +124,8 @@ impl<Payload, ErrData> ResponsePayload<Payload, ErrData> {

impl<Payload, ErrData> ResponsePayload<Payload, ErrData>
where
Payload: RpcObject,
ErrData: RpcObject,
Payload: RpcSend,
ErrData: RpcSend,
{
/// Convert the inner types into a [`RawValue`] by serializing them.
pub fn serialize_payload(&self) -> serde_json::Result<ResponsePayload> {
Expand Down
10 changes: 5 additions & 5 deletions crates/json-rpc/src/result.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Response, ResponsePayload, RpcError, RpcReturn};
use crate::{Response, ResponsePayload, RpcError, RpcRecv};
use serde_json::value::RawValue;
use std::borrow::Borrow;

Expand All @@ -24,7 +24,7 @@ pub type BorrowedRpcResult<'a, E> = RpcResult<&'a RawValue, E, &'a RawValue>;
/// [`Id`]: crate::Id
pub fn transform_response<T, E, ErrResp>(response: Response<T, ErrResp>) -> RpcResult<T, E, ErrResp>
where
ErrResp: RpcReturn,
ErrResp: RpcRecv,
{
match response {
Response { payload: ResponsePayload::Failure(err_resp), .. } => {
Expand All @@ -41,7 +41,7 @@ pub fn transform_result<T, E, ErrResp>(
response: Result<Response<T, ErrResp>, E>,
) -> Result<T, RpcError<E, ErrResp>>
where
ErrResp: RpcReturn,
ErrResp: RpcRecv,
{
match response {
Ok(resp) => transform_response(resp),
Expand All @@ -55,8 +55,8 @@ pub fn try_deserialize_ok<J, T, E, ErrResp>(
) -> RpcResult<T, E, ErrResp>
where
J: Borrow<RawValue>,
T: RpcReturn,
ErrResp: RpcReturn,
T: RpcRecv,
ErrResp: RpcRecv,
{
let json = result?;
let json = json.borrow().get();
Expand Down
14 changes: 7 additions & 7 deletions crates/provider/src/ext/debug.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! This module extends the Ethereum JSON-RPC provider with the Debug namespace's RPC methods.
use crate::Provider;
use alloy_json_rpc::RpcReturn;
use alloy_json_rpc::RpcRecv;
use alloy_network::Network;
use alloy_primitives::{hex, Bytes, TxHash, B256};
use alloy_rpc_types_debug::ExecutionWitness;
Expand Down Expand Up @@ -72,7 +72,7 @@ pub trait DebugApi<N>: Send + Sync {

/// Reruns the transaction specified by the hash and returns the trace in a specified format.
///
/// This method allows for the trace to be returned as a type that implements `RpcReturn` and
/// This method allows for the trace to be returned as a type that implements `RpcRecv` and
/// `serde::de::DeserializeOwned`.
///
/// [GethDebugTracingOptions] can be used to specify the trace options.
Expand All @@ -86,7 +86,7 @@ pub trait DebugApi<N>: Send + Sync {
trace_options: GethDebugTracingOptions,
) -> TransportResult<R>
where
R: RpcReturn + serde::de::DeserializeOwned;
R: RpcRecv + serde::de::DeserializeOwned;

/// Reruns the transaction specified by the hash and returns the trace as a JSON object.
///
Expand Down Expand Up @@ -122,7 +122,7 @@ pub trait DebugApi<N>: Send + Sync {

/// Reruns the transaction specified by the hash and returns the trace in a specified format.
///
/// This method allows for the trace to be returned as a type that implements `RpcReturn` and
/// This method allows for the trace to be returned as a type that implements `RpcRecv` and
/// `serde::de::DeserializeOwned`.
///
/// [GethDebugTracingOptions] can be used to specify the trace options.
Expand All @@ -137,7 +137,7 @@ pub trait DebugApi<N>: Send + Sync {
trace_options: GethDebugTracingCallOptions,
) -> TransportResult<R>
where
R: RpcReturn + serde::de::DeserializeOwned;
R: RpcRecv + serde::de::DeserializeOwned;

/// Reruns the transaction specified by the hash and returns the trace as a JSON object.
///
Expand Down Expand Up @@ -309,7 +309,7 @@ where
trace_options: GethDebugTracingOptions,
) -> TransportResult<R>
where
R: RpcReturn,
R: RpcRecv,
{
self.client().request("debug_traceTransaction", (hash, trace_options)).await
}
Expand Down Expand Up @@ -337,7 +337,7 @@ where
trace_options: GethDebugTracingCallOptions,
) -> TransportResult<R>
where
R: RpcReturn,
R: RpcRecv,
{
self.client().request("debug_traceCall", (tx, block, trace_options)).await
}
Expand Down
Loading

0 comments on commit 21e1dc4

Please sign in to comment.