Skip to content

Commit

Permalink
[#490] Translate from Slice<T> in CXX to [u8] in Rust
Browse files Browse the repository at this point in the history
  • Loading branch information
orecham committed Oct 31, 2024
1 parent 0112ec4 commit a970c4d
Show file tree
Hide file tree
Showing 9 changed files with 178 additions and 138 deletions.
25 changes: 12 additions & 13 deletions iceoryx2-ffi/cxx/include/iox/slice.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,21 @@ class Slice {
using ConstIterator = const T*;
using ValueType = T;

template <typename U>
Slice(U* data, uint64_t len)
: m_data { const_cast<T*>(static_cast<const std::remove_pointer_t<U>*>(data)) }
, m_len { len } {
Slice(const void* data, uint64_t number_of_elements)
: m_data { static_cast<T*>(const_cast<void*>(data)) }
, m_number_of_elements { number_of_elements } {
}

auto len() const -> uint64_t {
return m_len;
auto number_of_elements() const -> uint64_t {
return m_number_of_elements;
}
auto operator[](const uint64_t n) const -> const T& {
IOX_ASSERT(n < m_len, "Index out of bounds");
IOX_ASSERT(n < m_number_of_elements, "Index out of bounds");
return *(m_data + n);
}

auto operator[](const uint64_t n) -> T& {
IOX_ASSERT(n < m_len, "Index out of bounds");
IOX_ASSERT(n < m_number_of_elements, "Index out of bounds");
return *(m_data + n);
}

Expand All @@ -55,17 +54,17 @@ class Slice {

auto end() -> Iterator {
if constexpr (std::is_same_v<T, void>) {
return reinterpret_cast<T*>(reinterpret_cast<char*>(m_data) + m_len);
return reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(m_data) + m_number_of_elements);
} else {
return m_data + m_len;
return m_data + m_number_of_elements;
}
}

auto end() const -> ConstIterator {
if constexpr (std::is_same_v<T, void>) {
return reinterpret_cast<const T*>(reinterpret_cast<const char*>(m_data) + m_len);
return reinterpret_cast<const T*>(reinterpret_cast<const uint8_t*>(m_data) + m_number_of_elements);
} else {
return m_data + m_len;
return m_data + m_number_of_elements;
}
}

Expand All @@ -79,7 +78,7 @@ class Slice {

private:
T* m_data;
uint64_t m_len;
uint64_t m_number_of_elements;
};

template <typename>
Expand Down
22 changes: 20 additions & 2 deletions iceoryx2-ffi/cxx/include/iox2/port_factory_publisher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,26 @@ PortFactoryPublisher<S, Payload, UserHeader>::create() && -> iox::expected<Publi
iox2_port_factory_publisher_builder_unable_to_deliver_strategy(
&m_handle, static_cast<iox2_unable_to_deliver_strategy_e>(iox::into<int>(value)));
});
m_max_slice_len.and_then(
[&](auto value) { iox2_port_factory_publisher_builder_set_max_slice_len(&m_handle, value); });
m_max_slice_len
.and_then([&](auto value) {
// The payload type used by the C API is always a [u8].
// Thus need to convert from N to N * sizeof(payload).
// TODO: Consider alignment... not aligning each element properly will impact performance
if constexpr (iox::IsSlice<Payload>::VALUE) {
iox2_port_factory_publisher_builder_set_max_slice_len(&m_handle,
value * sizeof(typename Payload::ValueType));
} else {
iox2_port_factory_publisher_builder_set_max_slice_len(&m_handle, value * sizeof(Payload));
}
})
.or_else([&]() {
// Assume only one element if not otherwise specified
if constexpr (iox::IsSlice<Payload>::VALUE) {
iox2_port_factory_publisher_builder_set_max_slice_len(&m_handle, sizeof(typename Payload::ValueType));
} else {
iox2_port_factory_publisher_builder_set_max_slice_len(&m_handle, sizeof(Payload));
}
});
m_max_loaned_samples.and_then(
[&](auto value) { iox2_port_factory_publisher_builder_set_max_loaned_samples(&m_handle, value); });

Expand Down
31 changes: 19 additions & 12 deletions iceoryx2-ffi/cxx/include/iox2/publisher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,15 @@ inline auto Publisher<S, Payload, UserHeader>::unable_to_deliver_strategy() cons

template <ServiceType S, typename Payload, typename UserHeader>
inline auto Publisher<S, Payload, UserHeader>::max_slice_len() const -> uint64_t {
return iox2_publisher_max_slice_len(&m_handle);
// NOTE: The C API always uses a [u8] payload, therefore the max length returned is the number of bytes.
// Dividing by the size gives the number of slice elements available to the C++ API.
//
// NOTE: For non-slice types, the number of slice elements is always 1.
if constexpr (iox::IsSlice<Payload>::VALUE) {
return iox2_publisher_max_slice_len(&m_handle) / sizeof(typename Payload::ValueType);
} else {
return iox2_publisher_max_slice_len(&m_handle) / sizeof(Payload);
}
}

template <ServiceType S, typename Payload, typename UserHeader>
Expand Down Expand Up @@ -180,7 +188,7 @@ inline auto Publisher<S, Payload, UserHeader>::loan_uninit()
-> iox::expected<SampleMutUninit<S, Payload, UserHeader>, PublisherLoanError> {
SampleMutUninit<S, Payload, UserHeader> sample;

auto result = iox2_publisher_loan(&m_handle, &sample.m_sample.m_sample, &sample.m_sample.m_handle);
auto result = iox2_publisher_loan_slice_uninit(&m_handle, &sample.m_sample.m_sample, &sample.m_sample.m_handle, 1);

if (result == IOX2_OK) {
return iox::ok(std::move(sample));
Expand Down Expand Up @@ -208,19 +216,18 @@ template <ServiceType S, typename Payload, typename UserHeader>
template <typename T, typename>
inline auto Publisher<S, Payload, UserHeader>::loan_slice(const uint64_t number_of_elements)
-> iox::expected<SampleMut<S, T, UserHeader>, PublisherLoanError> {
SampleMutUninit<S, Payload, UserHeader> sample;
auto sample_uninit = loan_slice_uninit(number_of_elements);

auto result = iox2_publisher_loan_slice_uninit(
number_of_elements, &m_handle, &sample.m_sample.m_sample, &sample.m_sample.m_handle);
if (sample_uninit.has_error()) {
return iox::err(sample_uninit.error());
}
auto sample_init = std::move(sample_uninit.value());

if (result == IOX2_OK) {
for (auto it = sample.payload_slice().begin(); it != sample.payload_slice().end(); ++it) {
new (it) typename T::ValueType();
}
return iox::ok(assume_init(std::move(sample)));
for (auto it = sample_init.payload_slice().begin(); it != sample_init.payload_slice().end(); ++it) {
new (it) typename T::ValueType();
}

return iox::err(iox::into<PublisherLoanError>(result));
return iox::ok(assume_init(std::move(sample_init)));
}

template <ServiceType S, typename Payload, typename UserHeader>
Expand All @@ -230,7 +237,7 @@ inline auto Publisher<S, Payload, UserHeader>::loan_slice_uninit(const uint64_t
SampleMutUninit<S, Payload, UserHeader> sample;

auto result = iox2_publisher_loan_slice_uninit(
number_of_elements, &m_handle, &sample.m_sample.m_sample, &sample.m_sample.m_handle);
&m_handle, &sample.m_sample.m_sample, &sample.m_sample.m_handle, number_of_elements);

if (result == IOX2_OK) {
return iox::ok(std::move(sample));
Expand Down
13 changes: 7 additions & 6 deletions iceoryx2-ffi/cxx/include/iox2/sample.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,23 +130,24 @@ template <ServiceType S, typename Payload, typename UserHeader>
template <typename T, typename>
inline auto Sample<S, Payload, UserHeader>::payload() const -> const Payload& {
const void* ptr = nullptr;
size_t number_of_elements = 0;
size_t number_of_bytes = 0;

iox2_sample_payload(&m_handle, &ptr, &number_of_elements);
iox2_sample_payload(&m_handle, &ptr, &number_of_bytes);

return *static_cast<const Payload*>(ptr);
}


template <ServiceType S, typename Payload, typename UserHeader>
template <typename T, typename>
inline auto Sample<S, Payload, UserHeader>::payload_slice() const -> Payload {
const void* ptr = nullptr;
size_t number_of_elements = 0;
size_t number_of_bytes = 0;

iox2_sample_payload(&m_handle, &ptr, &number_of_bytes);

iox2_sample_payload(&m_handle, &ptr, &number_of_elements);
size_t number_of_elements = number_of_bytes / sizeof(typename Payload::ValueType);

return Payload(static_cast<const typename Payload::ValueType*>(ptr), number_of_elements);
return Payload(ptr, number_of_elements);
}

template <ServiceType S, typename Payload, typename UserHeader>
Expand Down
28 changes: 16 additions & 12 deletions iceoryx2-ffi/cxx/include/iox2/sample_mut.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,10 @@ template <ServiceType S, typename Payload, typename UserHeader>
template <typename T, typename>
inline auto SampleMut<S, Payload, UserHeader>::payload() const -> const Payload& {
const void* ptr = nullptr;
size_t number_of_elements = 0;
size_t number_of_bytes = 0;

iox2_sample_mut_payload(&m_handle, &ptr, &number_of_elements);
IOX_ASSERT(sizeof(Payload) <= number_of_elements, "");
iox2_sample_mut_payload(&m_handle, &ptr, &number_of_bytes);
IOX_ASSERT(sizeof(Payload) <= number_of_bytes, "");

return *static_cast<const Payload*>(ptr);
}
Expand All @@ -209,10 +209,10 @@ template <ServiceType S, typename Payload, typename UserHeader>
template <typename T, typename>
inline auto SampleMut<S, Payload, UserHeader>::payload_mut() -> Payload& {
void* ptr = nullptr;
size_t number_of_elements = 0;
size_t number_of_bytes = 0;

iox2_sample_mut_payload_mut(&m_handle, &ptr, &number_of_elements);
IOX_ASSERT(sizeof(Payload) <= number_of_elements, "");
iox2_sample_mut_payload_mut(&m_handle, &ptr, &number_of_bytes);
IOX_ASSERT(sizeof(Payload) <= number_of_bytes, "");

return *static_cast<Payload*>(ptr);
}
Expand All @@ -221,22 +221,26 @@ template <ServiceType S, typename Payload, typename UserHeader>
template <typename T, typename>
inline auto SampleMut<S, Payload, UserHeader>::payload_slice() const -> const Payload {
const void* ptr = nullptr;
size_t number_of_elements = 0;
size_t number_of_bytes = 0;

iox2_sample_mut_payload(&m_handle, &ptr, &number_of_elements);
iox2_sample_mut_payload(&m_handle, &ptr, &number_of_bytes);

return Payload(static_cast<const typename Payload::ValueType*>(ptr), number_of_elements);
size_t number_of_elements = number_of_bytes / sizeof(typename Payload::ValueType);

return Payload(ptr, number_of_elements);
}

template <ServiceType S, typename Payload, typename UserHeader>
template <typename T, typename>
inline auto SampleMut<S, Payload, UserHeader>::payload_slice_mut() -> Payload {
void* ptr = nullptr;
size_t number_of_elements = 0;
size_t number_of_bytes = 0;

iox2_sample_mut_payload_mut(&m_handle, &ptr, &number_of_bytes);

iox2_sample_mut_payload_mut(&m_handle, &ptr, &number_of_elements);
size_t number_of_elements = number_of_bytes / sizeof(typename Payload::ValueType);

return Payload(static_cast<typename Payload::ValueType*>(ptr), number_of_elements);
return Payload(ptr, number_of_elements);
}

template <ServiceType S, typename Payload, typename UserHeader>
Expand Down
41 changes: 25 additions & 16 deletions iceoryx2-ffi/cxx/include/iox2/service_builder_publish_subscribe.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@
#include <typeinfo>

namespace iox2 {

template <typename T>
struct PayloadValueType {
using TYPE = T;
};

template <typename T>
struct PayloadValueType<iox::Slice<T>> {
using TYPE = typename iox::Slice<T>::ValueType;
};

/// Builder to create new [`MessagingPattern::PublishSubscribe`] based [`Service`]s
template <typename Payload, typename UserHeader, ServiceType S>
class ServiceBuilderPublishSubscribe {
Expand Down Expand Up @@ -138,18 +149,17 @@ inline void ServiceBuilderPublishSubscribe<Payload, UserHeader, S>::set_paramete
[&](auto value) { iox2_service_builder_pub_sub_set_payload_alignment(&m_handle, value); });
m_max_nodes.and_then([&](auto value) { iox2_service_builder_pub_sub_set_max_nodes(&m_handle, value); });

using ValueType = typename PayloadValueType<Payload>::TYPE;
auto type_variant = iox::IsSlice<Payload>::VALUE ? iox2_type_variant_e_DYNAMIC : iox2_type_variant_e_FIXED_SIZE;

// payload type details
const auto* payload_type_name = typeid(Payload).name();
const auto* payload_type_name = typeid(ValueType).name();
const auto payload_type_name_len = strlen(payload_type_name);
const auto payload_type_size = sizeof(Payload);
const auto payload_type_align = alignof(Payload);
const auto payload_type_size = sizeof(ValueType);
const auto payload_type_align = alignof(ValueType);

const auto payload_result = iox2_service_builder_pub_sub_set_payload_type_details(&m_handle,
iox2_type_variant_e_FIXED_SIZE,
payload_type_name,
payload_type_name_len,
payload_type_size,
payload_type_align);
const auto payload_result = iox2_service_builder_pub_sub_set_payload_type_details(
&m_handle, type_variant, payload_type_name, payload_type_name_len, payload_type_size, payload_type_align);

if (payload_result != IOX2_OK) {
IOX_PANIC("This should never happen! Implementation failure while setting the Payload-Type.");
Expand All @@ -162,13 +172,12 @@ inline void ServiceBuilderPublishSubscribe<Payload, UserHeader, S>::set_paramete
const auto user_header_type_size = header_layout.size();
const auto user_header_type_align = header_layout.alignment();

const auto user_header_result =
iox2_service_builder_pub_sub_set_user_header_type_details(&m_handle,
iox2_type_variant_e_FIXED_SIZE,
user_header_type_name,
user_header_type_name_len,
user_header_type_size,
user_header_type_align);
const auto user_header_result = iox2_service_builder_pub_sub_set_user_header_type_details(&m_handle,
type_variant,
user_header_type_name,
user_header_type_name_len,
user_header_type_size,
user_header_type_align);

if (user_header_result != IOX2_OK) {
IOX_PANIC("This should never happen! Implementation failure while setting the User-Header-Type.");
Expand Down
Loading

0 comments on commit a970c4d

Please sign in to comment.