Skip to content

Commit d5a412a

Browse files
committed
🎨 Allow messages to be handled by value
Messages under a certain size are fine to copy and pass in registers.
1 parent 0fc9366 commit d5a412a

File tree

3 files changed

+76
-13
lines changed

3 files changed

+76
-13
lines changed

include/msg/callback.hpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,31 +24,32 @@ template <stdx::ct_string Name, typename Msg, match::matcher M,
2424
stdx::callable F>
2525
struct callback {
2626
[[nodiscard]] auto is_match(auto const &data) const -> bool {
27-
auto view = typename Msg::view_t{data};
28-
return matcher(view);
27+
return msg::call_with_message<Msg>(matcher, data);
2928
}
3029

3130
template <typename... Args>
32-
[[nodiscard]] auto handle(auto const &data,
33-
Args const &...args) const -> bool {
34-
auto view = typename Msg::view_t{data};
35-
if (matcher(view)) {
31+
[[nodiscard]] auto handle(auto const &data, Args &&...args) const -> bool {
32+
if (msg::call_with_message<Msg>(matcher, data)) {
3633
CIB_INFO("Incoming message matched [{}], because [{}], executing "
3734
"callback",
3835
stdx::ct_string_to_type<Name, sc::string_constant>(),
3936
matcher.describe());
40-
callable(view, args...);
37+
msg::call_with_message<Msg>(callable, data,
38+
std::forward<Args>(args)...);
4139
return true;
4240
}
4341
return false;
4442
}
4543

4644
auto log_mismatch(auto const &data) const -> void {
47-
auto view = typename Msg::view_t{data};
48-
4945
CIB_INFO(" {} - F:({})",
5046
stdx::ct_string_to_type<Name, sc::string_constant>(),
51-
matcher.describe_match(view));
47+
msg::call_with_message<Msg>(
48+
[&]<typename T>(T &&t) -> decltype(matcher.describe_match(
49+
std::forward<T>(t))) {
50+
return matcher.describe_match(std::forward<T>(t));
51+
},
52+
data));
5253
}
5354

5455
using msg_t = Msg;

include/msg/message.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,4 +627,26 @@ template <owninglike O1, owninglike O2>
627627
constexpr auto equivalent(O1 const &lhs, O2 const &rhs) {
628628
return equiv(lhs, rhs.as_const_view());
629629
}
630+
631+
template <typename Msg, typename F, typename S, typename... Args>
632+
constexpr auto call_with_message(F &&f, S &&s,
633+
Args &&...args) -> decltype(auto) {
634+
if constexpr (requires {
635+
std::forward<F>(f)(std::forward<S>(s),
636+
std::forward<Args>(args)...);
637+
}) {
638+
return std::forward<F>(f)(std::forward<S>(s),
639+
std::forward<Args>(args)...);
640+
} else if constexpr (requires {
641+
std::forward<F>(f)(
642+
typename Msg::view_t{std::forward<S>(s)},
643+
std::forward<Args>(args)...);
644+
}) {
645+
return std::forward<F>(f)(typename Msg::view_t{std::forward<S>(s)},
646+
std::forward<Args>(args)...);
647+
} else {
648+
return std::forward<F>(f)(typename Msg::owner_t{std::forward<S>(s)},
649+
std::forward<Args>(args)...);
650+
}
651+
}
630652
} // namespace msg

test/msg/callback.cpp

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,39 @@ using msg_defn = message<"msg", id_field, field1, field2, field3>;
2424

2525
constexpr auto id_match = msg::equal_to<id_field, 0x80>;
2626

27+
constexpr struct custom_match_t {
28+
using is_matcher = void;
29+
30+
[[nodiscard]] constexpr auto operator()(msg::owning<msg_defn>) const {
31+
return true;
32+
}
33+
34+
[[nodiscard]] constexpr static auto describe() { return "custom"_sc; }
35+
36+
[[nodiscard]] constexpr static auto describe_match(msg::owning<msg_defn>) {
37+
return describe();
38+
}
39+
} custom_match;
40+
2741
std::string log_buffer{};
2842
} // namespace
2943

3044
template <>
3145
inline auto logging::config<> =
3246
logging::fmt::config{std::back_inserter(log_buffer)};
3347

34-
TEST_CASE("callback matches message", "[callback]") {
48+
TEST_CASE("callback matches message by view", "[callback]") {
3549
auto callback = msg::callback<"cb", msg_defn>(id_match, [] {});
3650
auto const msg_match = std::array{0x8000ba11u, 0x0042d00du};
3751
CHECK(callback.is_match(msg_match));
3852
}
3953

54+
TEST_CASE("callback matches message by owning", "[callback]") {
55+
auto callback = msg::callback<"cb", msg_defn>(custom_match, [] {});
56+
auto const msg_match = std::array{0x8000ba11u, 0x0042d00du};
57+
CHECK(callback.is_match(msg_match));
58+
}
59+
4060
TEST_CASE("callback matches message (alternative range)", "[callback]") {
4161
auto callback = msg::callback<"cb", msg_defn>(id_match, [] {});
4262
auto const msg_match = std::array<std::uint8_t, 8>{0x11, 0xba, 0x00, 0x80,
@@ -50,7 +70,7 @@ TEST_CASE("callback matches message (typed message)", "[callback]") {
5070
CHECK(callback.is_match(msg_match));
5171
}
5272

53-
TEST_CASE("callback logs mismatch (raw)", "[callback]") {
73+
TEST_CASE("callback logs mismatch by view (raw)", "[callback]") {
5474
auto callback = msg::callback<"cb", msg_defn>(id_match, [] {});
5575
auto const msg_nomatch = std::array{0x8100ba11u, 0x0042d00du};
5676
CHECK(not callback.is_match(msg_nomatch));
@@ -61,6 +81,16 @@ TEST_CASE("callback logs mismatch (raw)", "[callback]") {
6181
CHECK(log_buffer.find("cb - F:(id (0x81) == 0x80)") != std::string::npos);
6282
}
6383

84+
TEST_CASE("callback logs mismatch by owning (raw)", "[callback]") {
85+
auto callback = msg::callback<"cb", msg_defn>(custom_match, [] {});
86+
auto const msg_nomatch = std::array{0x8100ba11u, 0x0042d00du};
87+
88+
log_buffer.clear();
89+
callback.log_mismatch(msg_nomatch);
90+
CAPTURE(log_buffer);
91+
CHECK(log_buffer.find("cb - F:(custom)") != std::string::npos);
92+
}
93+
6494
TEST_CASE("callback logs mismatch (typed)", "[callback]") {
6595
auto callback = msg::callback<"cb", msg_defn>(id_match, [] {});
6696
auto const msg_nomatch = msg::owning<msg_defn>{"id"_field = 0x81};
@@ -72,7 +102,7 @@ TEST_CASE("callback logs mismatch (typed)", "[callback]") {
72102
CHECK(log_buffer.find("cb - F:(id (0x81) == 0x80)") != std::string::npos);
73103
}
74104

75-
TEST_CASE("callback handles message (raw)", "[callback]") {
105+
TEST_CASE("callback handles message by view (raw)", "[callback]") {
76106
auto callback = msg::callback<"cb", msg_defn>(
77107
id_match, [](msg::const_view<msg_defn>) { dispatched = true; });
78108
auto const msg_match = std::array{0x8000ba11u, 0x0042d00du};
@@ -82,6 +112,16 @@ TEST_CASE("callback handles message (raw)", "[callback]") {
82112
CHECK(dispatched);
83113
}
84114

115+
TEST_CASE("callback handles message by owning (raw)", "[callback]") {
116+
auto callback = msg::callback<"cb", msg_defn>(
117+
id_match, [](msg::owning<msg_defn>) { dispatched = true; });
118+
auto const msg_match = std::array{0x8000ba11u, 0x0042d00du};
119+
120+
dispatched = false;
121+
CHECK(callback.handle(msg_match));
122+
CHECK(dispatched);
123+
}
124+
85125
namespace {
86126
template <typename T>
87127
using uint8_view =

0 commit comments

Comments
 (0)