alloy_json_rpc/response/
payload.rs

1use crate::{ErrorPayload, RpcSend};
2use serde::{de::DeserializeOwned, Deserialize};
3use serde_json::value::{to_raw_value, RawValue};
4use std::borrow::{Borrow, Cow};
5
6/// A JSON-RPC 2.0 response payload.
7///
8/// This enum covers both the success and error cases of a JSON-RPC 2.0
9/// response. It is used to represent the `result` and `error` fields of a
10/// response object.
11///
12/// ### Note
13///
14/// This type does not implement `Serialize` or `Deserialize` directly. It is
15/// deserialized as part of the [`Response`] type.
16///
17/// [`Response`]: crate::Response
18#[derive(Clone, Debug, PartialEq, Eq)]
19pub enum ResponsePayload<Payload = Box<RawValue>, ErrData = Box<RawValue>> {
20    /// A successful response payload.
21    Success(Payload),
22    /// An error response payload.
23    Failure(ErrorPayload<ErrData>),
24}
25
26/// A [`ResponsePayload`] that has been partially deserialized, borrowing its
27/// contents from the deserializer. This is used primarily for intermediate
28/// deserialization. Most users will not require it.
29///
30/// See the [top-level docs] for more info.
31///
32/// [top-level docs]: crate
33pub type BorrowedResponsePayload<'a> = ResponsePayload<&'a RawValue, &'a RawValue>;
34
35impl BorrowedResponsePayload<'_> {
36    /// Convert this borrowed response payload into an owned payload by copying
37    /// the data from the deserializer (if necessary).
38    pub fn into_owned(self) -> ResponsePayload {
39        match self {
40            Self::Success(payload) => ResponsePayload::Success(payload.to_owned()),
41            Self::Failure(error) => ResponsePayload::Failure(error.into_owned()),
42        }
43    }
44}
45
46impl<Payload, ErrData> ResponsePayload<Payload, ErrData> {
47    /// Create a new error payload for a parse error.
48    pub const fn parse_error() -> Self {
49        Self::Failure(ErrorPayload::parse_error())
50    }
51
52    /// Create a new error payload for an invalid request.
53    pub const fn invalid_request() -> Self {
54        Self::Failure(ErrorPayload::invalid_request())
55    }
56
57    /// Create a new error payload for a method not found error.
58    pub const fn method_not_found() -> Self {
59        Self::Failure(ErrorPayload::method_not_found())
60    }
61
62    /// Create a new error payload for an invalid params error.
63    pub const fn invalid_params() -> Self {
64        Self::Failure(ErrorPayload::invalid_params())
65    }
66
67    /// Create a new error payload for an internal error.
68    pub const fn internal_error() -> Self {
69        Self::Failure(ErrorPayload::internal_error())
70    }
71
72    /// Create a new error payload for an internal error with a custom message.
73    pub const fn internal_error_message(message: Cow<'static, str>) -> Self {
74        Self::Failure(ErrorPayload::internal_error_message(message))
75    }
76
77    /// Create a new error payload for an internal error with a custom message
78    /// and additional data.
79    pub const fn internal_error_with_obj(data: ErrData) -> Self
80    where
81        ErrData: RpcSend,
82    {
83        Self::Failure(ErrorPayload::internal_error_with_obj(data))
84    }
85
86    /// Create a new error payload for an internal error with a custom message
87    /// and additional data.
88    pub const fn internal_error_with_message_and_obj(
89        message: Cow<'static, str>,
90        data: ErrData,
91    ) -> Self
92    where
93        ErrData: RpcSend,
94    {
95        Self::Failure(ErrorPayload::internal_error_with_message_and_obj(message, data))
96    }
97
98    /// Fallible conversion to the successful payload.
99    pub const fn as_success(&self) -> Option<&Payload> {
100        match self {
101            Self::Success(payload) => Some(payload),
102            _ => None,
103        }
104    }
105
106    /// Fallible conversion to the error object.
107    pub const fn as_error(&self) -> Option<&ErrorPayload<ErrData>> {
108        match self {
109            Self::Failure(payload) => Some(payload),
110            _ => None,
111        }
112    }
113
114    /// Returns `true` if the response payload is a success.
115    pub const fn is_success(&self) -> bool {
116        matches!(self, Self::Success(_))
117    }
118
119    /// Returns `true` if the response payload is an error.
120    pub const fn is_error(&self) -> bool {
121        matches!(self, Self::Failure(_))
122    }
123}
124
125impl<Payload, ErrData> ResponsePayload<Payload, ErrData>
126where
127    Payload: RpcSend,
128    ErrData: RpcSend,
129{
130    /// Convert the inner types into a [`RawValue`] by serializing them.
131    pub fn serialize_payload(&self) -> serde_json::Result<ResponsePayload> {
132        match self {
133            Self::Success(payload) => Ok(ResponsePayload::Success(to_raw_value(payload)?)),
134            Self::Failure(error) => Ok(ResponsePayload::Failure(error.serialize_payload()?)),
135        }
136    }
137}
138
139impl<'a, Payload, ErrData> ResponsePayload<Payload, ErrData>
140where
141    Payload: AsRef<RawValue> + 'a,
142{
143    /// Attempt to deserialize the success payload, borrowing from the payload
144    /// if necessary.
145    ///
146    /// # Returns
147    /// - `None` if the payload is an error
148    /// - `Some(Ok(T))` if the payload is a success and can be deserialized
149    /// - `Some(Err(serde_json::Error))` if the payload is a success and can't be deserialized as
150    ///   `T`
151    pub fn try_success_as<T: Deserialize<'a>>(&'a self) -> Option<serde_json::Result<T>> {
152        self.as_success().map(|payload| serde_json::from_str(payload.as_ref().get()))
153    }
154
155    /// Deserialize a Success payload, if possible, transforming this type.
156    ///
157    /// # Returns
158    ///
159    /// - `Ok(ResponsePayload<T>)` if the payload is an error, or if the payload is a success and
160    ///   can be deserialized as `T`
161    /// - `Err(self)` if the payload is a success and can't be deserialized
162    pub fn deserialize_success<T: DeserializeOwned>(
163        self,
164    ) -> Result<ResponsePayload<T, ErrData>, Self> {
165        match self {
166            Self::Success(ref payload) => serde_json::from_str(payload.as_ref().get())
167                .map_or_else(|_| Err(self), |payload| Ok(ResponsePayload::Success(payload))),
168            Self::Failure(e) => Ok(ResponsePayload::Failure(e)),
169        }
170    }
171}
172
173impl<'a, Payload, Data> ResponsePayload<Payload, Data>
174where
175    Data: Borrow<RawValue> + 'a,
176{
177    /// Attempt to deserialize the error payload, borrowing from the payload if
178    /// necessary.
179    ///
180    /// # Returns
181    /// - `None` if the payload is a success
182    /// - `Some(Ok(T))` if the payload is an error and can be deserialized
183    /// - `Some(Err(serde_json::Error))` if the payload is an error and can't be deserialized as `T`
184    pub fn try_error_as<T: Deserialize<'a>>(&'a self) -> Option<serde_json::Result<T>> {
185        self.as_error().and_then(|error| error.try_data_as::<T>())
186    }
187
188    /// Deserialize an Error payload, if possible, transforming this type.
189    ///
190    /// # Returns
191    ///
192    /// - `Ok(ResponsePayload<Payload, T>)` if the payload is an error, or if the payload is an
193    ///   error and can be deserialized as `T`.
194    /// - `Err(self)` if the payload is an error and can't be deserialized.
195    pub fn deserialize_error<T: DeserializeOwned>(
196        self,
197    ) -> Result<ResponsePayload<Payload, T>, Self> {
198        match self {
199            Self::Failure(err) => match err.deser_data() {
200                Ok(deser) => Ok(ResponsePayload::Failure(deser)),
201                Err(err) => Err(Self::Failure(err)),
202            },
203            Self::Success(payload) => Ok(ResponsePayload::Success(payload)),
204        }
205    }
206}