use crate::client::ids::RequestId;
use crate::transport::BufferBound;
use std::marker::PhantomData;
use std::sync::Arc;
use async_trait::async_trait;
use crate::client::r#async::Client;
use crate::errors::Error;
use crate::messages::OutgoingMessages;
use crate::subscriptions::{DecoderContext, StreamDecoder, Subscription};
use crate::transport::{AsyncInternalSubscription, AsyncMessageBus};
pub(crate) struct RequestBuilder<'a> {
client: &'a Client,
request_id: RequestId,
}
impl<'a> RequestBuilder<'a> {
pub fn new(client: &'a Client) -> Self {
Self {
client,
request_id: client.mint_request_id(),
}
}
pub fn with_id(client: &'a Client, request_id: RequestId) -> Self {
Self { client, request_id }
}
pub fn request_id(&self) -> i32 {
self.request_id.raw()
}
pub async fn send<T>(self, message: Vec<u8>) -> Result<Subscription<T>, Error>
where
T: StreamDecoder<T> + Send + 'static,
{
let context = self.client.decoder_context();
let message_bus = self.client.message_bus.clone();
SubscriptionBuilder::<T>::new_with_components(context, message_bus)
.send_with_request_id(self.request_id, message)
.await
}
pub async fn send_bounded<T>(self, message: Vec<u8>, bound: BufferBound) -> Result<Subscription<T>, Error>
where
T: StreamDecoder<T> + Send + 'static,
{
let context = self.client.decoder_context();
let message_bus = self.client.message_bus.clone();
SubscriptionBuilder::<T>::new_with_components(context, message_bus)
.send_with_request_id_bounded(self.request_id, message, bound)
.await
}
pub async fn send_with_context<T>(self, message: Vec<u8>, context: DecoderContext) -> Result<Subscription<T>, Error>
where
T: StreamDecoder<T> + Send + 'static,
{
let message_bus = self.client.message_bus.clone();
SubscriptionBuilder::<T>::new_with_components(context, message_bus)
.send_with_request_id(self.request_id, message)
.await
}
pub async fn send_raw(self, message: Vec<u8>) -> Result<AsyncInternalSubscription, Error> {
self.client.send_request(self.request_id, message).await
}
}
pub(crate) struct SharedRequestBuilder<'a> {
client: &'a Client,
message_type: OutgoingMessages,
}
impl<'a> SharedRequestBuilder<'a> {
pub fn new(client: &'a Client, message_type: OutgoingMessages) -> Self {
Self { client, message_type }
}
pub async fn send_raw(self, message: Vec<u8>) -> Result<AsyncInternalSubscription, Error> {
self.client.send_shared_request(self.message_type, message).await
}
}
pub(crate) struct SubscriptionBuilder<T> {
message_bus: Arc<dyn AsyncMessageBus>,
context: DecoderContext,
_phantom: PhantomData<T>,
}
impl<T> SubscriptionBuilder<T>
where
T: Send + 'static,
{
pub fn new_with_components(context: DecoderContext, message_bus: Arc<dyn AsyncMessageBus>) -> Self {
Self {
message_bus,
context,
_phantom: PhantomData,
}
}
pub async fn send_with_request_id(self, request_id: RequestId, message: Vec<u8>) -> Result<Subscription<T>, Error>
where
T: StreamDecoder<T>,
{
let subscription = self.message_bus.send_request(request_id, message).await?;
Ok(Subscription::new_from_internal(
subscription,
self.message_bus.clone(),
Some(request_id.raw()),
None,
self.context,
))
}
pub async fn send_with_request_id_bounded(self, request_id: RequestId, message: Vec<u8>, bound: BufferBound) -> Result<Subscription<T>, Error>
where
T: StreamDecoder<T>,
{
let subscription = self.message_bus.send_request_bounded(request_id, message, bound).await?;
Ok(Subscription::new_from_internal(
subscription,
self.message_bus.clone(),
Some(request_id.raw()),
None,
self.context,
))
}
pub async fn send_shared(self, message_type: OutgoingMessages, message: Vec<u8>) -> Result<Subscription<T>, Error>
where
T: StreamDecoder<T>,
{
let subscription = self.message_bus.send_shared_request(message_type, message).await?;
Ok(Subscription::new_from_internal(
subscription,
self.message_bus.clone(),
None,
None,
self.context,
))
}
}
#[async_trait]
pub(crate) trait ClientRequestBuilders {
fn request(&self) -> RequestBuilder<'_>;
fn request_with_id(&self, request_id: RequestId) -> RequestBuilder<'_>;
fn shared_request(&self, message_type: OutgoingMessages) -> SharedRequestBuilder<'_>;
}
impl ClientRequestBuilders for Client {
fn request(&self) -> RequestBuilder<'_> {
RequestBuilder::new(self)
}
fn request_with_id(&self, request_id: RequestId) -> RequestBuilder<'_> {
RequestBuilder::with_id(self, request_id)
}
fn shared_request(&self, message_type: OutgoingMessages) -> SharedRequestBuilder<'_> {
SharedRequestBuilder::new(self, message_type)
}
}
pub(crate) trait SubscriptionBuilderExt {
fn subscription<T>(&self) -> SubscriptionBuilder<T>
where
T: Send + 'static;
}
impl SubscriptionBuilderExt for Client {
fn subscription<T>(&self) -> SubscriptionBuilder<T>
where
T: Send + 'static,
{
let context = self.decoder_context();
let message_bus = self.message_bus.clone();
SubscriptionBuilder::new_with_components(context, message_bus)
}
}
#[cfg(test)]
#[path = "async_tests.rs"]
mod tests;