blob: 7e7532200bd1a35234faa463394e9f04724a8594 [file] [log] [blame]
Wludzik, Jozefe2362792020-10-27 17:23:55 +01001#pragma once
2
3#include <nlohmann/json.hpp>
4#include <sdbusplus/message/types.hpp>
5
6namespace utils
7{
8
9inline void from_json(const nlohmann::json& j,
10 sdbusplus::message::object_path& o)
11{
12 o = j.get<std::string>();
13}
14
15inline 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
25namespace detail
26{
27
28template <class T>
29struct 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
45template <class T>
46constexpr bool has_utils_from_json_v = has_utils_from_json<T>::value;
47
48} // namespace detail
49
50template <class, class...>
51struct LabeledTuple;
52
53template <class... Args, class... Labels>
54struct LabeledTuple<std::tuple<Args...>, Labels...>
55{
56 LabeledTuple() = delete;
57
58 static_assert(sizeof...(Args) == sizeof...(Labels));
59
60 static nlohmann::json to_json(const std::tuple<Args...>& tuple)
61 {
62 nlohmann::json j;
63 to_json_all(j, tuple, std::make_index_sequence<sizeof...(Args)>());
64 return j;
65 }
66
67 static std::tuple<Args...> from_json(const nlohmann::json& j)
68 {
69 std::tuple<Args...> value;
70 from_json_all(j, value, std::make_index_sequence<sizeof...(Args)>());
71 return value;
72 }
73
74 private:
75 template <size_t... Idx>
76 static void to_json_all(nlohmann::json& j, const std::tuple<Args...>& tuple,
77 std::index_sequence<Idx...>)
78 {
79 (to_json_item<Idx>(j, tuple), ...);
80 }
81
82 template <size_t Idx>
83 static void to_json_item(nlohmann::json& j,
84 const std::tuple<Args...>& tuple)
85 {
86 using Label = std::tuple_element_t<Idx, std::tuple<Labels...>>;
87 j[Label::str()] = std::get<Idx>(tuple);
88 }
89
90 template <size_t... Idx>
91 static void from_json_all(const nlohmann::json& j,
92 std::tuple<Args...>& value,
93 std::index_sequence<Idx...>)
94 {
95 (from_json_item<Idx>(j, value), ...);
96 }
97
98 template <size_t Idx>
99 static void from_json_item(const nlohmann::json& j,
100 std::tuple<Args...>& value)
101 {
102 using Label = std::tuple_element_t<Idx, std::tuple<Labels...>>;
103 using T = std::tuple_element_t<Idx, std::tuple<Args...>>;
104 const nlohmann::json& item = j.at(Label::str());
105 if constexpr (detail::has_utils_from_json_v<T>)
106 {
107 T& v = std::get<Idx>(value);
108 utils::from_json(item, v);
109 }
110 else
111 {
112 std::get<Idx>(value) = item.get<T>();
113 }
114 }
115};
116
117} // namespace utils