#pragma once #include #include namespace utils { inline void from_json(const nlohmann::json& j, sdbusplus::message::object_path& o) { o = j.get(); } inline void from_json(const nlohmann::json& j, std::vector& o) { o.clear(); for (const nlohmann::json& item : j) { o.emplace_back(item.get()); } } namespace detail { template struct has_utils_from_json { template static U& ref(); template static std::true_type check( decltype(utils::from_json(ref(), ref()))*); template static std::false_type check(...); static constexpr bool value = decltype(check>(nullptr))::value; }; template constexpr bool has_utils_from_json_v = has_utils_from_json::value; } // namespace detail template struct LabeledTuple; template struct LabeledTuple, Labels...> { static_assert(sizeof...(Args) == sizeof...(Labels)); using tuple_type = std::tuple; LabeledTuple() = default; LabeledTuple(const LabeledTuple&) = default; LabeledTuple(LabeledTuple&&) = default; LabeledTuple(tuple_type v) : value(std::move(v)) {} LabeledTuple(Args... args) : value(std::move(args)...) {} LabeledTuple& operator=(const LabeledTuple&) = default; LabeledTuple& operator=(LabeledTuple&&) = default; nlohmann::json to_json() const { nlohmann::json j; to_json_all(j, std::make_index_sequence()); return j; } void from_json(const nlohmann::json& j) { from_json_all(j, std::make_index_sequence()); } template const auto& at_index() const { return std::get(value); } template auto& at_index() { return std::get(value); } template const auto& at_label() const { return find_item<0, Label>(*this); } template auto& at_label() { return find_item<0, Label>(*this); } bool operator==(const LabeledTuple& other) const { return value == other.value; } bool operator<(const LabeledTuple& other) const { return value < other.value; } private: template void to_json_all(nlohmann::json& j, std::index_sequence) const { (to_json_item(j), ...); } template void to_json_item(nlohmann::json& j) const { using Label = std::tuple_element_t>; j[Label::str()] = std::get(value); } template void from_json_all(const nlohmann::json& j, std::index_sequence) { (from_json_item(j), ...); } template void from_json_item(const nlohmann::json& j) { using Label = std::tuple_element_t>; using T = std::tuple_element_t; const nlohmann::json& item = j.at(Label::str()); if constexpr (detail::has_utils_from_json_v) { T& v = std::get(value); utils::from_json(item, v); } else { std::get(value) = item.get(); } } template static auto& find_item(Self& self) { if constexpr (std::is_same_v>>) { return std::get(self.value); } else { return find_item(self); } } tuple_type value; }; template inline void to_json(nlohmann::json& json, const LabeledTuple, Labels...>& tuple) { json = tuple.to_json(); } template inline void from_json(const nlohmann::json& json, LabeledTuple, Labels...>& tuple) { tuple.from_json(json); } } // namespace utils