From 68d1db0a2d3991e37c0994444de53ce6a31ca188 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Mon, 15 Jan 2024 19:00:25 +0100 Subject: [PATCH] chore: add helper functions to ResponsePacket --- crates/json-rpc/src/packet.rs | 60 ++++++++++++++++++++++++- crates/json-rpc/src/response/payload.rs | 2 +- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/crates/json-rpc/src/packet.rs b/crates/json-rpc/src/packet.rs index acd1b402491..18b2781ae72 100644 --- a/crates/json-rpc/src/packet.rs +++ b/crates/json-rpc/src/packet.rs @@ -1,4 +1,4 @@ -use crate::{Id, Response, SerializedRequest}; +use crate::{ErrorPayload, Id, Response, SerializedRequest}; use serde::{ de::{self, Deserializer, MapAccess, SeqAccess, Visitor}, Deserialize, Serialize, @@ -217,6 +217,41 @@ impl BorrowedResponsePacket<'_> { } impl ResponsePacket { + /// Returns `true` if the response payload is a success. + /// + /// For batch responses, this returns `true` if __all__ responses are successful. + pub fn is_success(&self) -> bool { + match self { + ResponsePacket::Single(single) => single.is_success(), + ResponsePacket::Batch(batch) => batch.iter().all(|res| res.is_success()), + } + } + + /// Returns `true` if the response payload is a success. + /// + /// For batch responses, this returns `true` there's at least one error response. + pub fn is_error(&self) -> bool { + match self { + ResponsePacket::Single(single) => single.is_error(), + ResponsePacket::Batch(batch) => batch.iter().any(|res| res.is_error()), + } + } + + /// Returns the [ErrorPayload] if the response is an error. + /// + /// For batch responses, this returns the first error response. + pub fn as_error(&self) -> Option<&ErrorPayload> { + self.iter_errors().next() + } + + /// Returns an iterator over the [ErrorPayload]s in the response. + pub fn iter_errors(&self) -> impl Iterator> + '_ { + match self { + ResponsePacket::Single(single) => ResponsePacketErrorsIter::Single(Some(single)), + ResponsePacket::Batch(batch) => ResponsePacketErrorsIter::Batch(batch.iter()), + } + } + /// Find responses by a list of IDs. /// /// This is intended to be used in conjunction with @@ -241,3 +276,26 @@ impl ResponsePacket { } } } + +/// An Iterator over the [ErrorPayload]s in a [ResponsePacket]. +#[derive(Debug, Clone)] +enum ResponsePacketErrorsIter<'a, Payload, ErrData> { + Single(Option<&'a Response>), + Batch(std::slice::Iter<'a, Response>), +} + +impl<'a, Payload, ErrData> Iterator for ResponsePacketErrorsIter<'a, Payload, ErrData> { + type Item = &'a ErrorPayload; + + fn next(&mut self) -> Option { + match self { + ResponsePacketErrorsIter::Single(single) => single.take()?.payload.as_error(), + ResponsePacketErrorsIter::Batch(batch) => loop { + let res = batch.next()?; + if let Some(err) = res.payload.as_error() { + return Some(err); + } + }, + } + } +} diff --git a/crates/json-rpc/src/response/payload.rs b/crates/json-rpc/src/response/payload.rs index 71d75b184cb..d4269fb4d94 100644 --- a/crates/json-rpc/src/response/payload.rs +++ b/crates/json-rpc/src/response/payload.rs @@ -44,7 +44,7 @@ impl BorrowedResponsePayload<'_> { } impl ResponsePayload { - /// Fallible conversion to the succesful payload. + /// Fallible conversion to the successful payload. pub const fn as_success(&self) -> Option<&Payload> { match self { ResponsePayload::Success(payload) => Some(payload),