diff --git a/include/msg/callback.hpp b/include/msg/callback.hpp index 46d6e293..e6f3a1b4 100644 --- a/include/msg/callback.hpp +++ b/include/msg/callback.hpp @@ -24,31 +24,32 @@ template struct callback { [[nodiscard]] auto is_match(auto const &data) const -> bool { - auto view = typename Msg::view_t{data}; - return matcher(view); + return msg::call_with_message(matcher, data); } template - [[nodiscard]] auto handle(auto const &data, - Args const &...args) const -> bool { - auto view = typename Msg::view_t{data}; - if (matcher(view)) { + [[nodiscard]] auto handle(auto const &data, Args &&...args) const -> bool { + if (msg::call_with_message(matcher, data)) { CIB_INFO("Incoming message matched [{}], because [{}], executing " "callback", stdx::ct_string_to_type(), matcher.describe()); - callable(view, args...); + msg::call_with_message(callable, data, + std::forward(args)...); return true; } return false; } auto log_mismatch(auto const &data) const -> void { - auto view = typename Msg::view_t{data}; - CIB_INFO(" {} - F:({})", stdx::ct_string_to_type(), - matcher.describe_match(view)); + msg::call_with_message( + [&](T &&t) -> decltype(matcher.describe_match( + std::forward(t))) { + return matcher.describe_match(std::forward(t)); + }, + data)); } using msg_t = Msg; diff --git a/include/msg/message.hpp b/include/msg/message.hpp index 06af11a6..1035fcbe 100644 --- a/include/msg/message.hpp +++ b/include/msg/message.hpp @@ -627,4 +627,26 @@ template constexpr auto equivalent(O1 const &lhs, O2 const &rhs) { return equiv(lhs, rhs.as_const_view()); } + +template +constexpr auto call_with_message(F &&f, S &&s, + Args &&...args) -> decltype(auto) { + if constexpr (requires { + std::forward(f)(std::forward(s), + std::forward(args)...); + }) { + return std::forward(f)(std::forward(s), + std::forward(args)...); + } else if constexpr (requires { + std::forward(f)( + typename Msg::view_t{std::forward(s)}, + std::forward(args)...); + }) { + return std::forward(f)(typename Msg::view_t{std::forward(s)}, + std::forward(args)...); + } else { + return std::forward(f)(typename Msg::owner_t{std::forward(s)}, + std::forward(args)...); + } +} } // namespace msg diff --git a/test/msg/callback.cpp b/test/msg/callback.cpp index e5434fdf..e23761e2 100644 --- a/test/msg/callback.cpp +++ b/test/msg/callback.cpp @@ -24,6 +24,20 @@ using msg_defn = message<"msg", id_field, field1, field2, field3>; constexpr auto id_match = msg::equal_to; +constexpr struct custom_match_t { + using is_matcher = void; + + [[nodiscard]] constexpr auto operator()(msg::owning) const { + return true; + } + + [[nodiscard]] constexpr static auto describe() { return "custom"_sc; } + + [[nodiscard]] constexpr static auto describe_match(msg::owning) { + return describe(); + } +} custom_match; + std::string log_buffer{}; } // namespace @@ -31,12 +45,18 @@ template <> inline auto logging::config<> = logging::fmt::config{std::back_inserter(log_buffer)}; -TEST_CASE("callback matches message", "[callback]") { +TEST_CASE("callback matches message by view", "[callback]") { auto callback = msg::callback<"cb", msg_defn>(id_match, [] {}); auto const msg_match = std::array{0x8000ba11u, 0x0042d00du}; CHECK(callback.is_match(msg_match)); } +TEST_CASE("callback matches message by owning", "[callback]") { + auto callback = msg::callback<"cb", msg_defn>(custom_match, [] {}); + auto const msg_match = std::array{0x8000ba11u, 0x0042d00du}; + CHECK(callback.is_match(msg_match)); +} + TEST_CASE("callback matches message (alternative range)", "[callback]") { auto callback = msg::callback<"cb", msg_defn>(id_match, [] {}); auto const msg_match = std::array{0x11, 0xba, 0x00, 0x80, @@ -50,7 +70,7 @@ TEST_CASE("callback matches message (typed message)", "[callback]") { CHECK(callback.is_match(msg_match)); } -TEST_CASE("callback logs mismatch (raw)", "[callback]") { +TEST_CASE("callback logs mismatch by view (raw)", "[callback]") { auto callback = msg::callback<"cb", msg_defn>(id_match, [] {}); auto const msg_nomatch = std::array{0x8100ba11u, 0x0042d00du}; CHECK(not callback.is_match(msg_nomatch)); @@ -61,6 +81,16 @@ TEST_CASE("callback logs mismatch (raw)", "[callback]") { CHECK(log_buffer.find("cb - F:(id (0x81) == 0x80)") != std::string::npos); } +TEST_CASE("callback logs mismatch by owning (raw)", "[callback]") { + auto callback = msg::callback<"cb", msg_defn>(custom_match, [] {}); + auto const msg_nomatch = std::array{0x8100ba11u, 0x0042d00du}; + + log_buffer.clear(); + callback.log_mismatch(msg_nomatch); + CAPTURE(log_buffer); + CHECK(log_buffer.find("cb - F:(custom)") != std::string::npos); +} + TEST_CASE("callback logs mismatch (typed)", "[callback]") { auto callback = msg::callback<"cb", msg_defn>(id_match, [] {}); auto const msg_nomatch = msg::owning{"id"_field = 0x81}; @@ -72,7 +102,7 @@ TEST_CASE("callback logs mismatch (typed)", "[callback]") { CHECK(log_buffer.find("cb - F:(id (0x81) == 0x80)") != std::string::npos); } -TEST_CASE("callback handles message (raw)", "[callback]") { +TEST_CASE("callback handles message by view (raw)", "[callback]") { auto callback = msg::callback<"cb", msg_defn>( id_match, [](msg::const_view) { dispatched = true; }); auto const msg_match = std::array{0x8000ba11u, 0x0042d00du}; @@ -82,6 +112,16 @@ TEST_CASE("callback handles message (raw)", "[callback]") { CHECK(dispatched); } +TEST_CASE("callback handles message by owning (raw)", "[callback]") { + auto callback = msg::callback<"cb", msg_defn>( + id_match, [](msg::owning) { dispatched = true; }); + auto const msg_match = std::array{0x8000ba11u, 0x0042d00du}; + + dispatched = false; + CHECK(callback.handle(msg_match)); + CHECK(dispatched); +} + namespace { template using uint8_view =