Skip to content

Commit 0556202

Browse files
authored
Merge pull request #687 from elbeno/relaxed-field-builders
🎨 Allow "relaxed" fields to have defaults, matchers etc
2 parents a2da186 + d3eb6f5 commit 0556202

File tree

2 files changed

+38
-11
lines changed

2 files changed

+38
-11
lines changed

include/msg/field.hpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -389,13 +389,19 @@ concept compatible_with_default = D::template is_compatible_value<V>;
389389
template <typename Name, typename T = std::uint32_t, auto... Ats>
390390
struct field_id_t {};
391391

392+
template <at... Ats> struct sort_key_t {
393+
constexpr static auto sort_key = std::min({Ats.sort_key()...});
394+
};
395+
template <> struct sort_key_t<> {};
396+
392397
template <typename Name, typename T = std::uint32_t,
393398
typename Default = detail::with_default<T>,
394399
match::matcher M = match::always_t, at... Ats>
395400
requires std::is_trivially_copyable_v<T>
396401
class field_t : public field_spec_t<Name, T, detail::field_size<Ats...>>,
397402
public detail::locator_for<Ats...>,
398-
public Default {
403+
public Default,
404+
public sort_key_t<Ats...> {
399405
using spec_t = field_spec_t<Name, T, detail::field_size<Ats...>>;
400406
using locator_t = detail::locator_for<Ats...>;
401407

@@ -412,7 +418,6 @@ class field_t : public field_spec_t<Name, T, detail::field_size<Ats...>>,
412418
using field_id = field_id_t<Name, T, Ats...>;
413419
using value_type = T;
414420
using matcher_t = M;
415-
constexpr static auto sort_key = std::min({Ats.sort_key()...});
416421

417422
template <stdx::range R>
418423
[[nodiscard]] constexpr static auto extract(R &&r) -> value_type {
@@ -511,6 +516,12 @@ class field_t : public field_spec_t<Name, T, detail::field_size<Ats...>>,
511516
using shifted_by =
512517
field_t<Name, T, Default, M, Ats.shifted_by(unit_bit_size<Unit>(N))...>;
513518

519+
template <at... NewAts>
520+
using located = field_t<Name, T, Default, M, NewAts...>;
521+
522+
constexpr static auto bitsize = sizeof(T) * CHAR_BIT;
523+
using default_located = located<at{msb_t{bitsize - 1}, lsb_t{}}>;
524+
514525
// ======================================================================
515526
// legacy aliases
516527
template <typename X> using WithMatch = with_matcher<X>;
@@ -527,13 +538,7 @@ class field_t : public field_spec_t<Name, T, detail::field_size<Ats...>>,
527538
template <stdx::ct_string Name, typename T = std::uint32_t,
528539
typename Default = detail::with_default<T>,
529540
match::matcher M = match::always_t>
530-
struct field {
531-
template <at... Ats>
532-
using located = detail::field_t<
533-
decltype(stdx::ct_string_to_type<Name, sc::string_constant>()), T,
534-
Default, M, Ats...>;
535-
536-
constexpr static auto bitsize = sizeof(T) * CHAR_BIT;
537-
using default_located = located<at{msb_t{bitsize - 1}, lsb_t{}}>;
538-
};
541+
using field = detail::field_t<
542+
decltype(stdx::ct_string_to_type<Name, sc::string_constant>()), T, Default,
543+
M>;
539544
} // namespace msg

test/msg/relaxed_message.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,25 @@ TEST_CASE("message with no automatically packed fields", "[relaxed_message]") {
4343
using expected_defn = msg::message<"msg", fixed_f>;
4444
static_assert(std::is_same_v<defn, expected_defn>);
4545
}
46+
47+
TEST_CASE("auto field with default value", "[relaxed_message]") {
48+
using defn = relaxed_message<"msg", auto_f1::with_default<42>>;
49+
using expected_defn = msg::message<
50+
"msg", auto_f1::located<at{0_dw, 31_msb, 0_lsb}>::with_default<42>>;
51+
static_assert(std::is_same_v<defn, expected_defn>);
52+
}
53+
54+
TEST_CASE("auto field with const default value", "[relaxed_message]") {
55+
using defn = relaxed_message<"msg", auto_f1::with_const_default<42>>;
56+
using expected_defn =
57+
msg::message<"msg", auto_f1::located<at{
58+
0_dw, 31_msb, 0_lsb}>::with_const_default<42>>;
59+
static_assert(std::is_same_v<defn, expected_defn>);
60+
}
61+
62+
TEST_CASE("auto field without default value", "[relaxed_message]") {
63+
using defn = relaxed_message<"msg", auto_f1::without_default>;
64+
using expected_defn = msg::message<
65+
"msg", auto_f1::located<at{0_dw, 31_msb, 0_lsb}>::without_default>;
66+
static_assert(std::is_same_v<defn, expected_defn>);
67+
}

0 commit comments

Comments
 (0)