sdbus++: async: server: generate set-property fn
Add binding generation for set-property functions.
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: I3fce183f668ea339a035b8186630ffc04aa9af82
diff --git a/example/calculator-aserver.cpp b/example/calculator-aserver.cpp
index 536ee25..290e0aa 100644
--- a/example/calculator-aserver.cpp
+++ b/example/calculator-aserver.cpp
@@ -13,21 +13,23 @@
ctx.spawn(startup());
}
- auto get_property(owner_t) const
- {
- return "asdf";
- }
-
auto get_property(last_result_t) const
{
return 42;
}
+ bool set_property(last_result_t, auto)
+ {
+ return false;
+ }
+
private:
auto startup() -> sdbusplus::async::task<>
{
ctx.get_bus().request_name("net.poettering.Calculator");
+ status(State::Error);
+
while (1)
{
using namespace std::literals;
diff --git a/include/sdbusplus/async/server.hpp b/include/sdbusplus/async/server.hpp
index cfc4d78..9710d5f 100644
--- a/include/sdbusplus/async/server.hpp
+++ b/include/sdbusplus/async/server.hpp
@@ -76,6 +76,23 @@
i.get_property(Tag{}, m);
});
+/* Determine if a type has a set_property call. */
+template <typename Tag, typename Instance, typename Arg>
+concept has_set_property_nomsg = requires(
+ Instance& i, Arg&& a) { i.set_property(Tag{}, std::forward<Arg>(a)); };
+
+/* Determine if a type has a set property call that requries a msg. */
+template <typename Tag, typename Instance, typename Arg>
+concept has_set_property_msg =
+ requires(Instance& i, sdbusplus::message_t& m, Arg&& a) {
+ i.set_property(Tag{}, m, std::forward<Arg>(a));
+ };
+
+/* Determine if a type has any set_property call. */
+template <typename Tag, typename Instance, typename Arg>
+concept has_set_property = has_set_property_nomsg<Tag, Instance, Arg> ||
+ has_set_property_msg<Tag, Instance, Arg>;
+
} // namespace server::details
} // namespace sdbusplus::async
diff --git a/tools/meson.build b/tools/meson.build
index dfc1f03..1538289 100644
--- a/tools/meson.build
+++ b/tools/meson.build
@@ -26,6 +26,7 @@
'sdbusplus/templates/property.md.mako',
'sdbusplus/templates/property.aserver.callback.hpp.mako',
'sdbusplus/templates/property.aserver.get.hpp.mako',
+ 'sdbusplus/templates/property.aserver.set.hpp.mako',
'sdbusplus/templates/property.aserver.tag.hpp.mako',
'sdbusplus/templates/property.aserver.typeid.hpp.mako',
'sdbusplus/templates/property.aserver.value.hpp.mako',
diff --git a/tools/sdbusplus/templates/interface.aserver.hpp.mako b/tools/sdbusplus/templates/interface.aserver.hpp.mako
index f6e419b..2f1189e 100644
--- a/tools/sdbusplus/templates/interface.aserver.hpp.mako
+++ b/tools/sdbusplus/templates/interface.aserver.hpp.mako
@@ -76,6 +76,9 @@
% for p in interface.properties:
${p.render(loader, "property.aserver.get.hpp.mako", property=p, interface=interface)}
% endfor
+% for p in interface.properties:
+${p.render(loader, "property.aserver.set.hpp.mako", property=p, interface=interface)}
+% endfor
private:
/** @return the async context */
diff --git a/tools/sdbusplus/templates/property.aserver.callback.hpp.mako b/tools/sdbusplus/templates/property.aserver.callback.hpp.mako
index aa43b98..58f3df4 100644
--- a/tools/sdbusplus/templates/property.aserver.callback.hpp.mako
+++ b/tools/sdbusplus/templates/property.aserver.callback.hpp.mako
@@ -57,6 +57,41 @@
sd_bus_message* value[[maybe_unused]], void* context [[maybe_unused]],
sd_bus_error* error [[maybe_unused]])
{
- return -EINVAL;
+ auto self = static_cast<${i_name}*>(context);
+
+ try
+ {
+ auto m = sdbusplus::message_t{value};
+
+ // Set up the transaction.
+ server::transaction::set_id(m);
+
+ auto new_value = m.unpack<${p_type}>();
+
+ // Get property value and add to message.
+ if constexpr (server_details::has_set_property_msg<
+ ${p_tag}, Instance, ${p_type}>)
+ {
+ self->${p_name}(m, std::move(new_value));
+ }
+ else
+ {
+ self->${p_name}(std::move(new_value));
+ }
+ }
+ % for e in property.errors:
+ catch (const ${interface.errorNamespacedClass(e)}& e)
+ {
+ return sd_bus_error_set(error, e.name(), e.description());
+ }
+ % endfor
+ catch (const std::exception&)
+ {
+ self->_context().get_bus().set_current_exception(
+ std::current_exception());
+ return -EINVAL;
+ }
+
+ return 1;
}
% endif
diff --git a/tools/sdbusplus/templates/property.aserver.set.hpp.mako b/tools/sdbusplus/templates/property.aserver.set.hpp.mako
new file mode 100644
index 0000000..e6dfc49
--- /dev/null
+++ b/tools/sdbusplus/templates/property.aserver.set.hpp.mako
@@ -0,0 +1,51 @@
+<%
+p_name = property.snake_case;
+p_tag = property.snake_case + "_t"
+p_type = property.cppTypeParam(interface.name)
+i_name = interface.joinedName("_", "interface")
+%>\
+ template <bool EmitSignal = true, typename Arg = ${p_type}>
+ void ${p_name}(Arg&& new_value)
+ requires server_details::has_set_property_nomsg<${p_tag}, Instance,
+ ${p_type}>
+ {
+ bool changed = static_cast<Instance*>(this)->set_property(
+ ${p_tag}{}, std::forward<Arg>(new_value));
+
+ if (changed && EmitSignal)
+ {
+ _${i_name}.property_changed("${property.name}");
+ }
+ }
+
+ template <bool EmitSignal = true, typename Arg = ${p_type}>
+ void ${p_name}(sdbusplus::message_t& m, Arg&& new_value)
+ requires server_details::has_set_property_msg<${p_tag}, Instance,
+ ${p_type}>
+ {
+ bool changed = static_cast<Instance*>(this)->set_property(
+ ${p_tag}{}, m, std::forward<Arg>(new_value));
+
+ if (changed && EmitSignal)
+ {
+ _${i_name}.property_changed("${property.name}");
+ }
+ }
+
+ template <bool EmitSignal = true, typename Arg = ${p_type}>
+ void ${p_name}(Arg&& new_value)
+ requires (!server_details::has_set_property<${p_tag}, Instance,
+ ${p_type}>)
+ {
+ static_assert(
+ !server_details::has_get_property<${p_tag}, Instance>,
+ "Cannot create default set-property for '${p_tag}' with get-property overload.");
+
+ bool changed = (new_value != _${p_name});
+ _${p_name} = std::forward<Arg>(new_value);
+
+ if (changed && EmitSignal)
+ {
+ _${i_name}.property_changed("${property.name}");
+ }
+ }