1 #pragma once 2 3 #include <nlohmann/json.hpp> 4 #include <sdbusplus/message/types.hpp> 5 6 namespace utils 7 { 8 9 inline void from_json(const nlohmann::json& j, 10 sdbusplus::message::object_path& o) 11 { 12 o = j.get<std::string>(); 13 } 14 15 inline void from_json(const nlohmann::json& j, 16 std::vector<sdbusplus::message::object_path>& o) 17 { 18 o.clear(); 19 for (const nlohmann::json& item : j) 20 { 21 o.emplace_back(item.get<std::string>()); 22 } 23 } 24 25 namespace detail 26 { 27 28 template <class T> 29 struct has_utils_from_json 30 { 31 template <class U> 32 static U& ref(); 33 34 template <class U> 35 static std::true_type check( 36 decltype(utils::from_json(ref<const nlohmann::json>(), ref<U>()))*); 37 38 template <class> 39 static std::false_type check(...); 40 41 static constexpr bool value = 42 decltype(check<std::decay_t<T>>(nullptr))::value; 43 }; 44 45 template <class T> 46 constexpr bool has_utils_from_json_v = has_utils_from_json<T>::value; 47 48 } // namespace detail 49 50 template <class, class...> 51 struct LabeledTuple; 52 53 template <class... Args, class... Labels> 54 struct LabeledTuple<std::tuple<Args...>, Labels...> 55 { 56 static_assert(sizeof...(Args) == sizeof...(Labels)); 57 58 using tuple_type = std::tuple<Args...>; 59 60 LabeledTuple() = default; 61 LabeledTuple(const LabeledTuple&) = default; 62 LabeledTuple(LabeledTuple&&) = default; 63 64 LabeledTuple(tuple_type v) : value(std::move(v)) 65 {} 66 LabeledTuple(Args... args) : value(std::move(args)...) 67 {} 68 69 LabeledTuple& operator=(const LabeledTuple&) = default; 70 LabeledTuple& operator=(LabeledTuple&&) = default; 71 72 nlohmann::json to_json() const 73 { 74 nlohmann::json j; 75 to_json_all(j, std::make_index_sequence<sizeof...(Args)>()); 76 return j; 77 } 78 79 void from_json(const nlohmann::json& j) 80 { 81 from_json_all(j, std::make_index_sequence<sizeof...(Args)>()); 82 } 83 84 template <size_t Idx> 85 const auto& at_index() const 86 { 87 return std::get<Idx>(value); 88 } 89 90 template <size_t Idx> 91 auto& at_index() 92 { 93 return std::get<Idx>(value); 94 } 95 96 template <class Label> 97 const auto& at_label() const 98 { 99 return find_item<0, Label>(*this); 100 } 101 102 template <class Label> 103 auto& at_label() 104 { 105 return find_item<0, Label>(*this); 106 } 107 108 bool operator==(const LabeledTuple& other) const 109 { 110 return value == other.value; 111 } 112 113 bool operator<(const LabeledTuple& other) const 114 { 115 return value < other.value; 116 } 117 118 private: 119 template <size_t... Idx> 120 void to_json_all(nlohmann::json& j, std::index_sequence<Idx...>) const 121 { 122 (to_json_item<Idx>(j), ...); 123 } 124 125 template <size_t Idx> 126 void to_json_item(nlohmann::json& j) const 127 { 128 using Label = std::tuple_element_t<Idx, std::tuple<Labels...>>; 129 j[Label::str()] = std::get<Idx>(value); 130 } 131 132 template <size_t... Idx> 133 void from_json_all(const nlohmann::json& j, std::index_sequence<Idx...>) 134 { 135 (from_json_item<Idx>(j), ...); 136 } 137 138 template <size_t Idx> 139 void from_json_item(const nlohmann::json& j) 140 { 141 using Label = std::tuple_element_t<Idx, std::tuple<Labels...>>; 142 using T = std::tuple_element_t<Idx, tuple_type>; 143 const nlohmann::json& item = j.at(Label::str()); 144 if constexpr (detail::has_utils_from_json_v<T>) 145 { 146 T& v = std::get<Idx>(value); 147 utils::from_json(item, v); 148 } 149 else 150 { 151 std::get<Idx>(value) = item.get<T>(); 152 } 153 } 154 155 template <size_t Idx, class Label, class Self> 156 static auto& find_item(Self& self) 157 { 158 if constexpr (std::is_same_v<Label, std::tuple_element_t< 159 Idx, std::tuple<Labels...>>>) 160 { 161 return std::get<Idx>(self.value); 162 } 163 else 164 { 165 return find_item<Idx + 1, Label>(self); 166 } 167 } 168 169 tuple_type value; 170 }; 171 172 template <class... Args, class... Labels> 173 void to_json(nlohmann::json& json, 174 const LabeledTuple<std::tuple<Args...>, Labels...>& tuple) 175 { 176 json = tuple.to_json(); 177 } 178 179 template <class... Args, class... Labels> 180 void from_json(const nlohmann::json& json, 181 LabeledTuple<std::tuple<Args...>, Labels...>& tuple) 182 { 183 tuple.from_json(json); 184 } 185 186 } // namespace utils 187