use super::request_response::PortFactory;
use crate::{
port::{
BackpressureFn, BackpressureHandler, DegradationAction, DegradationFn, DegradationHandler,
client::Client,
},
prelude::BackpressureStrategy,
service,
};
use alloc::format;
use core::fmt::Debug;
use iceoryx2_bb_elementary_traits::zero_copy_send::ZeroCopySend;
use iceoryx2_cal::shm_allocator::AllocationStrategy;
use iceoryx2_log::fail;
use tiny_fn::tiny_fn;
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum ClientCreateError {
UnableToCreateDataSegment,
ExceedsMaxSupportedClients,
FailedToDeployThreadsafetyPolicy,
UnableToCreatePortTag,
}
impl core::fmt::Display for ClientCreateError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "ClientCreateError::{self:?}")
}
}
impl core::error::Error for ClientCreateError {}
tiny_fn! {
pub struct PreallocatedRequestsOverride = Fn(number_of_preallocated_requests: usize) -> usize;
}
impl<'a> Debug for PreallocatedRequestsOverride<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "PreallocatedRequestsOverride")
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct LocalClientConfig {
pub(crate) backpressure_strategy: BackpressureStrategy,
pub(crate) initial_max_slice_len: usize,
pub(crate) allocation_strategy: AllocationStrategy,
}
#[derive(Debug)]
pub struct PortFactoryClient<
'factory,
Service: service::Service,
RequestPayload: Debug + ZeroCopySend + ?Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + ZeroCopySend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> {
pub(crate) config: LocalClientConfig,
pub(crate) preallocate_number_of_requests_override: PreallocatedRequestsOverride<'static>,
pub(crate) request_degradation_handler: DegradationHandler<'static>,
pub(crate) response_degradation_handler: DegradationHandler<'static>,
pub(crate) backpressure_handler: Option<BackpressureHandler<'static>>,
pub(crate) factory: &'factory PortFactory<
Service,
RequestPayload,
RequestHeader,
ResponsePayload,
ResponseHeader,
>,
}
unsafe impl<
Service: service::Service,
RequestPayload: Debug + ZeroCopySend + ?Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + ZeroCopySend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> Send
for PortFactoryClient<
'_,
Service,
RequestPayload,
RequestHeader,
ResponsePayload,
ResponseHeader,
>
{
}
impl<
'factory,
Service: service::Service,
RequestPayload: Debug + ZeroCopySend + ?Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + ZeroCopySend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
>
PortFactoryClient<
'factory,
Service,
RequestPayload,
RequestHeader,
ResponsePayload,
ResponseHeader,
>
{
#[doc(hidden)]
pub unsafe fn __internal_partial_clone(&self) -> Self {
Self {
config: self.config,
factory: self.factory,
request_degradation_handler: DegradationHandler::new_with(DegradationAction::Warn),
response_degradation_handler: DegradationHandler::new_with(DegradationAction::Warn),
backpressure_handler: None,
preallocate_number_of_requests_override: PreallocatedRequestsOverride::new(|v| v),
}
}
pub(crate) fn new(
factory: &'factory PortFactory<
Service,
RequestPayload,
RequestHeader,
ResponsePayload,
ResponseHeader,
>,
) -> Self {
let defs = &factory
.service
.shared_node()
.config()
.defaults
.request_response;
Self {
config: LocalClientConfig {
backpressure_strategy: defs.client_backpressure_strategy,
initial_max_slice_len: 1,
allocation_strategy: defs.client_allocation_strategy,
},
preallocate_number_of_requests_override: PreallocatedRequestsOverride::new(|v| v),
request_degradation_handler: DegradationHandler::new_with(DegradationAction::Warn),
response_degradation_handler: DegradationHandler::new_with(DegradationAction::Warn),
backpressure_handler: None,
factory,
}
}
pub fn override_request_preallocation<F: Fn(usize) -> usize + 'static>(
mut self,
callback: F,
) -> Self {
self.preallocate_number_of_requests_override =
PreallocatedRequestsOverride::new(move |v| callback(v).clamp(1, v));
self
}
pub fn backpressure_strategy(mut self, value: BackpressureStrategy) -> Self {
self.config.backpressure_strategy = value;
self
}
pub fn set_request_degradation_handler<F: DegradationFn + 'static>(
mut self,
handler: F,
) -> Self {
self.request_degradation_handler = DegradationHandler::new(handler);
self
}
pub fn set_response_degradation_handler<F: DegradationFn + 'static>(
mut self,
handler: F,
) -> Self {
self.response_degradation_handler = DegradationHandler::new(handler);
self
}
pub fn set_backpressure_handler<F: BackpressureFn + 'static>(mut self, handler: F) -> Self {
self.backpressure_handler = Some(BackpressureHandler::new(handler));
self
}
pub fn create(
self,
) -> Result<
Client<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader>,
ClientCreateError,
> {
let origin = format!("{self:?}");
Ok(fail!(from origin,
when Client::new(self),
"Failed to create new Client port."))
}
}
impl<
Service: service::Service,
RequestPayload: Debug + ZeroCopySend,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + ZeroCopySend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> PortFactoryClient<'_, Service, [RequestPayload], RequestHeader, ResponsePayload, ResponseHeader>
{
pub fn initial_max_slice_len(mut self, value: usize) -> Self {
self.config.initial_max_slice_len = value;
self
}
pub fn allocation_strategy(mut self, value: AllocationStrategy) -> Self {
self.config.allocation_strategy = value;
self
}
}