xref: /openbmc/sdbusplus/tools/sdbusplus/templates/interface.client.hpp.mako (revision 6bb7a8c9a34d805a624b9679b171e11a6d106f09)
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