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 {
50     static std::any op(sdbusplus::bus::bus& 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 {
60     static std::any op(sdbusplus::bus::bus& 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 {
80     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 {
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 
99 template <typename T, typename Enable = void>
100 struct AssignInterface
101 {
102     static void op(const Interface&, std::any&, bool)
103     {}
104 };
105 
106 template <typename T>
107 struct AssignInterface<T, std::enable_if_t<HasProperties<T>::value>>
108 {
109     static void op(const Interface& props, std::any& holder, bool deferSignal)
110     {
111         auto& iface = *std::any_cast<std::shared_ptr<T>&>(holder);
112         for (const auto& p : props)
113         {
114             iface.setPropertyByName(
115                 p.first,
116                 convertVariant<typename T::PropertiesVariant>(p.second),
117                 deferSignal);
118         }
119     }
120 };
121 
122 template <typename T, typename Ops, typename Enable = void>
123 struct 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 
132 template <typename T, typename Ops>
133 struct 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 
143 template <typename T, typename Ops, typename Enable = void>
144 struct 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 
152 template <typename T, typename Ops>
153 struct 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 
163 struct DummyInterface
164 {};
165 using MakeInterfaceType =
166     std::add_pointer_t<decltype(MakeInterface<DummyInterface>::op)>;
167 using AssignInterfaceType =
168     std::add_pointer_t<decltype(AssignInterface<DummyInterface>::op)>;
169 template <typename Ops>
170 using SerializeInterfaceType =
171     std::add_pointer_t<decltype(SerializeInterface<DummyInterface, Ops>::op)>;
172 template <typename Ops>
173 using DeserializeInterfaceType =
174     std::add_pointer_t<decltype(DeserializeInterface<DummyInterface, Ops>::op)>;
175 using GetPropertyValueType =
176     std::add_pointer_t<decltype(GetPropertyValue<DummyInterface>::op)>;
177 
178 } // namespace manager
179 } // namespace inventory
180 } // namespace phosphor
181