Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add relaxed_message #673

Merged
merged 1 commit into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/msg/field.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -532,5 +532,8 @@ struct field {
using located = detail::field_t<
decltype(stdx::ct_string_to_type<Name, sc::string_constant>()), T,
Default, M, Ats...>;

constexpr static auto bitsize = sizeof(T) * CHAR_BIT;
using default_located = located<at{msb_t{bitsize - 1}, lsb_t{}}>;
};
} // namespace msg
56 changes: 45 additions & 11 deletions include/msg/message.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,25 +664,23 @@ namespace detail {
template <typename AlignTo, typename... Msgs>
using msg_sizes = stdx::type_list<typename Msgs::template size<AlignTo>...>;

template <typename S>
using negated_size = std::integral_constant<std::size_t, -S::value>;

template <typename AlignTo, typename... Msgs>
using msg_offsets = boost::mp11::mp_partial_sum<
msg_sizes<AlignTo, Msgs...>,
negated_size<typename boost::mp11::mp_first<
stdx::type_list<Msgs...>>::template size<AlignTo>>,
boost::mp11::mp_plus>;
using msg_offsets = boost::mp11::mp_push_front<
boost::mp11::mp_partial_sum<msg_sizes<AlignTo, Msgs...>,
std::integral_constant<std::size_t, 0>,
boost::mp11::mp_plus>,
std::integral_constant<std::size_t, 0>>;

template <typename AlignTo> struct shift_msg_q {
template <typename Offset, typename Msg>
using fn = typename Msg::template shifted_by<Offset::value, AlignTo>;
};

template <typename AlignTo, typename... Msgs>
using shifted_msgs = boost::mp11::mp_transform_q<shift_msg_q<AlignTo>,
msg_offsets<AlignTo, Msgs...>,
stdx::type_list<Msgs...>>;
using shifted_msgs =
boost::mp11::mp_transform_q<shift_msg_q<AlignTo>,
msg_offsets<AlignTo, Msgs...>,
stdx::type_list<Msgs..., msg::message<"end">>>;

template <stdx::ct_string Name> struct combiner {
template <typename... Fields> using fn = msg::message<Name, Fields...>;
Expand All @@ -704,4 +702,40 @@ template <stdx::ct_string Name, typename AlignTo, typename... Msgs>
requires(sizeof...(Msgs) > 0)
using pack = boost::mp11::mp_apply_q<detail::combine_q<Name>,
detail::shifted_msgs<AlignTo, Msgs...>>;

namespace detail {
template <typename F>
using is_locatable = std::bool_constant<requires { F::sort_key; }>;

template <typename F1, typename F2>
using field_size_sort_fn = std::bool_constant < F2::bitsize<F1::bitsize>;

template <stdx::ct_string Name, typename... Fields> struct field_locator {
using fields = boost::mp11::mp_partition<boost::mp11::mp_list<Fields...>,
is_locatable>;
using located_fields = boost::mp11::mp_first<fields>;
using unlocated_fields = boost::mp11::mp_second<fields>;

using located_msg = boost::mp11::mp_apply_q<combiner<Name>, located_fields>;

using auto_fields =
boost::mp11::mp_sort<unlocated_fields, field_size_sort_fn>;

template <typename F>
using as_singleton_message =
msg::message<Name, typename F::default_located>;
using auto_msgs =
boost::mp11::mp_transform<as_singleton_message, auto_fields>;

using all_msgs = boost::mp11::mp_push_front<auto_msgs, located_msg>;

template <typename... Msgs>
using pack = msg::pack<Name, std::uint8_t, Msgs...>;
using msg_type = boost::mp11::mp_apply<pack, all_msgs>;
};
} // namespace detail

template <stdx::ct_string Name, typename... Fields>
using relaxed_message =
typename detail::field_locator<Name, Fields...>::msg_type;
} // namespace msg
1 change: 1 addition & 0 deletions test/msg/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ add_tests(
indexed_handler
indexed_handler_uninit
message
relaxed_message
send
LIBRARIES
cib)
Expand Down
21 changes: 21 additions & 0 deletions test/msg/message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -621,3 +621,24 @@ TEST_CASE("pack 1 message", "[message]") {
using expected_defn = message<"defn", f1, f2>;
static_assert(std::is_same_v<defn, expected_defn>);
}

TEST_CASE("pack with empty messages", "[message]") {
using m0 = message<"m0">;

using f1 = field<"f1", std::uint32_t>::located<at{15_msb, 0_lsb}>;
using f2 = field<"f2", std::uint32_t>::located<at{23_msb, 16_lsb}>;
using m1 = message<"m1", f1, f2>;

using m2 = message<"m2">;

using f3 = field<"f3", std::uint32_t>::located<at{15_msb, 0_lsb}>;
using f4 = field<"f4", std::uint32_t>::located<at{23_msb, 16_lsb}>;
using m3 = message<"m3", f3, f4>;

using defn = pack<"defn", std::uint8_t, m0, m1, m2, m3>;
using expected_defn =
message<"defn", f1, f2,
f3::shifted_by<m1::size<std::uint8_t>::value, std::uint8_t>,
f4::shifted_by<m1::size<std::uint8_t>::value, std::uint8_t>>;
static_assert(std::is_same_v<defn, expected_defn>);
}
45 changes: 45 additions & 0 deletions test/msg/relaxed_message.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <msg/message.hpp>

#include <catch2/catch_test_macros.hpp>

namespace {
using namespace msg;

using fixed_f =
field<"fixed", std::uint32_t>::located<at{0_dw, 31_msb, 24_lsb}>;
using auto_f1 = field<"auto1", std::uint32_t>;
using auto_f2 = field<"auto2", std::uint8_t>;

} // namespace

TEST_CASE("message with automatically packed fields", "[relaxed_message]") {
using defn = relaxed_message<"msg", auto_f1, auto_f2>;
using expected_defn =
msg::message<"msg", auto_f1::located<at{0_dw, 31_msb, 0_lsb}>,
auto_f2::located<at{1_dw, 7_msb, 0_lsb}>>;
static_assert(std::is_same_v<defn, expected_defn>);
}

TEST_CASE("automatically packed fields are sorted by size",
"[relaxed_message]") {
using defn = relaxed_message<"msg", auto_f2, auto_f1>;
using expected_defn =
msg::message<"msg", auto_f1::located<at{0_dw, 31_msb, 0_lsb}>,
auto_f2::located<at{1_dw, 7_msb, 0_lsb}>>;
static_assert(std::is_same_v<defn, expected_defn>);
}

TEST_CASE("message with mixed fixed and automatically packed fields",
"[relaxed_message]") {
using defn = relaxed_message<"msg", auto_f2, fixed_f, auto_f1>;
using expected_defn =
msg::message<"msg", fixed_f, auto_f1::located<at{1_dw, 31_msb, 0_lsb}>,
auto_f2::located<at{2_dw, 7_msb, 0_lsb}>>;
static_assert(std::is_same_v<defn, expected_defn>);
}

TEST_CASE("message with no automatically packed fields", "[relaxed_message]") {
using defn = relaxed_message<"msg", fixed_f>;
using expected_defn = msg::message<"msg", fixed_f>;
static_assert(std::is_same_v<defn, expected_defn>);
}
Loading