use flatbuffers::{FlatBufferBuilder, WIPOffset};
use iceoryx2_bb_elementary_traits::{iceoryx_send::IceoryxSend, zero_copy_send::ZeroCopySend};
use iceoryx2_bb_flatbuffers::ResizableMemory;
use iceoryx2_cal::{shared_memory::ShmPointer, zero_copy_connection::ChannelId};
use iceoryx2_log::fail;
use crate::{
payload::number_of_elements,
port::{
LoanError,
client::ClientSharedState,
details::{chunk::ChunkMut, chunk_mut_shared_state::ChunkMutSharedState},
},
request_mut::RequestMut,
service::{self, marker::Flatbuffer},
};
use core::marker::PhantomData;
use core::{fmt::Debug, mem::MaybeUninit};
pub type FlatbufferMemory<Service> =
ResizableMemory<ShmPointer, ChunkMutSharedState<Service, ClientSharedState<Service>>>;
pub struct RequestMutUninit<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ?Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> {
chunk: ChunkMut,
shared_state: ChunkMutSharedState<Service, ClientSharedState<Service>>,
channel_id: ChannelId,
flatbuffer_builder: Option<FlatBufferBuilder<'static, FlatbufferMemory<Service>>>,
assume_init_was_called: bool,
_request_payload: PhantomData<RequestPayload>,
_request_header: PhantomData<RequestHeader>,
_response_payload: PhantomData<ResponsePayload>,
_response_header: PhantomData<ResponseHeader>,
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ?Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> Drop
for RequestMutUninit<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader>
{
fn drop(&mut self) {
if !self.assume_init_was_called {
let _ = self.shared_state.call(|s| -> Result<(), ()> {
let header = unsafe { &*self.chunk.header_ptr().cast() };
s.release_request(false, header);
Ok(())
});
}
}
}
unsafe impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ?Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> Send for RequestMutUninit<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,
> Debug
for RequestMutUninit<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader>
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"RequestMutUninit {{ chunk: {:?}, channel_id: {:?} }}",
self.chunk, self.channel_id
)
}
}
impl<
Service: crate::service::Service,
RequestPayload,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
>
RequestMutUninit<
Service,
Flatbuffer<RequestPayload>,
RequestHeader,
ResponsePayload,
ResponseHeader,
>
{
pub(crate) fn new_flatbuffer(
shared_state: &Service::ArcThreadSafetyPolicy<ClientSharedState<Service>>,
chunk: ChunkMut,
channel_id: ChannelId,
) -> Result<Self, LoanError> {
let shared_state = fail!(from "RequestMutUninit::new_flatbuffer()",
when ChunkMutSharedState::new(shared_state, &chunk),
with LoanError::InternalFailure,
"Unable to create the request since the underlying shared state could not be initialized.");
let mut new_self = Self {
flatbuffer_builder: None,
shared_state,
chunk,
channel_id,
assume_init_was_called: false,
_request_header: PhantomData,
_request_payload: PhantomData,
_response_header: PhantomData,
_response_payload: PhantomData,
};
new_self.flatbuffer_builder = Some(FlatBufferBuilder::new_in(
new_self.__internal_create_resizable_memory(),
));
Ok(new_self)
}
pub fn flatbuffer_builder(
&mut self,
) -> &mut FlatBufferBuilder<'static, FlatbufferMemory<Service>> {
self.flatbuffer_builder
.as_mut()
.expect("Flatbuffer builder is set when using Flatbuffer marker.")
}
pub fn assume_init(
mut self,
root: WIPOffset<RequestPayload>,
) -> RequestMut<
Service,
Flatbuffer<RequestPayload>,
RequestHeader,
ResponsePayload,
ResponseHeader,
> {
self.flatbuffer_builder().finish(root, None);
let payload_ptr = self.flatbuffer_builder().finished_data().as_ptr();
self.__internal_finish_serialized(payload_ptr);
self.assume_init_was_called = true;
RequestMut {
chunk: self.chunk.clone(),
shared_state: self.shared_state.clone(),
was_sample_sent: false,
channel_id: self.channel_id,
_request_payload: PhantomData,
_request_header: PhantomData,
_response_header: PhantomData,
_response_payload: PhantomData,
}
}
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ?Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> RequestMutUninit<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader>
{
#[doc(hidden)]
pub fn __internal_available_payload_memory(&self) -> usize {
self.shared_state
.call(|s| -> Result<usize, ()> {
Ok(self.chunk.size - s.request_sender.message_type_details.all_headers_len())
})
.expect("Always returns ok.")
}
#[doc(hidden)]
pub fn __internal_create_resizable_memory(&self) -> FlatbufferMemory<Service> {
self.shared_state.create_resizable_memory(&self.chunk)
}
#[doc(hidden)]
pub fn __internal_finish_serialized(&mut self, payload_ptr: *const u8) {
let memory_structure = self.shared_state.memory_structure(payload_ptr);
self.chunk = memory_structure.chunk;
let header = unsafe {
&mut *self
.chunk
.header_mut_ptr()
.cast::<crate::service::header::request_response::RequestHeader>()
};
header.number_of_elements = memory_structure.payload_size;
header.payload_offset = memory_structure.payload_offset;
}
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ZeroCopySend + ?Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
> RequestMutUninit<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader>
{
pub(crate) fn new(
shared_state: &Service::ArcThreadSafetyPolicy<ClientSharedState<Service>>,
chunk: ChunkMut,
channel_id: ChannelId,
) -> Result<Self, LoanError> {
let shared_state = fail!(from "RequestMutUninit::new()",
when ChunkMutSharedState::new(shared_state, &chunk),
with LoanError::InternalFailure,
"Unable to create the request since the underlying shared state could not be initialized.");
Ok(Self {
flatbuffer_builder: None,
shared_state,
chunk,
channel_id,
assume_init_was_called: false,
_request_payload: PhantomData,
_request_header: PhantomData,
_response_payload: PhantomData,
_response_header: PhantomData,
})
}
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() }
}
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + IceoryxSend + ZeroCopySend,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
>
RequestMutUninit<
Service,
MaybeUninit<RequestPayload>,
RequestHeader,
ResponsePayload,
ResponseHeader,
>
{
pub fn payload(&self) -> &MaybeUninit<RequestPayload> {
unsafe { &*self.chunk.payload_ptr().cast() }
}
pub fn payload_mut(&mut self) -> &mut MaybeUninit<RequestPayload> {
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,
>
RequestMutUninit<
Service,
[MaybeUninit<RequestPayload>],
RequestHeader,
ResponsePayload,
ResponseHeader,
>
{
pub fn payload(&self) -> &[MaybeUninit<RequestPayload>] {
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),
)
}
}
pub fn payload_mut(&mut self) -> &mut [MaybeUninit<RequestPayload>] {
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 + ZeroCopySend + Sized,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
>
RequestMutUninit<
Service,
MaybeUninit<RequestPayload>,
RequestHeader,
ResponsePayload,
ResponseHeader,
>
{
pub fn write_payload(
mut self,
value: RequestPayload,
) -> RequestMut<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader> {
self.payload_mut().write(value);
unsafe { self.assume_init() }
}
pub unsafe fn assume_init(
mut self,
) -> RequestMut<Service, RequestPayload, RequestHeader, ResponsePayload, ResponseHeader> {
self.assume_init_was_called = true;
RequestMut {
chunk: self.chunk.clone(),
shared_state: self.shared_state.clone(),
was_sample_sent: false,
channel_id: self.channel_id,
_request_payload: PhantomData,
_request_header: PhantomData,
_response_header: PhantomData,
_response_payload: PhantomData,
}
}
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + ZeroCopySend,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
>
RequestMutUninit<
Service,
[MaybeUninit<RequestPayload>],
RequestHeader,
ResponsePayload,
ResponseHeader,
>
{
pub unsafe fn assume_init(
self,
) -> RequestMut<Service, [RequestPayload], RequestHeader, ResponsePayload, ResponseHeader> {
let this = core::mem::ManuallyDrop::new(self);
RequestMut {
chunk: this.chunk.clone(),
shared_state: unsafe { core::ptr::read(&this.shared_state) },
was_sample_sent: false,
channel_id: this.channel_id,
_request_payload: PhantomData,
_request_header: PhantomData,
_response_header: PhantomData,
_response_payload: PhantomData,
}
}
pub fn write_from_fn<F: FnMut(usize) -> RequestPayload>(
mut self,
mut initializer: F,
) -> RequestMut<Service, [RequestPayload], RequestHeader, ResponsePayload, ResponseHeader> {
for (i, element) in self.payload_mut().iter_mut().enumerate() {
element.write(initializer(i));
}
unsafe { self.assume_init() }
}
}
impl<
Service: crate::service::Service,
RequestPayload: Debug + Copy + ZeroCopySend,
RequestHeader: Debug + ZeroCopySend,
ResponsePayload: Debug + IceoryxSend + ?Sized,
ResponseHeader: Debug + ZeroCopySend,
>
RequestMutUninit<
Service,
[MaybeUninit<RequestPayload>],
RequestHeader,
ResponsePayload,
ResponseHeader,
>
{
pub fn write_from_slice(
mut self,
value: &[RequestPayload],
) -> RequestMut<Service, [RequestPayload], RequestHeader, ResponsePayload, ResponseHeader> {
self.payload_mut().copy_from_slice(unsafe {
core::mem::transmute::<&[RequestPayload], &[MaybeUninit<RequestPayload>]>(value)
});
unsafe { self.assume_init() }
}
}