1 #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 
13 namespace sdbusplus
14 {
15 namespace bus
16 {
17 class bus;
18 }
19 } // namespace sdbusplus
20 
21 namespace phosphor
22 {
23 namespace inventory
24 {
25 namespace manager
26 {
27 
28 template <typename T>
29 struct 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 
47 template <typename T, typename Enable = void>
48 struct MakeInterface
49 {
opphosphor::inventory::manager::MakeInterface50     static std::any op(sdbusplus::bus_t& bus, const char* path,
51                        const Interface&, bool)
52     {
53         return std::any(std::make_shared<T>(bus, path));
54     }
55 };
56 
57 template <typename T>
58 struct MakeInterface<T, std::enable_if_t<HasProperties<T>::value>>
59 {
opphosphor::inventory::manager::MakeInterface60     static std::any op(sdbusplus::bus_t& bus, const char* path,
61                        const Interface& props, bool deferSignal)
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, deferSignal));
74     }
75 };
76 
77 template <typename T, typename Enable = void>
78 struct GetPropertyValue
79 {
opphosphor::inventory::manager::GetPropertyValue80     static InterfaceVariantType op(const std::string /* propertyName */,
81                                    std::any& /* holder */)
82     {
83         return InterfaceVariantType{};
84     }
85 };
86 
87 template <typename T>
88 struct GetPropertyValue<T, std::enable_if_t<HasProperties<T>::value>>
89 {
opphosphor::inventory::manager::GetPropertyValue90     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 
99 template <typename T, typename Enable = void>
100 struct AssignInterface
101 {
opphosphor::inventory::manager::AssignInterface102     static void op(const Interface&, std::any&, bool) {}
103 };
104 
105 template <typename T>
106 struct AssignInterface<T, std::enable_if_t<HasProperties<T>::value>>
107 {
opphosphor::inventory::manager::AssignInterface108     static void op(const Interface& props, std::any& holder, bool deferSignal)
109     {
110         auto& iface = *std::any_cast<std::shared_ptr<T>&>(holder);
111         for (const auto& p : props)
112         {
113             iface.setPropertyByName(
114                 p.first,
115                 convertVariant<typename T::PropertiesVariant>(p.second),
116                 deferSignal);
117         }
118     }
119 };
120 
121 template <typename T, typename Ops, typename Enable = void>
122 struct SerializeInterface
123 {
opphosphor::inventory::manager::SerializeInterface124     static void op(const std::string& path, const std::string& iface,
125                    const std::any&)
126     {
127         Ops::serialize(path, iface);
128     }
129 };
130 
131 template <typename T, typename Ops>
132 struct SerializeInterface<T, Ops, std::enable_if_t<HasProperties<T>::value>>
133 {
opphosphor::inventory::manager::SerializeInterface134     static void op(const std::string& path, const std::string& iface,
135                    const std::any& holder)
136     {
137         const auto& object = *std::any_cast<const std::shared_ptr<T>&>(holder);
138         Ops::serialize(path, iface, object);
139     }
140 };
141 
142 template <typename T, typename Ops, typename Enable = void>
143 struct DeserializeInterface
144 {
opphosphor::inventory::manager::DeserializeInterface145     static void op(const std::string& path, const std::string& iface, std::any&)
146     {
147         Ops::deserialize(path, iface);
148     }
149 };
150 
151 template <typename T, typename Ops>
152 struct DeserializeInterface<T, Ops, std::enable_if_t<HasProperties<T>::value>>
153 {
opphosphor::inventory::manager::DeserializeInterface154     static void op(const std::string& path, const std::string& iface,
155                    std::any& holder)
156     {
157         auto& object = *std::any_cast<std::shared_ptr<T>&>(holder);
158         Ops::deserialize(path, iface, object);
159     }
160 };
161 
162 struct DummyInterface
163 {};
164 using MakeInterfaceType =
165     std::add_pointer_t<decltype(MakeInterface<DummyInterface>::op)>;
166 using AssignInterfaceType =
167     std::add_pointer_t<decltype(AssignInterface<DummyInterface>::op)>;
168 template <typename Ops>
169 using SerializeInterfaceType =
170     std::add_pointer_t<decltype(SerializeInterface<DummyInterface, Ops>::op)>;
171 template <typename Ops>
172 using DeserializeInterfaceType =
173     std::add_pointer_t<decltype(DeserializeInterface<DummyInterface, Ops>::op)>;
174 using GetPropertyValueType =
175     std::add_pointer_t<decltype(GetPropertyValue<DummyInterface>::op)>;
176 
177 } // namespace manager
178 } // namespace inventory
179 } // namespace phosphor
180