match: allow message callbacks

The original match constructor only allowed
sd_bus_message_handler_t functions, which does not allow for
sdbusplus::message::message's to be passed in.  Add a
constructor that allows functions of the following type:
    void(*)(sdbusplus::message::message&)

Change-Id: Idc006250777c5cc1a5fe48fc411da24339ca165e
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
diff --git a/sdbusplus/bus/match.hpp b/sdbusplus/bus/match.hpp
index 1daca60..8b15750 100644
--- a/sdbusplus/bus/match.hpp
+++ b/sdbusplus/bus/match.hpp
@@ -1,7 +1,10 @@
 #pragma once
 
+#include <functional>
+#include <memory>
 #include <sdbusplus/slot.hpp>
 #include <sdbusplus/bus.hpp>
+#include <sdbusplus/message.hpp>
 
 namespace sdbusplus
 {
@@ -46,8 +49,40 @@
         _slot = decltype(_slot){slot};
     }
 
+    using callback_t = std::function<void(sdbusplus::message::message&)>;
+
+    /** @brief Register a signal match.
+     *
+     *  @param[in] bus - The bus to register on.
+     *  @param[in] match - The match to register.
+     *  @param[in] callback - The callback for matches.
+     */
+    match(sdbusplus::bus::bus& bus, const char* match,
+          callback_t callback)
+                : _slot(nullptr),
+                  _callback(std::make_unique<callback_t>(std::move(callback)))
+    {
+        sd_bus_slot* slot = nullptr;
+        sd_bus_add_match(bus.get(), &slot, match, callCallback,
+                         _callback.get());
+
+        _slot = decltype(_slot){slot};
+    }
+
     private:
         slot::slot _slot;
+        std::unique_ptr<callback_t> _callback = nullptr;
+
+        static int callCallback(sd_bus_message *m, void* context,
+                                sd_bus_error* e)
+        {
+            auto c = static_cast<callback_t*>(context);
+            message::message message{m};
+
+            (*c)(message);
+
+            return 0;
+        }
 };
 
 } // namespace match
diff --git a/test/bus/match.cpp b/test/bus/match.cpp
index 8b58c9f..764392a 100644
--- a/test/bus/match.cpp
+++ b/test/bus/match.cpp
@@ -29,8 +29,6 @@
 
 TEST_F(Match, FunctorIs_sd_bus_message_handler_t)
 {
-    using namespace std::literals;
-
     bool triggered = false;
     auto trigger = [](sd_bus_message *m, void* context, sd_bus_error* e)
         {
@@ -49,3 +47,52 @@
     waitForIt(triggered);
     ASSERT_TRUE(triggered);
 }
+
+TEST_F(Match, FunctorIs_LambdaTakingMessage)
+{
+    bool triggered = false;
+    auto trigger = [&triggered](sdbusplus::message::message& m)
+        {
+            triggered = true;
+        };
+
+    sdbusplus::bus::match_t m{bus, matchRule, trigger};
+    auto m2 = std::move(m);  // ensure match is move-safe.
+
+    waitForIt(triggered);
+    ASSERT_FALSE(triggered);
+
+    bus.request_name(busName);
+
+    waitForIt(triggered);
+    ASSERT_TRUE(triggered);
+}
+
+TEST_F(Match, FunctorIs_MemberFunctionTakingMessage)
+{
+
+    class BoolHolder
+    {
+        public:
+            bool triggered = false;
+
+            void callback(sdbusplus::message::message& m)
+            {
+                triggered = true;
+            }
+    };
+    BoolHolder b;
+
+    sdbusplus::bus::match_t m{bus, matchRule,
+                              std::bind(std::mem_fn(&BoolHolder::callback),
+                                        &b, std::placeholders::_1)};
+    auto m2 = std::move(m);  // ensure match is move-safe.
+
+    waitForIt(b.triggered);
+    ASSERT_FALSE(b.triggered);
+
+    bus.request_name(busName);
+
+    waitForIt(b.triggered);
+    ASSERT_TRUE(b.triggered);
+}