use crate::messages::ResponseMessage;
use crate::proto::decoders::DecodeProto;
use crate::proto::payload::ProtoPayload;
use crate::Error;
fn fold_one_shot<R>(
response: Option<Result<ResponseMessage, Error>>,
processor: impl FnOnce(&ResponseMessage) -> Result<R, Error>,
) -> Result<R, Error> {
match response {
Some(Ok(message)) => processor(&message),
Some(Err(e)) => Err(e),
None => Err(Error::UnexpectedEndOfStream),
}
}
pub(crate) fn empty_on_end_of_stream<R: Default>(error: Error) -> Result<R, Error> {
match error {
Error::UnexpectedEndOfStream => Ok(R::default()),
other => Err(other),
}
}
pub(crate) fn expect_proto<P, R>(decode: impl Fn(P) -> Result<R, Error>) -> impl Fn(&ResponseMessage) -> Result<R, Error>
where
P: ProtoPayload,
{
move |message| {
let bytes = message.expect_type(P::MESSAGE_ID)?.require_proto()?;
decode(P::decode_proto(bytes)?)
}
}
#[cfg(test)]
#[path = "request_helpers_tests.rs"]
mod tests;
#[cfg(feature = "sync")]
mod sync_helpers {
use crate::client::blocking::ClientRequestBuilders;
use crate::client::sync::Client;
use crate::messages::{OutgoingMessages, ResponseMessage};
use crate::Error;
pub fn one_shot_shared<R>(
client: &Client,
message_type: OutgoingMessages,
encoder: impl Fn() -> Result<Vec<u8>, Error>,
processor: impl Fn(&ResponseMessage) -> Result<R, Error>,
) -> Result<R, Error> {
crate::common::retry::blocking::retry_on_connection_reset(client, || {
let request = encoder()?;
let subscription = client.shared_request(message_type).send_raw(request)?;
super::fold_one_shot(subscription.next(), &processor)
})
}
pub fn one_shot_by_request_id<R>(
client: &Client,
encoder: impl Fn(i32) -> Result<Vec<u8>, Error>,
processor: impl Fn(&ResponseMessage) -> Result<R, Error>,
) -> Result<R, Error> {
crate::common::retry::blocking::retry_on_connection_reset(client, || {
let request_id = client.mint_request_id();
let request = encoder(request_id.raw())?;
let subscription = client.send_request(request_id, request)?;
super::fold_one_shot(subscription.next(), &processor)
})
}
}
#[cfg(feature = "async")]
mod async_helpers {
use crate::client::{Client, ClientRequestBuilders};
use crate::messages::{OutgoingMessages, ResponseMessage};
use crate::Error;
pub async fn one_shot_shared<R>(
client: &Client,
message_type: OutgoingMessages,
encoder: impl Fn() -> Result<Vec<u8>, Error>,
processor: impl Fn(&ResponseMessage) -> Result<R, Error>,
) -> Result<R, Error> {
crate::common::retry::retry_on_connection_reset(client, || async {
let request = encoder()?;
let mut subscription = client.shared_request(message_type).send_raw(request).await?;
super::fold_one_shot(subscription.next().await, &processor)
})
.await
}
pub async fn one_shot_by_request_id<R>(
client: &Client,
encoder: impl Fn(i32) -> Result<Vec<u8>, Error>,
processor: impl Fn(&ResponseMessage) -> Result<R, Error>,
) -> Result<R, Error> {
crate::common::retry::retry_on_connection_reset(client, || async {
let request_id = client.mint_request_id();
let request = encoder(request_id.raw())?;
let mut subscription = client.send_request(request_id, request).await?;
super::fold_one_shot(subscription.next().await, &processor)
})
.await
}
}
#[cfg(feature = "sync")]
pub mod blocking {
pub(crate) use super::sync_helpers::*;
}
#[cfg(all(feature = "sync", not(feature = "async")))]
#[allow(unused_imports)]
pub use sync_helpers::*;
#[cfg(feature = "async")]
pub use async_helpers::*;