blob: e6203dd3caff15a9254a21a024be5f0b718dd674 [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{
Wludzik, Jozefe2362792020-10-27 17:23:55 +010056 static_assert(sizeof...(Args) == sizeof...(Labels));
57
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000058 using tuple_type = std::tuple<Args...>;
59
60 LabeledTuple() = default;
61 LabeledTuple(const LabeledTuple&) = default;
62 LabeledTuple(LabeledTuple&&) = default;
63
Krzysztof Grobelnyfbeb5bf2022-01-03 09:41:29 +010064 explicit LabeledTuple(tuple_type v) : value(std::move(v))
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000065 {}
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
Wludzik, Jozefe2362792020-10-27 17:23:55 +010073 {
74 nlohmann::json j;
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000075 to_json_all(j, std::make_index_sequence<sizeof...(Args)>());
Wludzik, Jozefe2362792020-10-27 17:23:55 +010076 return j;
77 }
78
Krzysztof Grobelny493e62e2022-02-14 10:55:50 +010079 const tuple_type& to_tuple() const
80 {
81 return value;
82 }
83
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000084 void from_json(const nlohmann::json& j)
Wludzik, Jozefe2362792020-10-27 17:23:55 +010085 {
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000086 from_json_all(j, std::make_index_sequence<sizeof...(Args)>());
87 }
88
Szymon Dompke3a617022021-07-19 18:23:02 +020089 std::string dump() const
90 {
91 return to_json().dump();
92 }
93
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000094 template <size_t Idx>
95 const auto& at_index() const
96 {
97 return std::get<Idx>(value);
98 }
99
100 template <size_t Idx>
101 auto& at_index()
102 {
103 return std::get<Idx>(value);
104 }
105
106 template <class Label>
107 const auto& at_label() const
108 {
109 return find_item<0, Label>(*this);
110 }
111
112 template <class Label>
113 auto& at_label()
114 {
115 return find_item<0, Label>(*this);
116 }
117
118 bool operator==(const LabeledTuple& other) const
119 {
120 return value == other.value;
121 }
122
123 bool operator<(const LabeledTuple& other) const
124 {
125 return value < other.value;
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100126 }
127
128 private:
129 template <size_t... Idx>
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000130 void to_json_all(nlohmann::json& j, std::index_sequence<Idx...>) const
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100131 {
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000132 (to_json_item<Idx>(j), ...);
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100133 }
134
135 template <size_t Idx>
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000136 void to_json_item(nlohmann::json& j) const
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100137 {
138 using Label = std::tuple_element_t<Idx, std::tuple<Labels...>>;
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000139 j[Label::str()] = std::get<Idx>(value);
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100140 }
141
142 template <size_t... Idx>
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000143 void from_json_all(const nlohmann::json& j, std::index_sequence<Idx...>)
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100144 {
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000145 (from_json_item<Idx>(j), ...);
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100146 }
147
148 template <size_t Idx>
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000149 void from_json_item(const nlohmann::json& j)
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100150 {
151 using Label = std::tuple_element_t<Idx, std::tuple<Labels...>>;
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000152 using T = std::tuple_element_t<Idx, tuple_type>;
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100153 const nlohmann::json& item = j.at(Label::str());
154 if constexpr (detail::has_utils_from_json_v<T>)
155 {
156 T& v = std::get<Idx>(value);
157 utils::from_json(item, v);
158 }
159 else
160 {
161 std::get<Idx>(value) = item.get<T>();
162 }
163 }
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000164
165 template <size_t Idx, class Label, class Self>
166 static auto& find_item(Self& self)
167 {
168 if constexpr (std::is_same_v<Label, std::tuple_element_t<
169 Idx, std::tuple<Labels...>>>)
170 {
171 return std::get<Idx>(self.value);
172 }
173 else
174 {
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100175 static_assert(Idx + 1 < sizeof...(Args),
176 "Label not found in LabeledTuple");
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000177 return find_item<Idx + 1, Label>(self);
178 }
179 }
180
181 tuple_type value;
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100182};
183
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000184template <class... Args, class... Labels>
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000185inline void to_json(nlohmann::json& json,
186 const LabeledTuple<std::tuple<Args...>, Labels...>& tuple)
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000187{
188 json = tuple.to_json();
189}
190
191template <class... Args, class... Labels>
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000192inline void from_json(const nlohmann::json& json,
193 LabeledTuple<std::tuple<Args...>, Labels...>& tuple)
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000194{
195 tuple.from_json(json);
196}
197
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100198} // namespace utils