1*e2362796SWludzik, Jozef #pragma once
2*e2362796SWludzik, Jozef 
3*e2362796SWludzik, Jozef #include <nlohmann/json.hpp>
4*e2362796SWludzik, Jozef #include <sdbusplus/message/types.hpp>
5*e2362796SWludzik, Jozef 
6*e2362796SWludzik, Jozef namespace utils
7*e2362796SWludzik, Jozef {
8*e2362796SWludzik, Jozef 
9*e2362796SWludzik, Jozef inline void from_json(const nlohmann::json& j,
10*e2362796SWludzik, Jozef                       sdbusplus::message::object_path& o)
11*e2362796SWludzik, Jozef {
12*e2362796SWludzik, Jozef     o = j.get<std::string>();
13*e2362796SWludzik, Jozef }
14*e2362796SWludzik, Jozef 
15*e2362796SWludzik, Jozef inline void from_json(const nlohmann::json& j,
16*e2362796SWludzik, Jozef                       std::vector<sdbusplus::message::object_path>& o)
17*e2362796SWludzik, Jozef {
18*e2362796SWludzik, Jozef     o.clear();
19*e2362796SWludzik, Jozef     for (const nlohmann::json& item : j)
20*e2362796SWludzik, Jozef     {
21*e2362796SWludzik, Jozef         o.emplace_back(item.get<std::string>());
22*e2362796SWludzik, Jozef     }
23*e2362796SWludzik, Jozef }
24*e2362796SWludzik, Jozef 
25*e2362796SWludzik, Jozef namespace detail
26*e2362796SWludzik, Jozef {
27*e2362796SWludzik, Jozef 
28*e2362796SWludzik, Jozef template <class T>
29*e2362796SWludzik, Jozef struct has_utils_from_json
30*e2362796SWludzik, Jozef {
31*e2362796SWludzik, Jozef     template <class U>
32*e2362796SWludzik, Jozef     static U& ref();
33*e2362796SWludzik, Jozef 
34*e2362796SWludzik, Jozef     template <class U>
35*e2362796SWludzik, Jozef     static std::true_type check(
36*e2362796SWludzik, Jozef         decltype(utils::from_json(ref<const nlohmann::json>(), ref<U>()))*);
37*e2362796SWludzik, Jozef 
38*e2362796SWludzik, Jozef     template <class>
39*e2362796SWludzik, Jozef     static std::false_type check(...);
40*e2362796SWludzik, Jozef 
41*e2362796SWludzik, Jozef     static constexpr bool value =
42*e2362796SWludzik, Jozef         decltype(check<std::decay_t<T>>(nullptr))::value;
43*e2362796SWludzik, Jozef };
44*e2362796SWludzik, Jozef 
45*e2362796SWludzik, Jozef template <class T>
46*e2362796SWludzik, Jozef constexpr bool has_utils_from_json_v = has_utils_from_json<T>::value;
47*e2362796SWludzik, Jozef 
48*e2362796SWludzik, Jozef } // namespace detail
49*e2362796SWludzik, Jozef 
50*e2362796SWludzik, Jozef template <class, class...>
51*e2362796SWludzik, Jozef struct LabeledTuple;
52*e2362796SWludzik, Jozef 
53*e2362796SWludzik, Jozef template <class... Args, class... Labels>
54*e2362796SWludzik, Jozef struct LabeledTuple<std::tuple<Args...>, Labels...>
55*e2362796SWludzik, Jozef {
56*e2362796SWludzik, Jozef     LabeledTuple() = delete;
57*e2362796SWludzik, Jozef 
58*e2362796SWludzik, Jozef     static_assert(sizeof...(Args) == sizeof...(Labels));
59*e2362796SWludzik, Jozef 
60*e2362796SWludzik, Jozef     static nlohmann::json to_json(const std::tuple<Args...>& tuple)
61*e2362796SWludzik, Jozef     {
62*e2362796SWludzik, Jozef         nlohmann::json j;
63*e2362796SWludzik, Jozef         to_json_all(j, tuple, std::make_index_sequence<sizeof...(Args)>());
64*e2362796SWludzik, Jozef         return j;
65*e2362796SWludzik, Jozef     }
66*e2362796SWludzik, Jozef 
67*e2362796SWludzik, Jozef     static std::tuple<Args...> from_json(const nlohmann::json& j)
68*e2362796SWludzik, Jozef     {
69*e2362796SWludzik, Jozef         std::tuple<Args...> value;
70*e2362796SWludzik, Jozef         from_json_all(j, value, std::make_index_sequence<sizeof...(Args)>());
71*e2362796SWludzik, Jozef         return value;
72*e2362796SWludzik, Jozef     }
73*e2362796SWludzik, Jozef 
74*e2362796SWludzik, Jozef   private:
75*e2362796SWludzik, Jozef     template <size_t... Idx>
76*e2362796SWludzik, Jozef     static void to_json_all(nlohmann::json& j, const std::tuple<Args...>& tuple,
77*e2362796SWludzik, Jozef                             std::index_sequence<Idx...>)
78*e2362796SWludzik, Jozef     {
79*e2362796SWludzik, Jozef         (to_json_item<Idx>(j, tuple), ...);
80*e2362796SWludzik, Jozef     }
81*e2362796SWludzik, Jozef 
82*e2362796SWludzik, Jozef     template <size_t Idx>
83*e2362796SWludzik, Jozef     static void to_json_item(nlohmann::json& j,
84*e2362796SWludzik, Jozef                              const std::tuple<Args...>& tuple)
85*e2362796SWludzik, Jozef     {
86*e2362796SWludzik, Jozef         using Label = std::tuple_element_t<Idx, std::tuple<Labels...>>;
87*e2362796SWludzik, Jozef         j[Label::str()] = std::get<Idx>(tuple);
88*e2362796SWludzik, Jozef     }
89*e2362796SWludzik, Jozef 
90*e2362796SWludzik, Jozef     template <size_t... Idx>
91*e2362796SWludzik, Jozef     static void from_json_all(const nlohmann::json& j,
92*e2362796SWludzik, Jozef                               std::tuple<Args...>& value,
93*e2362796SWludzik, Jozef                               std::index_sequence<Idx...>)
94*e2362796SWludzik, Jozef     {
95*e2362796SWludzik, Jozef         (from_json_item<Idx>(j, value), ...);
96*e2362796SWludzik, Jozef     }
97*e2362796SWludzik, Jozef 
98*e2362796SWludzik, Jozef     template <size_t Idx>
99*e2362796SWludzik, Jozef     static void from_json_item(const nlohmann::json& j,
100*e2362796SWludzik, Jozef                                std::tuple<Args...>& value)
101*e2362796SWludzik, Jozef     {
102*e2362796SWludzik, Jozef         using Label = std::tuple_element_t<Idx, std::tuple<Labels...>>;
103*e2362796SWludzik, Jozef         using T = std::tuple_element_t<Idx, std::tuple<Args...>>;
104*e2362796SWludzik, Jozef         const nlohmann::json& item = j.at(Label::str());
105*e2362796SWludzik, Jozef         if constexpr (detail::has_utils_from_json_v<T>)
106*e2362796SWludzik, Jozef         {
107*e2362796SWludzik, Jozef             T& v = std::get<Idx>(value);
108*e2362796SWludzik, Jozef             utils::from_json(item, v);
109*e2362796SWludzik, Jozef         }
110*e2362796SWludzik, Jozef         else
111*e2362796SWludzik, Jozef         {
112*e2362796SWludzik, Jozef             std::get<Idx>(value) = item.get<T>();
113*e2362796SWludzik, Jozef         }
114*e2362796SWludzik, Jozef     }
115*e2362796SWludzik, Jozef };
116*e2362796SWludzik, Jozef 
117*e2362796SWludzik, Jozef } // namespace utils
118