Skip to content
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
21 changes: 11 additions & 10 deletions include/msg/callback.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,32 @@ template <stdx::ct_string Name, typename Msg, match::matcher M,
stdx::callable F>
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<Msg>(matcher, data);
}

template <typename... Args>
[[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<Msg>(matcher, data)) {
CIB_INFO("Incoming message matched [{}], because [{}], executing "
"callback",
stdx::ct_string_to_type<Name, sc::string_constant>(),
matcher.describe());
callable(view, args...);
msg::call_with_message<Msg>(callable, data,
std::forward<Args>(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<Name, sc::string_constant>(),
matcher.describe_match(view));
msg::call_with_message<Msg>(
[&]<typename T>(T &&t) -> decltype(matcher.describe_match(
std::forward<T>(t))) {
return matcher.describe_match(std::forward<T>(t));
},
data));
}

using msg_t = Msg;
Expand Down
22 changes: 22 additions & 0 deletions include/msg/message.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,4 +627,26 @@ template <owninglike O1, owninglike O2>
constexpr auto equivalent(O1 const &lhs, O2 const &rhs) {
return equiv(lhs, rhs.as_const_view());
}

template <typename Msg, typename F, typename S, typename... Args>
constexpr auto call_with_message(F &&f, S &&s,
Args &&...args) -> decltype(auto) {
if constexpr (requires {
std::forward<F>(f)(std::forward<S>(s),
std::forward<Args>(args)...);
}) {
return std::forward<F>(f)(std::forward<S>(s),
std::forward<Args>(args)...);
} else if constexpr (requires {
std::forward<F>(f)(
typename Msg::view_t{std::forward<S>(s)},
std::forward<Args>(args)...);
}) {
return std::forward<F>(f)(typename Msg::view_t{std::forward<S>(s)},
std::forward<Args>(args)...);
} else {
return std::forward<F>(f)(typename Msg::owner_t{std::forward<S>(s)},
std::forward<Args>(args)...);
}
}
} // namespace msg
46 changes: 43 additions & 3 deletions test/msg/callback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,39 @@ using msg_defn = message<"msg", id_field, field1, field2, field3>;

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

constexpr struct custom_match_t {
using is_matcher = void;

[[nodiscard]] constexpr auto operator()(msg::owning<msg_defn>) const {
return true;
}

[[nodiscard]] constexpr static auto describe() { return "custom"_sc; }

[[nodiscard]] constexpr static auto describe_match(msg::owning<msg_defn>) {
return describe();
}
} custom_match;

std::string log_buffer{};
} // namespace

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<std::uint8_t, 8>{0x11, 0xba, 0x00, 0x80,
Expand All @@ -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));
Expand All @@ -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<msg_defn>{"id"_field = 0x81};
Expand All @@ -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<msg_defn>) { dispatched = true; });
auto const msg_match = std::array{0x8000ba11u, 0x0042d00du};
Expand All @@ -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<msg_defn>) { dispatched = true; });
auto const msg_match = std::array{0x8000ba11u, 0x0042d00du};

dispatched = false;
CHECK(callback.handle(msg_match));
CHECK(dispatched);
}

namespace {
template <typename T>
using uint8_view =
Expand Down