blob: db429b86f2522f6183a27682b8b7b522a9550b06 [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,
51 const Interface&)
52 {
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,
61 const Interface& props)
62 {
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
73 return std::any(std::make_shared<T>(bus, path, v));
74 }
75};
76
77template <typename T, typename Enable = void>
78struct AssignInterface
79{
80 static void op(const Interface&, std::any&)
81 {
82 }
83};
84
85template <typename T>
86struct AssignInterface<T, std::enable_if_t<HasProperties<T>::value>>
87{
88 static void op(const Interface& props, std::any& holder)
89 {
90 auto& iface = *std::any_cast<std::shared_ptr<T>&>(holder);
91 for (const auto& p : props)
92 {
93 iface.setPropertyByName(
94 p.first,
95 convertVariant<typename T::PropertiesVariant>(p.second));
96 }
97 }
98};
99
100template <typename T, typename Ops, typename Enable = void>
101struct SerializeInterface
102{
103 static void op(const std::string& path, const std::string& iface,
104 const std::any&)
105 {
106 Ops::serialize(path, iface);
107 }
108};
109
110template <typename T, typename Ops>
111struct SerializeInterface<T, Ops, std::enable_if_t<HasProperties<T>::value>>
112{
113 static void op(const std::string& path, const std::string& iface,
114 const std::any& holder)
115 {
116 const auto& object = *std::any_cast<const std::shared_ptr<T>&>(holder);
117 Ops::serialize(path, iface, object);
118 }
119};
120
121template <typename T, typename Ops, typename Enable = void>
122struct DeserializeInterface
123{
124 static void op(const std::string& path, const std::string& iface, std::any&)
125 {
126 Ops::deserialize(path, iface);
127 }
128};
129
130template <typename T, typename Ops>
131struct DeserializeInterface<T, Ops, std::enable_if_t<HasProperties<T>::value>>
132{
133 static void op(const std::string& path, const std::string& iface,
134 std::any& holder)
135 {
136 auto& object = *std::any_cast<std::shared_ptr<T>&>(holder);
137 Ops::deserialize(path, iface, object);
138 }
139};
140
141struct DummyInterface
142{
143};
144using MakeInterfaceType =
145 std::add_pointer_t<decltype(MakeInterface<DummyInterface>::op)>;
146using AssignInterfaceType =
147 std::add_pointer_t<decltype(AssignInterface<DummyInterface>::op)>;
148template <typename Ops>
149using SerializeInterfaceType =
150 std::add_pointer_t<decltype(SerializeInterface<DummyInterface, Ops>::op)>;
151template <typename Ops>
152using DeserializeInterfaceType =
153 std::add_pointer_t<decltype(DeserializeInterface<DummyInterface, Ops>::op)>;
154
155} // namespace manager
156} // namespace inventory
157} // namespace phosphor