diff --git a/iceoryx2/src/port/publisher.rs b/iceoryx2/src/port/publisher.rs index 9122169e4..6d613519d 100644 --- a/iceoryx2/src/port/publisher.rs +++ b/iceoryx2/src/port/publisher.rs @@ -71,7 +71,7 @@ use crate::service::dynamic_config::publish_subscribe::{PublisherDetails, Subscr use crate::service::header::publish_subscribe::Header; use crate::service::naming_scheme::data_segment_name; use crate::service::port_factory::publisher::{LocalPublisherConfig, UnableToDeliverStrategy}; -use crate::service::static_config::publish_subscribe; +use crate::service::static_config::publish_subscribe::{self, TypeDetails}; use crate::{config, sample_mut::SampleMut}; use iceoryx2_bb_container::queue::Queue; use iceoryx2_bb_elementary::allocator::AllocationError; @@ -111,6 +111,7 @@ impl std::error::Error for PublisherCreateError {} pub enum PublisherLoanError { OutOfMemory, ExceedsMaxLoanedChunks, + ExceedsMaxLoanSize, InternalFailure, } @@ -674,12 +675,10 @@ impl Publisher Result, Service>, PublisherLoanError> { let chunk = self.allocate(RawSampleMut::::layout())?; - let (header_ptr, message_ptr) = RawSampleMut::::header_message_ptr(chunk.data_ptr); unsafe { header_ptr.write(Header::new(self.data_segment.port_id)) }; - unsafe { message_ptr.write(MaybeUninit::uninit()) }; let sample = unsafe { RawSampleMut::new_unchecked(header_ptr, message_ptr) }; Ok(SampleMut::, Service>::new( @@ -737,7 +736,8 @@ impl Publisher Result, PublisherLoanError> { - todo!() + let sample = self.loan_slice_uninit(number_of_elements)?; + Ok(sample.write_from_fn(|_| MessageType::default())) } } @@ -746,6 +746,27 @@ impl Publisher Result], Service>, PublisherLoanError> { + let max_elements = if let TypeDetails::Sliced { sliced: d } = self + .data_segment + .static_config + .publish_subscribe() + .type_details() + { + d.max_elements + } else { + debug_assert!( + false, + "This should never happen! The Publisher Type is not a slice." + ); + 0 + }; + + if max_elements < number_of_elements { + fail!(from self, with PublisherLoanError::ExceedsMaxLoanSize, + "Unable to loan slice with {} elements since it would exceed the max supported number of elements of {}.", + number_of_elements, max_elements); + } + let layout = RawSampleMut::::layout_slice(number_of_elements); let chunk = self.allocate(layout)?; @@ -756,8 +777,6 @@ impl Publisher], Service>::new( diff --git a/iceoryx2/src/sample_mut.rs b/iceoryx2/src/sample_mut.rs index 322a3b7f7..49a6d46c9 100644 --- a/iceoryx2/src/sample_mut.rs +++ b/iceoryx2/src/sample_mut.rs @@ -189,6 +189,27 @@ impl } } +impl + SampleMut<[MaybeUninit], Service> +{ + pub unsafe fn assume_init(self) -> SampleMut<[MessageType], Service> { + // the transmute is not nice but safe since MaybeUninit is #[repr(transparent)] to the inner type + std::mem::transmute(self) + } + + pub fn write_from_fn MessageType>( + mut self, + mut initializer: F, + ) -> SampleMut<[MessageType], Service> { + for (i, element) in self.payload_mut().iter_mut().enumerate() { + element.write(initializer(i)); + } + + // SAFETY: this is safe since the payload was initialized on the line above + unsafe { self.assume_init() } + } +} + impl< M: Debug + ?Sized, // `M` is either a `MessageType` or a `MaybeUninit` Service: crate::service::Service, diff --git a/iceoryx2/src/service/builder/publish_subscribe.rs b/iceoryx2/src/service/builder/publish_subscribe.rs index 436a5c03f..86c63ffbd 100644 --- a/iceoryx2/src/service/builder/publish_subscribe.rs +++ b/iceoryx2/src/service/builder/publish_subscribe.rs @@ -247,7 +247,7 @@ impl Builder { } /// Returns the [`SlicedBuilder`] to create a slice typed [`Service`]. - pub fn slice(mut self) -> SlicedBuilder { + pub fn sliced(mut self) -> SlicedBuilder { self.config_details_mut().type_details = TypeDetails::from_slice::(1); SlicedBuilder { diff --git a/iceoryx2/tests/publisher_tests.rs b/iceoryx2/tests/publisher_tests.rs index d06a7f533..f6339fb48 100644 --- a/iceoryx2/tests/publisher_tests.rs +++ b/iceoryx2/tests/publisher_tests.rs @@ -33,6 +33,22 @@ mod publisher { ))?) } + const COMPLEX_TYPE_DEFAULT_VALUE: u64 = 872379237; + + #[derive(Debug)] + #[repr(C)] + struct ComplexType { + data: u64, + } + + impl Default for ComplexType { + fn default() -> Self { + ComplexType { + data: COMPLEX_TYPE_DEFAULT_VALUE, + } + } + } + #[test] fn publisher_loan_and_send_sample_works() -> TestResult<()> { let service_name = generate_name()?; @@ -50,6 +66,81 @@ mod publisher { Ok(()) } + #[test] + fn publisher_loan_initializes_sample_with_default() -> TestResult<()> { + let service_name = generate_name()?; + let service = Sut::new(&service_name) + .publish_subscribe() + .typed::() + .create()?; + + let publisher = service.publisher().create()?; + let sut = publisher.loan()?; + + assert_that!(sut.payload().data, eq COMPLEX_TYPE_DEFAULT_VALUE); + + Ok(()) + } + + #[test] + fn publisher_loan_slice_initializes_sample_with_default() -> TestResult<()> { + const NUMBER_OF_ELEMENTS: usize = 120; + let service_name = generate_name()?; + let service = Sut::new(&service_name) + .publish_subscribe() + .sliced::() + .max_elements(NUMBER_OF_ELEMENTS) + .create()?; + + let publisher = service.publisher().create()?; + let sut = publisher.loan_slice(NUMBER_OF_ELEMENTS)?; + + for i in 0..NUMBER_OF_ELEMENTS { + assert_that!(sut.payload()[i].data, eq COMPLEX_TYPE_DEFAULT_VALUE); + } + + Ok(()) + } + + #[test] + fn publisher_loan_slice_up_to_max_elements_works() -> TestResult<()> { + const NUMBER_OF_ELEMENTS: usize = 125; + let service_name = generate_name()?; + let service = Sut::new(&service_name) + .publish_subscribe() + .sliced::() + .max_elements(NUMBER_OF_ELEMENTS) + .create()?; + + let publisher = service.publisher().create()?; + + for i in 0..NUMBER_OF_ELEMENTS { + let sut = publisher.loan_slice(i)?; + assert_that!(sut.payload().len(), eq i); + } + + Ok(()) + } + + #[test] + fn publisher_loan_slice_more_than_max_elements_fails() -> TestResult<()> { + const NUMBER_OF_ELEMENTS: usize = 125; + let service_name = generate_name()?; + let service = Sut::new(&service_name) + .publish_subscribe() + .sliced::() + .max_elements(NUMBER_OF_ELEMENTS) + .create()?; + + let publisher = service.publisher().create()?; + + let sut = publisher.loan_slice(NUMBER_OF_ELEMENTS + 1); + assert_that!(sut, is_err); + assert_that!(sut.err().unwrap(), eq PublisherLoanError::ExceedsMaxLoanSize); + + Ok(()) + } + #[test] fn publisher_loan_unit_and_send_sample_works() -> TestResult<()> { let service_name = generate_name()?; diff --git a/iceoryx2/tests/service_publish_subscribe_tests.rs b/iceoryx2/tests/service_publish_subscribe_tests.rs index a3d1abb60..ecfe354b5 100644 --- a/iceoryx2/tests/service_publish_subscribe_tests.rs +++ b/iceoryx2/tests/service_publish_subscribe_tests.rs @@ -1794,7 +1794,7 @@ mod service_publish_subscribe { let service_name = generate_name(); let sut = Sut::new(&service_name) .publish_subscribe() - .slice::() + .sliced::() .max_elements(12) .create() .unwrap(); @@ -1802,7 +1802,7 @@ mod service_publish_subscribe { let publisher = sut.publisher().create().unwrap(); let subscriber = sut.subscriber().create().unwrap(); - let sample = publisher.loan_slice_uninit(11).unwrap(); + let sample = publisher.loan_slice(11).unwrap(); } #[instantiate_tests()]