use crate::payload::number_of_elements;
use crate::port::LoanError;
use crate::port::details::chunk::ChunkMut;
use crate::port::details::chunk_mut_shared_state::ChunkMutSharedState;
use crate::{
port::publisher::PublisherSharedState,
sample_mut::SampleMut,
service::{header::publish_subscribe::Header, marker::Flatbuffer},
};
use core::marker::PhantomData;
use core::{fmt::Debug, mem::MaybeUninit};
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;
use iceoryx2_log::fail;
pub type FlatbufferMemory<Service> =
ResizableMemory<ShmPointer, ChunkMutSharedState<Service, PublisherSharedState<Service>>>;
pub struct SampleMutUninit<
Service: crate::service::Service,
Payload: IceoryxSend + Debug + ?Sized,
UserHeader: ZeroCopySend,
> {
shared_state: ChunkMutSharedState<Service, PublisherSharedState<Service>>,
chunk: ChunkMut,
flatbuffer_builder: Option<FlatBufferBuilder<'static, FlatbufferMemory<Service>>>,
_payload: PhantomData<Payload>,
_user_header: PhantomData<UserHeader>,
}
unsafe impl<
Service: crate::service::Service,
Payload: IceoryxSend + Debug + ?Sized,
UserHeader: ZeroCopySend,
> Send for SampleMutUninit<Service, Payload, UserHeader>
where
Service::ArcThreadSafetyPolicy<PublisherSharedState<Service>>: Send + Sync,
{
}
impl<
Service: crate::service::Service,
Payload: IceoryxSend + Debug + ?Sized,
UserHeader: ZeroCopySend,
> SampleMutUninit<Service, Payload, UserHeader>
{
#[doc(hidden)]
pub fn __internal_available_payload_memory(&self) -> usize {
self.shared_state
.call(|s| -> Result<usize, ()> {
Ok(self.chunk.size - s.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::<Header>() };
header.number_of_elements = memory_structure.payload_size;
header.payload_offset = memory_structure.payload_offset;
}
}
impl<Service: crate::service::Service, Payload, UserHeader: ZeroCopySend>
SampleMutUninit<Service, Flatbuffer<Payload>, UserHeader>
{
pub(crate) fn new_flatbuffer(
publisher_shared_state: &Service::ArcThreadSafetyPolicy<PublisherSharedState<Service>>,
chunk: ChunkMut,
) -> Result<Self, LoanError> {
let shared_state = fail!(from "SampleMutUninit::new_flatbuffer()",
when ChunkMutSharedState::new(publisher_shared_state, &chunk),
with LoanError::InternalFailure,
"Unable to create the sample since the underlying shared state could not be initialized.");
let mut new_self = Self {
flatbuffer_builder: None,
shared_state,
chunk,
_payload: PhantomData,
_user_header: 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<Payload>,
) -> SampleMut<Service, Flatbuffer<Payload>, UserHeader> {
self.flatbuffer_builder().finish(root, None);
let payload_ptr = self.flatbuffer_builder().finished_data().as_ptr();
self.__internal_finish_serialized(payload_ptr);
SampleMut {
shared_state: self.shared_state,
chunk: self.chunk,
_payload: PhantomData,
_user_header: PhantomData,
}
}
}
impl<
Service: crate::service::Service,
Payload: IceoryxSend + ZeroCopySend + Debug + ?Sized,
UserHeader: ZeroCopySend,
> SampleMutUninit<Service, Payload, UserHeader>
{
pub fn header(&self) -> &Header {
unsafe { &*(self.chunk.header_ptr().cast()) }
}
pub fn user_header(&self) -> &UserHeader {
unsafe { &*(self.chunk.user_header_ptr().cast()) }
}
pub fn user_header_mut(&mut self) -> &mut UserHeader {
unsafe { &mut *(self.chunk.user_header_mut_ptr().cast()) }
}
}
impl<
Service: crate::service::Service,
Payload: IceoryxSend + Debug + ?Sized,
UserHeader: ZeroCopySend,
> SampleMutUninit<Service, Payload, UserHeader>
{
pub(crate) fn new(
publisher_shared_state: &Service::ArcThreadSafetyPolicy<PublisherSharedState<Service>>,
chunk: ChunkMut,
) -> Result<Self, LoanError> {
let shared_state = fail!(from "SampleMutUninit::new()",
when ChunkMutSharedState::new(publisher_shared_state, &chunk),
with LoanError::InternalFailure,
"Unable to create the sample since the underlying shared state could not be initialized.");
Ok(Self {
flatbuffer_builder: None,
shared_state,
chunk,
_payload: PhantomData,
_user_header: PhantomData,
})
}
}
impl<
Service: crate::service::Service,
Payload: IceoryxSend + ZeroCopySend + Debug,
UserHeader: ZeroCopySend,
> SampleMutUninit<Service, MaybeUninit<Payload>, UserHeader>
{
pub fn payload(&self) -> &MaybeUninit<Payload> {
unsafe { &*(self.chunk.payload_ptr().cast()) }
}
pub fn payload_mut(&mut self) -> &mut MaybeUninit<Payload> {
unsafe { &mut *(self.chunk.payload_mut_ptr().cast()) }
}
pub fn write_payload(mut self, value: Payload) -> SampleMut<Service, Payload, UserHeader>
where
Payload: ZeroCopySend,
{
self.payload_mut().write(value);
unsafe { self.assume_init() }
}
pub unsafe fn assume_init(self) -> SampleMut<Service, Payload, UserHeader> {
SampleMut {
shared_state: self.shared_state,
chunk: self.chunk,
_payload: PhantomData,
_user_header: PhantomData,
}
}
}
impl<Service: crate::service::Service, Payload: Debug + ZeroCopySend, UserHeader: ZeroCopySend>
SampleMutUninit<Service, [MaybeUninit<Payload>], UserHeader>
{
pub fn payload(&self) -> &[MaybeUninit<Payload>] {
let payload_size = self.shared_state.payload_size();
unsafe {
&*core::ptr::slice_from_raw_parts(
self.chunk.payload_ptr().cast(),
number_of_elements::<Payload, _>(self.header(), payload_size),
)
}
}
pub fn payload_mut(&mut self) -> &mut [MaybeUninit<Payload>] {
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::<Payload, _>(self.header(), payload_size),
)
}
}
pub unsafe fn assume_init(self) -> SampleMut<Service, [Payload], UserHeader> {
SampleMut {
shared_state: self.shared_state,
chunk: self.chunk,
_payload: PhantomData,
_user_header: PhantomData,
}
}
pub fn write_from_fn<F: FnMut(usize) -> Payload>(
mut self,
mut initializer: F,
) -> SampleMut<Service, [Payload], UserHeader> {
for (i, element) in self.payload_mut().iter_mut().enumerate() {
element.write(initializer(i));
}
unsafe { self.assume_init() }
}
}
impl<
Service: crate::service::Service,
Payload: Debug + Copy + ZeroCopySend,
UserHeader: ZeroCopySend,
> SampleMutUninit<Service, [MaybeUninit<Payload>], UserHeader>
{
pub fn write_from_slice(
mut self,
value: &[Payload],
) -> SampleMut<Service, [Payload], UserHeader> {
self.payload_mut().copy_from_slice(unsafe {
core::mem::transmute::<&[Payload], &[MaybeUninit<Payload>]>(value)
});
unsafe { self.assume_init() }
}
}