blob: 98b0ffb87f232f54b4f1b9c849bdd882761672a4 [file] [log] [blame]
Brad Bishop9cc42ab2018-12-12 16:36:51 -05001#pragma once
2
3#include "types.hpp"
4#include "utils.hpp"
5
6#include <any>
7#include <map>
8#include <memory>
9#include <string>
10#include <type_traits>
11#include <utility>
12
13namespace sdbusplus
14{
15namespace bus
16{
17class bus;
18}
19} // namespace sdbusplus
20
21namespace phosphor
22{
23namespace inventory
24{
25namespace manager
26{
27
28template <typename T>
29struct HasProperties
30{
31 private:
32 using yes = char;
33 struct no
34 {
35 char array[2];
36 };
37
38 template <typename U>
39 static constexpr yes test(typename U::PropertiesVariant*);
40 template <typename U>
41 static constexpr no test(...);
42
43 public:
44 static constexpr auto value = sizeof(test<T>(0)) == sizeof(yes);
45};
46
47template <typename T, typename Enable = void>
48struct MakeInterface
49{
50 static std::any op(sdbusplus::bus::bus& bus, const char* path,
Brad Bishope96f2aa2020-12-06 19:09:09 -050051 const Interface&, bool)
Brad Bishop9cc42ab2018-12-12 16:36:51 -050052 {
53 return std::any(std::make_shared<T>(bus, path));
54 }
55};
56
57template <typename T>
58struct MakeInterface<T, std::enable_if_t<HasProperties<T>::value>>
59{
60 static std::any op(sdbusplus::bus::bus& bus, const char* path,
Brad Bishope96f2aa2020-12-06 19:09:09 -050061 const Interface& props, bool deferSignal)
Brad Bishop9cc42ab2018-12-12 16:36:51 -050062 {
63 using InterfaceVariant =
64 std::map<std::string, typename T::PropertiesVariant>;
65
66 InterfaceVariant v;
67 for (const auto& p : props)
68 {
69 v.emplace(p.first,
70 convertVariant<typename T::PropertiesVariant>(p.second));
71 }
72
Brad Bishope96f2aa2020-12-06 19:09:09 -050073 return std::any(std::make_shared<T>(bus, path, v, deferSignal));
Brad Bishop9cc42ab2018-12-12 16:36:51 -050074 }
75};
76
77template <typename T, typename Enable = void>
Matt Spinler59521e82021-02-11 13:41:06 -060078struct GetPropertyValue
79{
George Liu23314a52022-04-13 18:26:03 +080080 static InterfaceVariantType op(const std::string /* propertyName */,
81 std::any& /* holder */)
Matt Spinler59521e82021-02-11 13:41:06 -060082 {
83 return InterfaceVariantType{};
84 }
85};
86
87template <typename T>
88struct GetPropertyValue<T, std::enable_if_t<HasProperties<T>::value>>
89{
90 static InterfaceVariantType op(const std::string propertyName,
91 std::any& holder)
92 {
93 auto& iface = *std::any_cast<std::shared_ptr<T>&>(holder);
94 auto property = iface.getPropertyByName(propertyName);
95 return convertVariant<InterfaceVariantType>(property);
96 }
97};
98
99template <typename T, typename Enable = void>
Brad Bishop9cc42ab2018-12-12 16:36:51 -0500100struct AssignInterface
101{
Brad Bishope96f2aa2020-12-06 19:09:09 -0500102 static void op(const Interface&, std::any&, bool)
Brad Bishopa83db302020-12-06 14:51:23 -0500103 {}
Brad Bishop9cc42ab2018-12-12 16:36:51 -0500104};
105
106template <typename T>
107struct AssignInterface<T, std::enable_if_t<HasProperties<T>::value>>
108{
Brad Bishope96f2aa2020-12-06 19:09:09 -0500109 static void op(const Interface& props, std::any& holder, bool deferSignal)
Brad Bishop9cc42ab2018-12-12 16:36:51 -0500110 {
111 auto& iface = *std::any_cast<std::shared_ptr<T>&>(holder);
112 for (const auto& p : props)
113 {
114 iface.setPropertyByName(
115 p.first,
Brad Bishope96f2aa2020-12-06 19:09:09 -0500116 convertVariant<typename T::PropertiesVariant>(p.second),
117 deferSignal);
Brad Bishop9cc42ab2018-12-12 16:36:51 -0500118 }
119 }
120};
121
122template <typename T, typename Ops, typename Enable = void>
123struct SerializeInterface
124{
125 static void op(const std::string& path, const std::string& iface,
126 const std::any&)
127 {
128 Ops::serialize(path, iface);
129 }
130};
131
132template <typename T, typename Ops>
133struct SerializeInterface<T, Ops, std::enable_if_t<HasProperties<T>::value>>
134{
135 static void op(const std::string& path, const std::string& iface,
136 const std::any& holder)
137 {
138 const auto& object = *std::any_cast<const std::shared_ptr<T>&>(holder);
139 Ops::serialize(path, iface, object);
140 }
141};
142
143template <typename T, typename Ops, typename Enable = void>
144struct DeserializeInterface
145{
146 static void op(const std::string& path, const std::string& iface, std::any&)
147 {
148 Ops::deserialize(path, iface);
149 }
150};
151
152template <typename T, typename Ops>
153struct DeserializeInterface<T, Ops, std::enable_if_t<HasProperties<T>::value>>
154{
155 static void op(const std::string& path, const std::string& iface,
156 std::any& holder)
157 {
158 auto& object = *std::any_cast<std::shared_ptr<T>&>(holder);
159 Ops::deserialize(path, iface, object);
160 }
161};
162
163struct DummyInterface
Brad Bishopa83db302020-12-06 14:51:23 -0500164{};
Brad Bishop9cc42ab2018-12-12 16:36:51 -0500165using MakeInterfaceType =
166 std::add_pointer_t<decltype(MakeInterface<DummyInterface>::op)>;
167using AssignInterfaceType =
168 std::add_pointer_t<decltype(AssignInterface<DummyInterface>::op)>;
169template <typename Ops>
170using SerializeInterfaceType =
171 std::add_pointer_t<decltype(SerializeInterface<DummyInterface, Ops>::op)>;
172template <typename Ops>
173using DeserializeInterfaceType =
174 std::add_pointer_t<decltype(DeserializeInterface<DummyInterface, Ops>::op)>;
Matt Spinler59521e82021-02-11 13:41:06 -0600175using GetPropertyValueType =
176 std::add_pointer_t<decltype(GetPropertyValue<DummyInterface>::op)>;
Brad Bishop9cc42ab2018-12-12 16:36:51 -0500177
178} // namespace manager
179} // namespace inventory
180} // namespace phosphor