blob: 5d3be09c17f184280551f898dfe110ba5cc898f6 [file] [log] [blame]
Patrick Williams51103a42016-07-20 17:43:38 -05001#pragma once
2
3#include <tuple>
4#include <string>
5#include <vector>
Patrick Williamsbbe0e432016-09-10 08:57:03 -05006#include <map>
Patrick Williams75596782016-09-11 21:14:10 -05007#include <mapbox/variant.hpp>
Patrick Williams90b4f3c2016-09-09 13:54:56 -05008#include <systemd/sd-bus.h>
Patrick Williams51103a42016-07-20 17:43:38 -05009
Ed Tanous28dc36d2018-02-21 12:22:54 -080010#include <sdbusplus/utility/container_traits.hpp>
Patrick Williams51103a42016-07-20 17:43:38 -050011#include <sdbusplus/utility/type_traits.hpp>
Patrick Williams44982982017-01-06 16:02:37 -060012#include <sdbusplus/message/native_types.hpp>
Patrick Williams51103a42016-07-20 17:43:38 -050013
14namespace sdbusplus
15{
16
17namespace message
18{
19
Patrick Williams9fa85522017-02-01 23:06:33 -060020namespace variant_ns = mapbox::util;
21
Andrew Geissler072da3e2018-01-18 07:21:42 -080022template <typename... Args> using variant = variant_ns::variant<Args...>;
Patrick Williams75596782016-09-11 21:14:10 -050023
Patrick Williams51103a42016-07-20 17:43:38 -050024namespace types
25{
26
27/** @fn type_id()
28 * @brief Get a tuple containing the dbus type character(s) for a
29 * sequence of C++ types.
30 *
31 * @tparam ...Args - Types to get the type_id sequence for.
32 * @returns A tuple of characters representing the dbus types for ...Args.
33 *
34 * The design uses a tuple because a tuple can, at compile-time, be easily
35 * appended to, concatenated, and converted to an array (representing a
36 * C-string). There are other options to create a string of characters but
37 * they require runtime processing and memory allocation. By performing all
38 * options at compile-time the use of type-deduced dbus strings is equal to
39 * the cost of hard-coded type string constants.
40 */
Andrew Geissler072da3e2018-01-18 07:21:42 -080041template <typename... Args> constexpr auto type_id();
Patrick Williamsbbe0e432016-09-10 08:57:03 -050042/** @fn type_id_nonull()
43 * @brief A non-null-terminated version of type_id.
44 *
45 * This is useful when type-ids may need to be concatenated.
46 */
Andrew Geissler072da3e2018-01-18 07:21:42 -080047template <typename... Args> constexpr auto type_id_nonull();
Patrick Williams51103a42016-07-20 17:43:38 -050048
49namespace details
50{
51
Ed Tanous28dc36d2018-02-21 12:22:54 -080052/** @brief Downcast type submembers.
53 *
54 * This allows std::tuple and std::pair members to be downcast to their
55 * non-const, nonref versions of themselves to limit duplication in template
56 * specializations
57 *
58 * 1. Remove references.
59 * 2. Remove 'const' and 'volatile'.
60 * 3. Convert 'char[N]' to 'char*'.
61 */
62template <typename T> struct downcast_members
63{
64 using type = T;
65};
66template <typename... Args> struct downcast_members<std::pair<Args...>>
67{
68 using type = std::pair<utility::array_to_ptr_t<
69 char, std::remove_cv_t<std::remove_reference_t<Args>>>...>;
70};
71
72template <typename... Args> struct downcast_members<std::tuple<Args...>>
73{
74 using type = std::tuple<utility::array_to_ptr_t<
75 char, std::remove_cv_t<std::remove_reference_t<Args>>>...>;
76};
77
78template <typename T>
79using downcast_members_t = typename downcast_members<T>::type;
80
Patrick Williams930460c2016-07-20 17:52:55 -050081/** @brief Convert some C++ types to others for 'type_id' conversion purposes.
82 *
83 * Similar C++ types have the same dbus type-id, so 'downcast' those to limit
84 * duplication in type_id template specializations.
85 *
86 * 1. Remove references.
87 * 2. Remove 'const' and 'volatile'.
88 * 3. Convert 'char[N]' to 'char*'.
89 */
90template <typename T> struct type_id_downcast
91{
Ed Tanous28dc36d2018-02-21 12:22:54 -080092 using type = utility::array_to_ptr_t<
93 char, downcast_members_t<std::remove_cv_t<std::remove_reference_t<T>>>>;
Patrick Williams930460c2016-07-20 17:52:55 -050094};
95
Andrew Geissler072da3e2018-01-18 07:21:42 -080096template <typename T>
97using type_id_downcast_t = typename type_id_downcast<T>::type;
Patrick Williams930460c2016-07-20 17:52:55 -050098
Patrick Williams51103a42016-07-20 17:43:38 -050099/** @struct undefined_type_id
100 * @brief Special type indicating no dbus-type_id is defined for a C++ type.
101 */
102struct undefined_type_id
103{
104 /** An empty tuple indicating no type-characters. */
105 // We want this to be tuple so that we can use operations like
106 // tuple_cat on it without cascading compile failures. There is a
107 // static_assert in type_id_single to ensure this is never used, but to
108 // keep the compile failures as clean as possible.
109 static constexpr auto value = std::make_tuple();
110};
111
112/** @struct tuple_type_id
113 * @brief Special type indicating a tuple of dbus-type_id's.
114 *
115 * @tparam C1 - The first dbus type character character.
116 * @tparam ...C - The remaining sequence of dbus type characters.
117 *
118 * A tuple_type_id must be one or more characters. The C1 template param
119 * ensures at least one is present.
120 */
121template <char C1, char... C> struct tuple_type_id
122{
123
Andrew Geissler072da3e2018-01-18 07:21:42 -0800124/* This version check is required because a fix for auto is in 5.2+.
125 * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66421
126 */
127/** A tuple containing the type-characters. */
Patrick Williams51103a42016-07-20 17:43:38 -0500128#if (__GNUC__ > 5) || (__GNUC__ == 5 && (__GNUC_MINOR__ >= 2))
129 static constexpr auto value = std::make_tuple(C1, C...);
130#else
131 static constexpr decltype(std::make_tuple(C1, C...)) value =
132 std::make_tuple(C1, C...);
133#endif
134};
135
136/** @fn type_id_single()
137 * @brief Get a tuple containing the dbus type character(s) for a C++ type.
138 *
139 * @tparam T - The type to get the dbus type character(s) for.
140 */
Brad Bishopf7c23072018-02-14 23:45:30 -0500141template <typename T> constexpr auto type_id_single();
Patrick Williams51103a42016-07-20 17:43:38 -0500142
143/** @fn type_id_multiple()
144 * @brief Get a tuple containing the dbus type characters for a sequence of
145 * C++ types.
146 *
147 * @tparam T - The first type to get the dbus type character(s) for.
148 * @tparam ...Args - The remaining types.
149 */
Andrew Geissler072da3e2018-01-18 07:21:42 -0800150template <typename T, typename... Args> constexpr auto type_id_multiple();
Patrick Williams51103a42016-07-20 17:43:38 -0500151
152/** @struct type_id
153 * @brief Defined dbus type tuple for a C++ type.
154 *
155 * @tparam T - C++ type.
156 *
157 * Struct must have a 'value' tuple containing the dbus type. The default
Patrick Williamsc8235ce2016-09-11 21:17:07 -0500158 * value is an empty tuple, which is used to indicate an unsupported type.
Patrick Williams51103a42016-07-20 17:43:38 -0500159 */
Ed Tanous28dc36d2018-02-21 12:22:54 -0800160template <typename T, typename Enable = void>
161struct type_id : public undefined_type_id
Andrew Geissler072da3e2018-01-18 07:21:42 -0800162{
163};
164// Specializations for built-in types.
165template <> struct type_id<bool> : tuple_type_id<SD_BUS_TYPE_BOOLEAN>
166{
167};
168template <> struct type_id<uint8_t> : tuple_type_id<SD_BUS_TYPE_BYTE>
169{
170};
Patrick Williams51103a42016-07-20 17:43:38 -0500171// int8_t isn't supported by dbus.
Andrew Geissler072da3e2018-01-18 07:21:42 -0800172template <> struct type_id<uint16_t> : tuple_type_id<SD_BUS_TYPE_UINT16>
173{
174};
175template <> struct type_id<int16_t> : tuple_type_id<SD_BUS_TYPE_INT16>
176{
177};
178template <> struct type_id<uint32_t> : tuple_type_id<SD_BUS_TYPE_UINT32>
179{
180};
181template <> struct type_id<int32_t> : tuple_type_id<SD_BUS_TYPE_INT32>
182{
183};
184template <> struct type_id<uint64_t> : tuple_type_id<SD_BUS_TYPE_UINT64>
185{
186};
187template <> struct type_id<int64_t> : tuple_type_id<SD_BUS_TYPE_INT64>
188{
189};
Patrick Williams51103a42016-07-20 17:43:38 -0500190// float isn't supported by dbus.
Andrew Geissler072da3e2018-01-18 07:21:42 -0800191template <> struct type_id<double> : tuple_type_id<SD_BUS_TYPE_DOUBLE>
192{
193};
194template <> struct type_id<const char*> : tuple_type_id<SD_BUS_TYPE_STRING>
195{
196};
197template <> struct type_id<char*> : tuple_type_id<SD_BUS_TYPE_STRING>
198{
199};
200template <> struct type_id<std::string> : tuple_type_id<SD_BUS_TYPE_STRING>
201{
202};
203template <> struct type_id<object_path> : tuple_type_id<SD_BUS_TYPE_OBJECT_PATH>
204{
205};
206template <> struct type_id<signature> : tuple_type_id<SD_BUS_TYPE_SIGNATURE>
207{
208};
Patrick Williams51103a42016-07-20 17:43:38 -0500209
Ed Tanous28dc36d2018-02-21 12:22:54 -0800210template <typename T>
211struct type_id<T, std::enable_if_t<utility::has_const_iterator<T>::value>>
212 : std::false_type
Patrick Williams930460c2016-07-20 17:52:55 -0500213{
Ed Tanous28dc36d2018-02-21 12:22:54 -0800214 static constexpr auto value = std::tuple_cat(
215 tuple_type_id<SD_BUS_TYPE_ARRAY>::value,
216 type_id<type_id_downcast_t<typename T::value_type>>::value);
Patrick Williams930460c2016-07-20 17:52:55 -0500217};
218
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500219template <typename T1, typename T2> struct type_id<std::pair<T1, T2>>
220{
Andrew Geissler072da3e2018-01-18 07:21:42 -0800221 static constexpr auto value =
222 std::tuple_cat(tuple_type_id<SD_BUS_TYPE_DICT_ENTRY_BEGIN>::value,
223 type_id<type_id_downcast_t<T1>>::value,
224 type_id<type_id_downcast_t<T2>>::value,
225 tuple_type_id<SD_BUS_TYPE_DICT_ENTRY_END>::value);
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500226};
227
Andrew Geissler072da3e2018-01-18 07:21:42 -0800228template <typename... Args> struct type_id<std::tuple<Args...>>
Patrick Williamsaa2f48a2016-09-10 14:23:34 -0500229{
Andrew Geissler072da3e2018-01-18 07:21:42 -0800230 static constexpr auto value =
231 std::tuple_cat(tuple_type_id<SD_BUS_TYPE_STRUCT_BEGIN>::value,
232 type_id<type_id_downcast_t<Args>>::value...,
233 tuple_type_id<SD_BUS_TYPE_STRUCT_END>::value);
Patrick Williamsaa2f48a2016-09-10 14:23:34 -0500234};
235
Andrew Geissler072da3e2018-01-18 07:21:42 -0800236template <typename... Args>
237struct type_id<variant<Args...>> : tuple_type_id<SD_BUS_TYPE_VARIANT>
238{
239};
Patrick Williams75596782016-09-11 21:14:10 -0500240
Brad Bishopf7c23072018-02-14 23:45:30 -0500241template <typename T> constexpr auto type_id_single()
Patrick Williams51103a42016-07-20 17:43:38 -0500242{
243 static_assert(!std::is_base_of<undefined_type_id, type_id<T>>::value,
Andrew Geissler072da3e2018-01-18 07:21:42 -0800244 "No dbus type conversion provided for type.");
Patrick Williams51103a42016-07-20 17:43:38 -0500245 return type_id<T>::value;
246}
247
Andrew Geissler072da3e2018-01-18 07:21:42 -0800248template <typename T, typename... Args> constexpr auto type_id_multiple()
Patrick Williams51103a42016-07-20 17:43:38 -0500249{
Andrew Geissler072da3e2018-01-18 07:21:42 -0800250 return std::tuple_cat(type_id_single<T>(), type_id_single<Args>()...);
Patrick Williams51103a42016-07-20 17:43:38 -0500251}
252
Patrick Williams51103a42016-07-20 17:43:38 -0500253} // namespace details
254
Andrew Geissler072da3e2018-01-18 07:21:42 -0800255template <typename... Args> constexpr auto type_id()
Patrick Williams51103a42016-07-20 17:43:38 -0500256{
257 return std::tuple_cat(
258 details::type_id_multiple<details::type_id_downcast_t<Args>...>(),
Andrew Geissler072da3e2018-01-18 07:21:42 -0800259 std::make_tuple('\0') /* null terminator for C-string */);
Patrick Williams51103a42016-07-20 17:43:38 -0500260}
261
Andrew Geissler072da3e2018-01-18 07:21:42 -0800262template <typename... Args> constexpr auto type_id_nonull()
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500263{
264 return details::type_id_multiple<details::type_id_downcast_t<Args>...>();
265}
266
Patrick Williams51103a42016-07-20 17:43:38 -0500267} // namespace types
268
269} // namespace message
270
271} // namespace sdbusplus