use core::ops::{Deref, DerefMut};
use core::{fmt::Debug, marker::PhantomData};
use flatbuffers::InvalidFlatbuffer;
use iceoryx2_bb_concurrency::atomic::Ordering;
use iceoryx2_bb_elementary_traits::iceoryx_send::IceoryxSend;
use iceoryx2_bb_elementary_traits::testing::abandonable::Abandonable;
use iceoryx2_bb_elementary_traits::zero_copy_send::ZeroCopySend;
use iceoryx2_bb_flatbuffers::FlatbufferError;
use iceoryx2_cal::zero_copy_connection::ChannelId;
use crate::payload::number_of_elements;
use crate::port::details::chunk::ChunkMut;
use crate::port::details::chunk_mut_shared_state::ChunkMutSharedState;
use crate::service::marker::Flatbuffer;
use crate::{
pending_response::PendingResponse,
port::client::{ClientSharedState, RequestSendError},
service,
};
pub struct RequestMut<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ?Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> {
pub(crate) chunk: ChunkMut,
pub(crate) shared_state: ChunkMutSharedState<Service, ClientSharedState<Service>>,
pub(crate) was_sample_sent: bool,
pub(crate) channel_id: ChannelId,
pub(crate) _request_payload: PhantomData<RequestPayload>,
pub(crate) _request_header: PhantomData<RequestHeader>,
pub(crate) _response_payload: PhantomData<ResponsePayload>,
pub(crate) _response_header: PhantomData<ResponseHeader>,
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ?Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> Abandonable
for RequestMut<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader>
{
unsafe fn abandon_in_place(mut this: core::ptr::NonNull<Self>) {
let this = unsafe { this.as_mut() };
unsafe { core::ptr::drop_in_place(&mut this.shared_state) };
}
}
unsafe impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ?Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> Send for RequestMut<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader>
where
Service::ArcThreadSafetyPolicy<ClientSharedState<Service>>: Send + Sync,
{
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ?Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> Drop for RequestMut<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader>
{
fn drop(&mut self) {
let _ = self.shared_state.call(|s| -> Result<(), ()> {
s.release_request(self.was_sample_sent, self.header());
Ok(())
});
}
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ?Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> Debug for RequestMut<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader>
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"RequestMut<{}, {}, {}, {}, {}> {{ chunk: {:?}, was_sample_sent: {}, channel_id: {} }}",
core::any::type_name::<Service>(),
core::any::type_name::<RequestPayload>(),
core::any::type_name::<RequestHeader>(),
core::any::type_name::<ResponsePayload>(),
core::any::type_name::<ResponseHeader>(),
self.chunk,
self.was_sample_sent,
self.channel_id.value()
)
}
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ZeroCopySend,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> Deref for RequestMut<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader>
{
type Target = RequestPayload;
fn deref(&self) -> &Self::Target {
unsafe { &*self.chunk.payload_ptr().cast() }
}
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ZeroCopySend,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> Deref for RequestMut<Service, [RequestPayload], RequestHeader, ResponsePayload, ResponseHeader>
{
type Target = [RequestPayload];
fn deref(&self) -> &Self::Target {
let payload_size = self.shared_state.payload_size();
unsafe {
&*core::ptr::slice_from_raw_parts(
self.chunk.payload_ptr().cast(),
number_of_elements::<RequestPayload, _>(self.header(), payload_size),
)
}
}
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ZeroCopySend,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> DerefMut for RequestMut<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader>
{
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.chunk.payload_mut_ptr().cast() }
}
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ZeroCopySend,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> DerefMut
for RequestMut<Service, [RequestPayload], RequestHeader, ResponsePayload, ResponseHeader>
{
fn deref_mut(&mut self) -> &mut Self::Target {
let payload_size = self.shared_state.payload_size();
unsafe {
&mut *core::ptr::slice_from_raw_parts_mut(
self.chunk.payload_mut_ptr().cast(),
number_of_elements::<RequestPayload, _>(self.header(), payload_size),
)
}
}
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ?Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> RequestMut<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader>
{
pub fn header(&self) -> &service::header::request_response::RequestHeader {
unsafe { &*self.chunk.header_ptr().cast() }
}
pub fn user_header(&self) -> &RequestHeader {
unsafe { &*self.chunk.user_header_ptr().cast() }
}
pub fn user_header_mut(&mut self) -> &mut RequestHeader {
unsafe { &mut *self.chunk.user_header_mut_ptr().cast() }
}
pub fn send(
mut self,
) -> Result<
PendingResponse<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader>,
RequestSendError,
> {
let shared_state = self.shared_state.clone();
shared_state.call(|s| {
match s.send_request(&self.chunk, self.channel_id, self.header().request_id) {
Ok(number_of_server_connections) => {
s.loan_counter.fetch_sub(1, Ordering::Relaxed);
self.was_sample_sent = true;
let active_request = PendingResponse {
number_of_server_connections,
request: self,
_service: PhantomData,
_response_payload: PhantomData,
_response_header: PhantomData,
};
Ok(active_request)
}
Err(e) => Err(e),
}
})
}
}
impl<
Service: crate::service::Service,
RequestPayload,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> RequestMut<Service, Flatbuffer<RequestPayload>, RequestHeader, ResponsePayload, ResponseHeader>
{
pub fn payload_bytes(&self) -> &[u8] {
let payload_offset = self.header().payload_offset as usize;
let payload_ptr = self.chunk.payload_ptr();
let payload_len = self.header().number_of_elements as usize;
unsafe {
core::slice::from_raw_parts(
payload_ptr.add(payload_offset),
payload_len - payload_offset,
)
}
}
pub fn payload_root<'a>(
&'a self,
) -> Result<RequestPayload::Inner, FlatbufferError<InvalidFlatbuffer>>
where
RequestPayload: flatbuffers::Follow<'a> + flatbuffers::Verifiable,
{
Ok(flatbuffers::root::<RequestPayload>(self.payload_bytes())?)
}
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ZeroCopySend,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> RequestMut<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader>
{
pub fn payload(&self) -> &RequestPayload {
self.deref()
}
pub fn payload_mut(&mut self) -> &mut RequestPayload {
&mut *self
}
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ZeroCopySend,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> RequestMut<Service, [RequestPayload], RequestHeader, ResponsePayload, ResponseHeader>
{
pub fn payload(&self) -> &[RequestPayload] {
self.deref()
}
pub fn payload_mut(&mut self) -> &mut [RequestPayload] {
&mut *self
}
}