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