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