use crate::{ErrorPayload, RpcSend};
use serde::{de::DeserializeOwned, Deserialize};
use serde_json::value::{to_raw_value, RawValue};
use std::borrow::{Borrow, Cow};
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ResponsePayload<Payload = Box<RawValue>, ErrData = Box<RawValue>> {
Success(Payload),
Failure(ErrorPayload<ErrData>),
}
pub type BorrowedResponsePayload<'a> = ResponsePayload<&'a RawValue, &'a RawValue>;
impl BorrowedResponsePayload<'_> {
pub fn into_owned(self) -> ResponsePayload {
match self {
Self::Success(payload) => ResponsePayload::Success(payload.to_owned()),
Self::Failure(error) => ResponsePayload::Failure(error.into_owned()),
}
}
}
impl<Payload, ErrData> ResponsePayload<Payload, ErrData> {
pub const fn parse_error() -> Self {
Self::Failure(ErrorPayload::parse_error())
}
pub const fn invalid_request() -> Self {
Self::Failure(ErrorPayload::invalid_request())
}
pub const fn method_not_found() -> Self {
Self::Failure(ErrorPayload::method_not_found())
}
pub const fn invalid_params() -> Self {
Self::Failure(ErrorPayload::invalid_params())
}
pub const fn internal_error() -> Self {
Self::Failure(ErrorPayload::internal_error())
}
pub const fn internal_error_message(message: Cow<'static, str>) -> Self {
Self::Failure(ErrorPayload::internal_error_message(message))
}
pub const fn internal_error_with_obj(data: ErrData) -> Self
where
ErrData: RpcSend,
{
Self::Failure(ErrorPayload::internal_error_with_obj(data))
}
pub const fn internal_error_with_message_and_obj(
message: Cow<'static, str>,
data: ErrData,
) -> Self
where
ErrData: RpcSend,
{
Self::Failure(ErrorPayload::internal_error_with_message_and_obj(message, data))
}
pub const fn as_success(&self) -> Option<&Payload> {
match self {
Self::Success(payload) => Some(payload),
_ => None,
}
}
pub const fn as_error(&self) -> Option<&ErrorPayload<ErrData>> {
match self {
Self::Failure(payload) => Some(payload),
_ => None,
}
}
pub fn try_into_success(self) -> Result<Payload, ErrorPayload<ErrData>> {
match self {
Self::Success(res) => Ok(res),
Self::Failure(error) => Err(error),
}
}
pub fn error_code(&self) -> Option<i64> {
self.as_error().map(|err| err.code)
}
pub fn error_data(&self) -> Option<&ErrData> {
self.as_error().and_then(|err| err.data.as_ref())
}
pub const fn is_success(&self) -> bool {
matches!(self, Self::Success(_))
}
pub const fn is_error(&self) -> bool {
matches!(self, Self::Failure(_))
}
}
impl<Payload, ErrData> ResponsePayload<Payload, ErrData>
where
Payload: RpcSend,
ErrData: RpcSend,
{
pub fn serialize_payload(&self) -> serde_json::Result<ResponsePayload> {
match self {
Self::Success(payload) => Ok(ResponsePayload::Success(to_raw_value(payload)?)),
Self::Failure(error) => Ok(ResponsePayload::Failure(error.serialize_payload()?)),
}
}
}
impl<'a, Payload, ErrData> ResponsePayload<Payload, ErrData>
where
Payload: AsRef<RawValue> + 'a,
{
pub fn try_success_as<T: Deserialize<'a>>(&'a self) -> Option<serde_json::Result<T>> {
self.as_success().map(|payload| serde_json::from_str(payload.as_ref().get()))
}
pub fn deserialize_success<T: DeserializeOwned>(
self,
) -> Result<ResponsePayload<T, ErrData>, Self> {
match self {
Self::Success(ref payload) => serde_json::from_str(payload.as_ref().get())
.map_or_else(|_| Err(self), |payload| Ok(ResponsePayload::Success(payload))),
Self::Failure(e) => Ok(ResponsePayload::Failure(e)),
}
}
}
impl<'a, Payload, Data> ResponsePayload<Payload, Data>
where
Data: Borrow<RawValue> + 'a,
{
pub fn try_error_as<T: Deserialize<'a>>(&'a self) -> Option<serde_json::Result<T>> {
self.as_error().and_then(|error| error.try_data_as::<T>())
}
pub fn deserialize_error<T: DeserializeOwned>(
self,
) -> Result<ResponsePayload<Payload, T>, Self> {
match self {
Self::Failure(err) => match err.deser_data() {
Ok(deser) => Ok(ResponsePayload::Failure(deser)),
Err(err) => Err(Self::Failure(err)),
},
Self::Success(payload) => Ok(ResponsePayload::Success(payload)),
}
}
}