1#pragma once 2#include <sdbusplus/async/client.hpp> 3#include <sdbusplus/async/execution.hpp> 4#include <type_traits> 5#include <variant> 6 7% for h in interface.cpp_includes(): 8#include <${h}> 9% endfor 10#include <${interface.headerFile()}> 11 12namespace sdbusplus::client::${interface.cppNamespace()} 13{ 14 15namespace details 16{ 17// forward declaration 18template <typename Client, typename Proxy> 19class ${interface.classname}; 20} // namespace details 21 22/** Alias class so we can use the client in both a client_t aggregation 23 * and individually. 24 * 25 * sdbusplus::async::client_t<${interface.classname}>() or 26 * ${interface.classname}() both construct an equivalent instance. 27 */ 28template <typename Client = void, typename Proxy = void> 29struct ${interface.classname} : 30 public std::conditional_t<std::is_void_v<Client>, 31 sdbusplus::async::client_t<details::${interface.classname}>, 32 details::${interface.classname}<Client, Proxy>> 33{ 34 template <typename... Args> 35 ${interface.classname}(Args&&... args) : 36 std::conditional_t<std::is_void_v<Client>, 37 sdbusplus::async::client_t<details::${interface.classname}>, 38 details::${interface.classname}<Client, Proxy>>( 39 std::forward<Args>(args)...) 40 {} 41}; 42 43namespace details 44{ 45 46template <typename Client, typename Proxy> 47class ${interface.classname} : 48 public sdbusplus::common::${interface.cppNamespacedClass()}, 49 private sdbusplus::async::client::details::client_context_friend 50{ 51 public: 52 friend Client; 53 template <typename, typename> 54 friend struct sdbusplus::client::${interface.cppNamespacedClass()}; 55 56 // Delete default constructor as these should only be constructed 57 // indirectly through sdbusplus::async::client_t. 58 ${interface.classname}() = delete; 59 60 % for m in interface.methods: 61${m.render(loader, "method.client.hpp.mako", method=m, interface=interface)} 62 % endfor 63 % for p in interface.properties: 64${p.render(loader, "property.client.hpp.mako", property=p, interface=interface)} 65 % endfor 66 67 % if interface.properties: 68 auto properties() 69 { 70 return proxy.template get_all_properties<PropertiesVariant>(context()) | 71 sdbusplus::async::execution::then([](auto&& v) { 72 properties_t result; 73 for (const auto& [property, value] : v) 74 { 75 std::visit( 76 [&](auto v) { 77 % for p in interface.properties: 78 if (property == "${p.name}") 79 { 80 if constexpr (std::is_same_v< 81 std::decay_t<decltype(v)>, 82 ${p.cppTypeParam(interface.name)}>) 83 { 84 result.${p.snake_case} = v; 85 return; 86 } 87 else 88 { 89 throw exception::UnpackPropertyError( 90 property, 91 UnpackErrorReason::wrongType); 92 } 93 } 94 % endfor 95 }, 96 value); 97 } 98 return result; 99 }); 100 } 101 % endif 102 103 private: 104 // Conversion constructor from proxy used by client_t. 105 explicit constexpr ${interface.classname}(Proxy p) : 106 proxy(p.interface(interface)) 107 {} 108 109 sdbusplus::async::context& context() 110 { 111 return sdbusplus::async::client::details::client_context_friend:: 112 context<Client, ${interface.classname}>(this); 113 } 114 115 decltype(std::declval<Proxy>().interface(interface)) proxy = {}; 116}; 117 118} // namespace details 119 120} // namespace sdbusplus::client::${interface.cppNamespace()} 121