1 #pragma once
2 
3 #include <nlohmann/json.hpp>
4 #include <sdbusplus/message/types.hpp>
5 
6 namespace utils
7 {
8 
9 inline void from_json(const nlohmann::json& j,
10                       sdbusplus::message::object_path& o)
11 {
12     o = j.get<std::string>();
13 }
14 
15 inline 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 
25 namespace detail
26 {
27 
28 template <class T>
29 struct 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 
45 template <class T>
46 constexpr bool has_utils_from_json_v = has_utils_from_json<T>::value;
47 
48 } // namespace detail
49 
50 template <class, class...>
51 struct LabeledTuple;
52 
53 template <class... Args, class... Labels>
54 struct 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
118