diff --git a/doc/release-notes/iceoryx2-unreleased.md b/doc/release-notes/iceoryx2-unreleased.md index 8f095bd7d..8362aa404 100644 --- a/doc/release-notes/iceoryx2-unreleased.md +++ b/doc/release-notes/iceoryx2-unreleased.md @@ -38,6 +38,7 @@ * Rename `NodeEvent` into `WaitEvent` [#390](https://github.com/eclipse-iceoryx/iceoryx2/issues/390) * Bazel support for the Rust crates [#349](https://github.com/eclipse-iceoryx/iceoryx2/issues/349) * Remove ACL dependency [#457](https://github.com/eclipse-iceoryx/iceoryx2/issues/457) +* Publish Subscribe Header contains number of elements contained in a `Sample` [#498](https://github.com/eclipse-iceoryx/iceoryx2/issues/498) ### Workflow @@ -72,3 +73,5 @@ // ... } ``` + +2. Removed `payload_type_layout()` from `publish_subscribe::Header`. diff --git a/iceoryx2-bb/posix/tests/unix_datagram_socket_tests.rs b/iceoryx2-bb/posix/tests/unix_datagram_socket_tests.rs index 173b007fa..9f504a262 100644 --- a/iceoryx2-bb/posix/tests/unix_datagram_socket_tests.rs +++ b/iceoryx2-bb/posix/tests/unix_datagram_socket_tests.rs @@ -14,7 +14,6 @@ use iceoryx2_bb_container::semantic_string::SemanticString; use iceoryx2_bb_posix::barrier::*; use iceoryx2_bb_posix::config::*; use iceoryx2_bb_posix::creation_mode::*; -use iceoryx2_bb_posix::directory::Directory; use iceoryx2_bb_posix::file::*; use iceoryx2_bb_posix::file_descriptor::*; use iceoryx2_bb_posix::socket_ancillary::*; diff --git a/iceoryx2-ffi/cxx/include/iox2/header_publish_subscribe.hpp b/iceoryx2-ffi/cxx/include/iox2/header_publish_subscribe.hpp index ac29d5ed7..a548ea9a8 100644 --- a/iceoryx2-ffi/cxx/include/iox2/header_publish_subscribe.hpp +++ b/iceoryx2-ffi/cxx/include/iox2/header_publish_subscribe.hpp @@ -30,8 +30,8 @@ class HeaderPublishSubscribe { /// Returns the [`UniquePublisherId`] of the source [`Publisher`]. auto publisher_id() const -> UniquePublisherId; - /// Returns the [`Layout`] of the corresponding payload. - auto payload_type_layout() const -> iox::Layout; + /// Returns the number of [`Payload`] elements in the received [`Sample`]. + auto number_of_elements() const -> uint64_t; private: template diff --git a/iceoryx2-ffi/cxx/src/header_publish_subscribe.cpp b/iceoryx2-ffi/cxx/src/header_publish_subscribe.cpp index d8c0389af..3ac5932ec 100644 --- a/iceoryx2-ffi/cxx/src/header_publish_subscribe.cpp +++ b/iceoryx2-ffi/cxx/src/header_publish_subscribe.cpp @@ -51,10 +51,7 @@ auto HeaderPublishSubscribe::publisher_id() const -> UniquePublisherId { return UniquePublisherId { id_handle }; } -auto HeaderPublishSubscribe::payload_type_layout() const -> iox::Layout { - auto size = iox2_publish_subscribe_header_payload_type_size(&m_handle); - auto alignment = iox2_publish_subscribe_header_payload_type_alignment(&m_handle); - - return iox::Layout::create(size, alignment).expect("Payload layout is always valid."); +auto HeaderPublishSubscribe::number_of_elements() const -> uint64_t { + return iox2_publish_subscribe_header_number_of_elements(&m_handle); } } // namespace iox2 diff --git a/iceoryx2-ffi/ffi/src/api/publish_subscribe_header.rs b/iceoryx2-ffi/ffi/src/api/publish_subscribe_header.rs index 374a463ed..fe18c5e7d 100644 --- a/iceoryx2-ffi/ffi/src/api/publish_subscribe_header.rs +++ b/iceoryx2-ffi/ffi/src/api/publish_subscribe_header.rs @@ -154,7 +154,12 @@ pub unsafe extern "C" fn iox2_publish_subscribe_header_publisher_id( *id_handle_ptr = (*storage_ptr).as_handle(); } -/// Returns the payloads type size. +/// Returns the number of elements of the payload. +/// The element size is defined via this call when creating a new service +/// [`crate::iox2_service_builder_pub_sub_set_payload_type_details()`]. +/// So if the payload is defined with alignment 8 and size 16 and this function returns 5. It +/// means that the payload consists of 5 elements of size 16 and every element is 8 byte aligned. +/// Therefore, the payload pointer points to a memory region with 5 * 16 = 80 bytes. /// /// # Arguments /// @@ -165,35 +170,13 @@ pub unsafe extern "C" fn iox2_publish_subscribe_header_publisher_id( /// /// * `header_handle` is valid and non-null #[no_mangle] -pub unsafe extern "C" fn iox2_publish_subscribe_header_payload_type_size( +pub unsafe extern "C" fn iox2_publish_subscribe_header_number_of_elements( header_handle: iox2_publish_subscribe_header_h_ref, -) -> usize { +) -> u64 { header_handle.assert_non_null(); let header = &mut *header_handle.as_type(); - header.value.as_ref().payload_type_layout().size() + header.value.as_ref().number_of_elements() } - -/// Returns the payloads type alignment. -/// -/// # Arguments -/// -/// * `handle` is valid, non-null and was initialized with -/// [`iox2_sample_header()`](crate::iox2_sample_header) -/// -/// # Safety -/// -/// * `header_handle` is valid and non-null -#[no_mangle] -pub unsafe extern "C" fn iox2_publish_subscribe_header_payload_type_alignment( - header_handle: iox2_publish_subscribe_header_h_ref, -) -> usize { - header_handle.assert_non_null(); - - let header = &mut *header_handle.as_type(); - - header.value.as_ref().payload_type_layout().align() -} - // END C API diff --git a/iceoryx2-ffi/ffi/src/api/publisher.rs b/iceoryx2-ffi/ffi/src/api/publisher.rs index 7989d3de6..142b68e45 100644 --- a/iceoryx2-ffi/ffi/src/api/publisher.rs +++ b/iceoryx2-ffi/ffi/src/api/publisher.rs @@ -192,7 +192,7 @@ unsafe fn send_copy( // loan_slice_uninit(1) <= 1 is correct here since it defines the number of // slice elements not bytes. The element was set via TypeDetails and has a // defined size and alignment. - let mut sample = match publisher.loan_slice_uninit(1) { + let mut sample = match publisher.loan_custom_payload(1) { Ok(sample) => sample, Err(e) => return e.into_c_int(), }; @@ -383,7 +383,7 @@ pub unsafe extern "C" fn iox2_publisher_loan( let publisher = &mut *publisher_handle.as_type(); match publisher.service_type { - iox2_service_type_e::IPC => match publisher.value.as_ref().ipc.loan_slice_uninit(1) { + iox2_service_type_e::IPC => match publisher.value.as_ref().ipc.loan_custom_payload(1) { Ok(sample) => { let (sample_struct_ptr, deleter) = init_sample_struct_ptr(sample_struct_ptr); (*sample_struct_ptr).init( @@ -396,7 +396,7 @@ pub unsafe extern "C" fn iox2_publisher_loan( } Err(error) => error.into_c_int(), }, - iox2_service_type_e::LOCAL => match publisher.value.as_ref().local.loan_slice_uninit(1) { + iox2_service_type_e::LOCAL => match publisher.value.as_ref().local.loan_custom_payload(1) { Ok(sample) => { let (sample_struct_ptr, deleter) = init_sample_struct_ptr(sample_struct_ptr); (*sample_struct_ptr).init( diff --git a/iceoryx2-ffi/ffi/src/api/service_builder.rs b/iceoryx2-ffi/ffi/src/api/service_builder.rs index f03ccd556..b60a00b86 100644 --- a/iceoryx2-ffi/ffi/src/api/service_builder.rs +++ b/iceoryx2-ffi/ffi/src/api/service_builder.rs @@ -15,7 +15,7 @@ use crate::api::{iox2_service_type_e, AssertNonNullHandle, HandleToType}; use iceoryx2::prelude::*; -use iceoryx2::service::builder::publish_subscribe::CustomHeaderMarker; +use iceoryx2::service::builder::publish_subscribe::{CustomHeaderMarker, CustomPayloadMarker}; use iceoryx2::service::builder::{ event::Builder as ServiceBuilderEvent, publish_subscribe::Builder as ServiceBuilderPubSub, Builder as ServiceBuilderBase, @@ -29,8 +29,8 @@ use core::mem::MaybeUninit; // BEGIN types definition pub(super) type UserHeaderFfi = CustomHeaderMarker; -pub(super) type PayloadFfi = [u8]; -pub(super) type UninitPayloadFfi = [MaybeUninit]; +pub(super) type PayloadFfi = [CustomPayloadMarker]; +pub(super) type UninitPayloadFfi = [MaybeUninit]; pub(super) union ServiceBuilderUnionNested { pub(super) base: ManuallyDrop>, diff --git a/iceoryx2-ffi/ffi/src/api/subscriber.rs b/iceoryx2-ffi/ffi/src/api/subscriber.rs index af0ab03e0..e041c6ad1 100644 --- a/iceoryx2-ffi/ffi/src/api/subscriber.rs +++ b/iceoryx2-ffi/ffi/src/api/subscriber.rs @@ -273,7 +273,7 @@ pub unsafe extern "C" fn iox2_subscriber_receive( let subscriber = &mut *subscriber_handle.as_type(); match subscriber.service_type { - iox2_service_type_e::IPC => match subscriber.value.as_ref().ipc.receive() { + iox2_service_type_e::IPC => match subscriber.value.as_ref().ipc.receive_custom_payload() { Ok(Some(sample)) => { let (sample_struct_ptr, deleter) = init_sample_struct_ptr(sample_struct_ptr); (*sample_struct_ptr).init( @@ -286,19 +286,21 @@ pub unsafe extern "C" fn iox2_subscriber_receive( Ok(None) => (), Err(error) => return error.into_c_int(), }, - iox2_service_type_e::LOCAL => match subscriber.value.as_ref().local.receive() { - Ok(Some(sample)) => { - let (sample_struct_ptr, deleter) = init_sample_struct_ptr(sample_struct_ptr); - (*sample_struct_ptr).init( - subscriber.service_type, - SampleUnion::new_local(sample), - deleter, - ); - *sample_handle_ptr = (*sample_struct_ptr).as_handle(); + iox2_service_type_e::LOCAL => { + match subscriber.value.as_ref().local.receive_custom_payload() { + Ok(Some(sample)) => { + let (sample_struct_ptr, deleter) = init_sample_struct_ptr(sample_struct_ptr); + (*sample_struct_ptr).init( + subscriber.service_type, + SampleUnion::new_local(sample), + deleter, + ); + *sample_handle_ptr = (*sample_struct_ptr).as_handle(); + } + Ok(None) => (), + Err(error) => return error.into_c_int(), } - Ok(None) => (), - Err(error) => return error.into_c_int(), - }, + } } IOX2_OK diff --git a/iceoryx2/src/port/publisher.rs b/iceoryx2/src/port/publisher.rs index 9ef12e57a..ce4b9fb37 100644 --- a/iceoryx2/src/port/publisher.rs +++ b/iceoryx2/src/port/publisher.rs @@ -108,6 +108,7 @@ use crate::port::update_connections::{ConnectionFailure, UpdateConnections}; use crate::port::DegrationAction; use crate::raw_sample::RawSampleMut; use crate::sample_mut_uninit::SampleMutUninit; +use crate::service::builder::publish_subscribe::CustomPayloadMarker; use crate::service::config_scheme::{connection_config, data_segment_config}; use crate::service::dynamic_config::publish_subscribe::{PublisherDetails, SubscriberDetails}; use crate::service::header::publish_subscribe::Header; @@ -115,6 +116,7 @@ use crate::service::naming_scheme::{ data_segment_name, extract_publisher_id_from_connection, extract_subscriber_id_from_connection, }; use crate::service::port_factory::publisher::{LocalPublisherConfig, UnableToDeliverStrategy}; +use crate::service::static_config::message_type_details::TypeVariant; use crate::service::static_config::publish_subscribe::{self}; use crate::service::{self, ServiceState}; use crate::{config, sample_mut::SampleMut}; @@ -138,6 +140,7 @@ use iceoryx2_cal::zero_copy_connection::{ ZeroCopyConnection, ZeroCopyCreationError, ZeroCopySendError, ZeroCopySender, }; use iceoryx2_pal_concurrency_sync::iox_atomic::{IoxAtomicBool, IoxAtomicU64, IoxAtomicUsize}; +use std::any::TypeId; use std::cell::UnsafeCell; use std::fmt::Debug; use std::sync::atomic::Ordering; @@ -528,7 +531,11 @@ impl DataSegment { /// Sending endpoint of a publish-subscriber based communication. #[derive(Debug)] -pub struct Publisher { +pub struct Publisher< + Service: service::Service, + Payload: Debug + ?Sized + 'static, + UserHeader: Debug, +> { pub(crate) data_segment: Arc>, dynamic_publisher_handle: Option, payload_size: usize, @@ -738,30 +745,31 @@ impl .sample_layout(number_of_elements) } - fn payload_layout(&self, number_of_elements: usize) -> Layout { + fn user_header_ptr(&self, header: *const Header) -> *const u8 { self.data_segment .subscriber_connections .static_config .message_type_details - .payload_layout(number_of_elements) + .user_header_ptr_from_header(header.cast()) + .cast() } - fn user_header_ptr(&self, header: *const Header) -> *const u8 { + fn payload_ptr(&self, header: *const Header) -> *const u8 { self.data_segment .subscriber_connections .static_config .message_type_details - .user_header_ptr_from_header(header.cast()) + .payload_ptr_from_header(header.cast()) .cast() } - fn payload_ptr(&self, header: *const Header) -> *const u8 { + fn payload_type_variant(&self) -> TypeVariant { self.data_segment .subscriber_connections .static_config .message_type_details - .payload_ptr_from_header(header.cast()) - .cast() + .payload + .variant } } @@ -837,12 +845,7 @@ impl let user_header_ptr = self.user_header_ptr(header_ptr) as *mut UserHeader; let payload_ptr = self.payload_ptr(header_ptr) as *mut MaybeUninit; - unsafe { - header_ptr.write(Header::new( - self.data_segment.port_id, - Layout::new::(), - )) - }; + unsafe { header_ptr.write(Header::new(self.data_segment.port_id, 1)) }; let sample = unsafe { RawSampleMut::new_unchecked(header_ptr, user_header_ptr, payload_ptr) }; @@ -974,6 +977,18 @@ impl &self, slice_len: usize, ) -> Result], UserHeader>, PublisherLoanError> + { + // required since Rust does not support generic specializations or negative traits + debug_assert!(TypeId::of::() != TypeId::of::()); + + unsafe { self.loan_slice_uninit_impl(slice_len, slice_len) } + } + + unsafe fn loan_slice_uninit_impl( + &self, + slice_len: usize, + underlying_number_of_slice_elements: usize, + ) -> Result], UserHeader>, PublisherLoanError> { let max_slice_len = self.data_segment.config.max_slice_len; if max_slice_len < slice_len { @@ -988,24 +1003,13 @@ impl let user_header_ptr = self.user_header_ptr(header_ptr) as *mut UserHeader; let payload_ptr = self.payload_ptr(header_ptr) as *mut MaybeUninit; - unsafe { - header_ptr.write(Header::new( - self.data_segment.port_id, - self.payload_layout(slice_len), - )) - }; - - let slice_len_adjusted_to_payload_type_details = - self.payload_size * slice_len / core::mem::size_of::(); + unsafe { header_ptr.write(Header::new(self.data_segment.port_id, slice_len as _)) }; let sample = unsafe { RawSampleMut::new_unchecked( header_ptr, user_header_ptr, - core::slice::from_raw_parts_mut( - payload_ptr, - slice_len_adjusted_to_payload_type_details, - ), + core::slice::from_raw_parts_mut(payload_ptr, underlying_number_of_slice_elements), ) }; @@ -1018,6 +1022,31 @@ impl ) } } + +impl + Publisher +{ + /// # Safety + /// + /// * slice_len != 1 only when payload TypeVariant == Dynamic + /// * The number_of_elements in the [`Header`](crate::service::header::publish_subscribe::Header) + /// is set to `slice_len` + /// * The [`SampleMutUninit`] will contain `slice_len` * `MessageTypeDetails::payload.size` + /// elements of type [`CustomPayloadMarker`]. + #[doc(hidden)] + pub unsafe fn loan_custom_payload( + &self, + slice_len: usize, + ) -> Result< + SampleMutUninit], UserHeader>, + PublisherLoanError, + > { + // TypeVariant::Dynamic == slice and only here it makes sense to loan more than one element + debug_assert!(slice_len == 1 || self.payload_type_variant() == TypeVariant::Dynamic); + + self.loan_slice_uninit_impl(slice_len, self.payload_size * slice_len) + } +} //////////////////////// // END: sliced API //////////////////////// diff --git a/iceoryx2/src/port/subscriber.rs b/iceoryx2/src/port/subscriber.rs index 6626a5aa5..e1767eb63 100644 --- a/iceoryx2/src/port/subscriber.rs +++ b/iceoryx2/src/port/subscriber.rs @@ -31,6 +31,7 @@ //! # } //! ``` +use std::any::TypeId; use std::cell::UnsafeCell; use std::fmt::Debug; use std::marker::PhantomData; @@ -46,6 +47,7 @@ use iceoryx2_cal::{shared_memory::*, zero_copy_connection::*}; use crate::port::DegrationAction; use crate::sample::SampleDetails; +use crate::service::builder::publish_subscribe::CustomPayloadMarker; use crate::service::dynamic_config::publish_subscribe::{PublisherDetails, SubscriberDetails}; use crate::service::header::publish_subscribe::Header; use crate::service::port_factory::subscriber::SubscriberConfig; @@ -102,7 +104,11 @@ impl std::error::Error for SubscriberCreateError {} /// The receiving endpoint of a publish-subscribe communication. #[derive(Debug)] -pub struct Subscriber { +pub struct Subscriber< + Service: service::Service, + Payload: Debug + ?Sized + 'static, + UserHeader: Debug, +> { dynamic_subscriber_handle: Option, publisher_connections: PublisherConnections, to_be_removed_connections: UnsafeCell>>>, @@ -443,13 +449,13 @@ impl pub fn receive( &self, ) -> Result>, SubscriberReceiveError> { + debug_assert!(TypeId::of::() != TypeId::of::()); + Ok(self.receive_impl()?.map(|(details, absolute_address)| { let header_ptr = absolute_address as *const Header; let user_header_ptr = self.user_header_ptr(header_ptr).cast(); let payload_ptr = self.payload_ptr(header_ptr).cast(); - - let payload_layout = unsafe { (*header_ptr).payload_type_layout() }; - let number_of_elements = payload_layout.size() / core::mem::size_of::(); + let number_of_elements = unsafe { (*header_ptr).number_of_elements() }; Sample { details, @@ -457,7 +463,51 @@ impl RawSample::::new_slice_unchecked( header_ptr, user_header_ptr, - core::slice::from_raw_parts(payload_ptr, number_of_elements), + core::slice::from_raw_parts(payload_ptr, number_of_elements as _), + ) + }, + } + })) + } +} + +impl + Subscriber +{ + /// # Safety + /// + /// * The number_of_elements in the [`Header`](crate::service::header::publish_subscribe::Header) + /// corresponds to the payload type details that where overridden in + /// `MessageTypeDetails::payload.size`. + /// If the `payload.size == 8` a value for number_of_elements of 5 means that there are + /// 5 elements of size 8 stored in the [`Sample`]. + /// * When the payload.size == 8 and the number of elements if 5, it means that the sample + /// will contain a slice of 8 * 5 = 40 [`CustomPayloadMarker`]s or 40 bytes. + #[doc(hidden)] + pub unsafe fn receive_custom_payload( + &self, + ) -> Result>, SubscriberReceiveError> + { + Ok(self.receive_impl()?.map(|(details, absolute_address)| { + let header_ptr = absolute_address as *const Header; + let user_header_ptr = self.user_header_ptr(header_ptr).cast(); + let payload_ptr = self.payload_ptr(header_ptr).cast(); + let number_of_elements = unsafe { (*header_ptr).number_of_elements() }; + let number_of_bytes = number_of_elements as usize + * self + .static_config + .publish_subscribe() + .message_type_details + .payload + .size; + + Sample { + details, + ptr: unsafe { + RawSample::::new_slice_unchecked( + header_ptr, + user_header_ptr, + core::slice::from_raw_parts(payload_ptr, number_of_bytes), ) }, } diff --git a/iceoryx2/src/service/builder/publish_subscribe.rs b/iceoryx2/src/service/builder/publish_subscribe.rs index 5acd0cbaa..7eae4ff59 100644 --- a/iceoryx2/src/service/builder/publish_subscribe.rs +++ b/iceoryx2/src/service/builder/publish_subscribe.rs @@ -40,6 +40,11 @@ use super::{OpenDynamicStorageFailure, ServiceState}; #[doc(hidden)] pub struct CustomHeaderMarker {} +#[repr(C)] +#[derive(Debug)] +#[doc(hidden)] +pub struct CustomPayloadMarker(u8); + /// Errors that can occur when an existing [`MessagingPattern::PublishSubscribe`] [`Service`] shall be opened. #[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)] pub enum PublishSubscribeOpenError { @@ -716,7 +721,9 @@ impl } } -impl Builder<[u8], UserHeader, ServiceType> { +impl + Builder<[CustomPayloadMarker], UserHeader, ServiceType> +{ #[doc(hidden)] pub unsafe fn __internal_set_payload_type_details(mut self, value: &TypeDetail) -> Self { self.override_payload_type = Some(value.clone()); diff --git a/iceoryx2/src/service/header/publish_subscribe.rs b/iceoryx2/src/service/header/publish_subscribe.rs index 210397012..5de1d6508 100644 --- a/iceoryx2/src/service/header/publish_subscribe.rs +++ b/iceoryx2/src/service/header/publish_subscribe.rs @@ -30,7 +30,6 @@ //! # Ok(()) //! # } //! ``` -use std::alloc::Layout; use crate::port::port_identifiers::UniquePublisherId; @@ -40,14 +39,14 @@ use crate::port::port_identifiers::UniquePublisherId; #[repr(C)] pub struct Header { publisher_port_id: UniquePublisherId, - payload_type_layout: Layout, + number_of_elements: u64, } impl Header { - pub(crate) fn new(publisher_port_id: UniquePublisherId, payload_type_layout: Layout) -> Self { + pub(crate) fn new(publisher_port_id: UniquePublisherId, number_of_elements: u64) -> Self { Self { publisher_port_id, - payload_type_layout, + number_of_elements, } } @@ -56,8 +55,16 @@ impl Header { self.publisher_port_id } - /// Returns the [`Layout`] of the corresponding payload. - pub fn payload_type_layout(&self) -> Layout { - self.payload_type_layout + /// Returns how many elements are stored inside the sample's payload. + /// + /// # Details when using + /// [`CustomPayloadMarker`](crate::service::builder::publish_subscribe::CustomPayloadMarker) + /// + /// In this case the number of elements relates to the element defined in the + /// [`MessageTypeDetails`](crate::service::static_config::message_type_details::MessageTypeDetails). + /// When the element has a `payload.size == 40` and the `Sample::payload().len() == 120` it + /// means that it contains 3 elements (3 * 40 == 120). + pub fn number_of_elements(&self) -> u64 { + self.number_of_elements } } diff --git a/iceoryx2/src/service/static_config/message_type_details.rs b/iceoryx2/src/service/static_config/message_type_details.rs index 3efa1fe9f..57924140a 100644 --- a/iceoryx2/src/service/static_config/message_type_details.rs +++ b/iceoryx2/src/service/static_config/message_type_details.rs @@ -17,7 +17,7 @@ use serde::{Deserialize, Serialize}; /// Defines if the type is a slice with a runtime-size ([`TypeVariant::Dynamic`]) /// or if its a type that satisfies [`Sized`] ([`TypeVariant::FixedSize`]). -#[derive(Default, Debug, Clone, Eq, Hash, PartialEq, Serialize, Deserialize)] +#[derive(Default, Debug, Clone, Copy, Eq, Hash, PartialEq, Serialize, Deserialize)] pub enum TypeVariant { #[default] /// A type notated by [`#[repr(C)]`](https://doc.rust-lang.org/reference/type-layout.html#reprc). diff --git a/iceoryx2/tests/publisher_tests.rs b/iceoryx2/tests/publisher_tests.rs index 326234887..db55b141b 100644 --- a/iceoryx2/tests/publisher_tests.rs +++ b/iceoryx2/tests/publisher_tests.rs @@ -18,6 +18,7 @@ mod publisher { use iceoryx2::port::publisher::{PublisherCreateError, PublisherLoanError}; use iceoryx2::prelude::*; + use iceoryx2::service::builder::publish_subscribe::CustomPayloadMarker; use iceoryx2::service::port_factory::publisher::UnableToDeliverStrategy; use iceoryx2::service::static_config::message_type_details::{TypeDetail, TypeVariant}; use iceoryx2::service::{service_name::ServiceName, Service}; @@ -393,8 +394,7 @@ mod publisher { } #[test] - fn publisher_with_overridden_payload_details_adjusts_slice_len() -> TestResult<()> - { + fn publisher_with_custom_payload_details_adjusts_slice_len() -> TestResult<()> { const TYPE_SIZE_OVERRIDE: usize = 128; let service_name = generate_name()?; let config = generate_isolated_config(); @@ -404,20 +404,68 @@ mod publisher { let service = unsafe { node.service_builder(&service_name) - .publish_subscribe::<[u8]>() + .publish_subscribe::<[CustomPayloadMarker]>() .__internal_set_payload_type_details(&type_detail) .create()? }; let sut = service.publisher_builder().create()?; - let sample = sut.loan_slice(1)?; + let sample = unsafe { sut.loan_custom_payload(1)? }; assert_that!(sample.payload(), len TYPE_SIZE_OVERRIDE); Ok(()) } + #[test] + #[should_panic] + #[cfg(debug_assertions)] + fn publisher_with_custom_payload_details_panics_when_calling_loan_slice_uninit() { + const TYPE_SIZE_OVERRIDE: usize = 128; + let service_name = generate_name().unwrap(); + let config = generate_isolated_config(); + let node = NodeBuilder::new().config(&config).create::().unwrap(); + let mut type_detail = TypeDetail::__internal_new::(TypeVariant::FixedSize); + type_detail.size = TYPE_SIZE_OVERRIDE; + + let service = unsafe { + node.service_builder(&service_name) + .publish_subscribe::<[CustomPayloadMarker]>() + .__internal_set_payload_type_details(&type_detail) + .create() + .unwrap() + }; + + let sut = service.publisher_builder().create().unwrap(); + + // panics here + let _sample = sut.loan_slice_uninit(1); + } + + #[test] + #[should_panic] + #[cfg(debug_assertions)] + fn custom_fixed_size_payload_panics_when_loaning_more_than_one_element() { + set_log_level(LogLevel::Error); + let service_name = generate_name().unwrap(); + let config = generate_isolated_config(); + let node = NodeBuilder::new().config(&config).create::().unwrap(); + let type_details = TypeDetail::__internal_new::(TypeVariant::FixedSize); + + let service = unsafe { + node.service_builder(&service_name) + .publish_subscribe::<[CustomPayloadMarker]>() + .__internal_set_payload_type_details(&type_details) + .create() + .unwrap() + }; + + let sut = service.publisher_builder().create().unwrap(); + + let _sample = unsafe { sut.loan_custom_payload(2) }; + } + #[instantiate_tests()] mod ipc {} diff --git a/iceoryx2/tests/service_publish_subscribe_tests.rs b/iceoryx2/tests/service_publish_subscribe_tests.rs index d3e935f51..355594b92 100644 --- a/iceoryx2/tests/service_publish_subscribe_tests.rs +++ b/iceoryx2/tests/service_publish_subscribe_tests.rs @@ -21,9 +21,9 @@ mod service_publish_subscribe { use iceoryx2::port::subscriber::SubscriberCreateError; use iceoryx2::port::update_connections::UpdateConnections; use iceoryx2::prelude::*; - use iceoryx2::service::builder::publish_subscribe::CustomHeaderMarker; use iceoryx2::service::builder::publish_subscribe::PublishSubscribeCreateError; use iceoryx2::service::builder::publish_subscribe::PublishSubscribeOpenError; + use iceoryx2::service::builder::publish_subscribe::{CustomHeaderMarker, CustomPayloadMarker}; use iceoryx2::service::messaging_pattern::MessagingPattern; use iceoryx2::service::port_factory::publisher::UnableToDeliverStrategy; use iceoryx2::service::static_config::message_type_details::{TypeDetail, TypeVariant}; @@ -2611,7 +2611,7 @@ mod service_publish_subscribe { let _sut = unsafe { node.service_builder(&service_name) - .publish_subscribe::<[u8]>() + .publish_subscribe::<[CustomPayloadMarker]>() .__internal_set_payload_type_details(&TypeDetail::__internal_new::( TypeVariant::FixedSize, )) @@ -2704,7 +2704,7 @@ mod service_publish_subscribe { let sut2 = unsafe { node.service_builder(&service_name) - .publish_subscribe::<[u8]>() + .publish_subscribe::<[CustomPayloadMarker]>() .__internal_set_payload_type_details(&TypeDetail::__internal_new::( TypeVariant::FixedSize, )) @@ -2715,7 +2715,7 @@ mod service_publish_subscribe { let sut3 = unsafe { node.service_builder(&service_name) - .publish_subscribe::<[u8]>() + .publish_subscribe::<[CustomPayloadMarker]>() .__internal_set_payload_type_details(&TypeDetail::__internal_new::( TypeVariant::FixedSize, )) @@ -2902,6 +2902,80 @@ mod service_publish_subscribe { assert_that!(*sample, eq 456); } + #[test] + fn communication_with_custom_payload_works() { + set_log_level(LogLevel::Error); + const NUMBER_OF_ELEMENTS: usize = 1; + let service_name = generate_name(); + let config = generate_isolated_config(); + let node = NodeBuilder::new().config(&config).create::().unwrap(); + let mut type_details = TypeDetail::__internal_new::(TypeVariant::FixedSize); + type_details.size = 1024; + type_details.alignment = 1024; + + let sut = unsafe { + node.service_builder(&service_name) + .publish_subscribe::<[CustomPayloadMarker]>() + .__internal_set_payload_type_details(&type_details) + .create() + .unwrap() + }; + + let publisher = sut.publisher_builder().create().unwrap(); + let subscriber = sut.subscriber_builder().create().unwrap(); + + let sample = unsafe { publisher.loan_custom_payload(NUMBER_OF_ELEMENTS).unwrap() }; + assert_that!(sample.payload(), len type_details.size); + assert_that!((sample.payload().as_ptr() as usize % type_details.alignment), eq 0); + assert_that!(sample.header().number_of_elements(), eq NUMBER_OF_ELEMENTS as u64); + + unsafe { sample.assume_init().send().unwrap() }; + + let sample = unsafe { subscriber.receive_custom_payload().unwrap().unwrap() }; + assert_that!(sample.payload(), len type_details.size); + assert_that!((sample.payload().as_ptr() as usize % type_details.alignment), eq 0); + assert_that!(sample.header().number_of_elements(), eq NUMBER_OF_ELEMENTS as u64); + } + + #[test] + fn communication_with_custom_slice_payload_works() { + set_log_level(LogLevel::Error); + const NUMBER_OF_ELEMENTS: usize = 7; + let service_name = generate_name(); + let config = generate_isolated_config(); + let node = NodeBuilder::new().config(&config).create::().unwrap(); + let mut type_details = TypeDetail::__internal_new::(TypeVariant::Dynamic); + type_details.size = 2048; + type_details.alignment = 2048; + + let sut = unsafe { + node.service_builder(&service_name) + .publish_subscribe::<[CustomPayloadMarker]>() + .__internal_set_payload_type_details(&type_details) + .create() + .unwrap() + }; + + let publisher = sut + .publisher_builder() + .max_slice_len(NUMBER_OF_ELEMENTS) + .create() + .unwrap(); + let subscriber = sut.subscriber_builder().create().unwrap(); + + let sample = unsafe { publisher.loan_custom_payload(NUMBER_OF_ELEMENTS).unwrap() }; + assert_that!(sample.payload(), len type_details.size * NUMBER_OF_ELEMENTS); + assert_that!((sample.payload().as_ptr() as usize % type_details.alignment), eq 0); + assert_that!(sample.header().number_of_elements(), eq NUMBER_OF_ELEMENTS as u64); + + unsafe { sample.assume_init().send().unwrap() }; + + let sample = unsafe { subscriber.receive_custom_payload().unwrap().unwrap() }; + assert_that!(sample.payload(), len type_details.size * NUMBER_OF_ELEMENTS); + assert_that!((sample.payload().as_ptr() as usize % type_details.alignment), eq 0); + assert_that!(sample.header().number_of_elements(), eq NUMBER_OF_ELEMENTS as u64); + } + #[instantiate_tests()] mod ipc {} diff --git a/iceoryx2/tests/subscriber_tests.rs b/iceoryx2/tests/subscriber_tests.rs index 273743c37..996e2d578 100644 --- a/iceoryx2/tests/subscriber_tests.rs +++ b/iceoryx2/tests/subscriber_tests.rs @@ -12,6 +12,8 @@ #[generic_tests::define] mod subscriber { + use iceoryx2::service::builder::publish_subscribe::CustomPayloadMarker; + use iceoryx2::service::static_config::message_type_details::{TypeDetail, TypeVariant}; use std::collections::HashSet; use iceoryx2::{ @@ -69,6 +71,33 @@ mod subscriber { } } + #[test] + #[should_panic] + #[cfg(debug_assertions)] + fn subscriber_with_custom_payload_details_panics_when_calling_non_custom_receive< + Sut: Service, + >() { + const TYPE_SIZE_OVERRIDE: usize = 128; + let service_name = generate_name(); + let config = generate_isolated_config(); + let node = NodeBuilder::new().config(&config).create::().unwrap(); + let mut type_detail = TypeDetail::__internal_new::(TypeVariant::FixedSize); + type_detail.size = TYPE_SIZE_OVERRIDE; + + let service = unsafe { + node.service_builder(&service_name) + .publish_subscribe::<[CustomPayloadMarker]>() + .__internal_set_payload_type_details(&type_detail) + .create() + .unwrap() + }; + + let sut = service.subscriber_builder().create().unwrap(); + + // panics here + let _sample = sut.receive(); + } + #[instantiate_tests()] mod ipc {}