blob: 6a30dd698ffc80b09f07d49186bac376878bcee5 [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
10#include <sdbusplus/utility/type_traits.hpp>
Patrick Williams44982982017-01-06 16:02:37 -060011#include <sdbusplus/message/native_types.hpp>
Patrick Williams51103a42016-07-20 17:43:38 -050012
13namespace sdbusplus
14{
15
16namespace message
17{
18
Patrick Williams9fa85522017-02-01 23:06:33 -060019namespace variant_ns = mapbox::util;
20
Andrew Geissler072da3e2018-01-18 07:21:42 -080021template <typename... Args> using variant = variant_ns::variant<Args...>;
Patrick Williams75596782016-09-11 21:14:10 -050022
Patrick Williams51103a42016-07-20 17:43:38 -050023namespace types
24{
25
26/** @fn type_id()
27 * @brief Get a tuple containing the dbus type character(s) for a
28 * sequence of C++ types.
29 *
30 * @tparam ...Args - Types to get the type_id sequence for.
31 * @returns A tuple of characters representing the dbus types for ...Args.
32 *
33 * The design uses a tuple because a tuple can, at compile-time, be easily
34 * appended to, concatenated, and converted to an array (representing a
35 * C-string). There are other options to create a string of characters but
36 * they require runtime processing and memory allocation. By performing all
37 * options at compile-time the use of type-deduced dbus strings is equal to
38 * the cost of hard-coded type string constants.
39 */
Andrew Geissler072da3e2018-01-18 07:21:42 -080040template <typename... Args> constexpr auto type_id();
Patrick Williamsbbe0e432016-09-10 08:57:03 -050041/** @fn type_id_nonull()
42 * @brief A non-null-terminated version of type_id.
43 *
44 * This is useful when type-ids may need to be concatenated.
45 */
Andrew Geissler072da3e2018-01-18 07:21:42 -080046template <typename... Args> constexpr auto type_id_nonull();
Patrick Williams51103a42016-07-20 17:43:38 -050047
48namespace details
49{
50
Patrick Williams930460c2016-07-20 17:52:55 -050051/** @brief Convert some C++ types to others for 'type_id' conversion purposes.
52 *
53 * Similar C++ types have the same dbus type-id, so 'downcast' those to limit
54 * duplication in type_id template specializations.
55 *
56 * 1. Remove references.
57 * 2. Remove 'const' and 'volatile'.
58 * 3. Convert 'char[N]' to 'char*'.
59 */
60template <typename T> struct type_id_downcast
61{
62 using type = typename utility::array_to_ptr_t<
Andrew Geissler072da3e2018-01-18 07:21:42 -080063 char, std::remove_cv_t<std::remove_reference_t<T>>>;
Patrick Williams930460c2016-07-20 17:52:55 -050064};
65
Andrew Geissler072da3e2018-01-18 07:21:42 -080066template <typename T>
67using type_id_downcast_t = typename type_id_downcast<T>::type;
Patrick Williams930460c2016-07-20 17:52:55 -050068
Patrick Williams51103a42016-07-20 17:43:38 -050069/** @struct undefined_type_id
70 * @brief Special type indicating no dbus-type_id is defined for a C++ type.
71 */
72struct undefined_type_id
73{
74 /** An empty tuple indicating no type-characters. */
75 // We want this to be tuple so that we can use operations like
76 // tuple_cat on it without cascading compile failures. There is a
77 // static_assert in type_id_single to ensure this is never used, but to
78 // keep the compile failures as clean as possible.
79 static constexpr auto value = std::make_tuple();
80};
81
82/** @struct tuple_type_id
83 * @brief Special type indicating a tuple of dbus-type_id's.
84 *
85 * @tparam C1 - The first dbus type character character.
86 * @tparam ...C - The remaining sequence of dbus type characters.
87 *
88 * A tuple_type_id must be one or more characters. The C1 template param
89 * ensures at least one is present.
90 */
91template <char C1, char... C> struct tuple_type_id
92{
93
Andrew Geissler072da3e2018-01-18 07:21:42 -080094/* This version check is required because a fix for auto is in 5.2+.
95 * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66421
96 */
97/** A tuple containing the type-characters. */
Patrick Williams51103a42016-07-20 17:43:38 -050098#if (__GNUC__ > 5) || (__GNUC__ == 5 && (__GNUC_MINOR__ >= 2))
99 static constexpr auto value = std::make_tuple(C1, C...);
100#else
101 static constexpr decltype(std::make_tuple(C1, C...)) value =
102 std::make_tuple(C1, C...);
103#endif
104};
105
106/** @fn type_id_single()
107 * @brief Get a tuple containing the dbus type character(s) for a C++ type.
108 *
109 * @tparam T - The type to get the dbus type character(s) for.
110 */
Brad Bishopf7c23072018-02-14 23:45:30 -0500111template <typename T> constexpr auto type_id_single();
Patrick Williams51103a42016-07-20 17:43:38 -0500112
113/** @fn type_id_multiple()
114 * @brief Get a tuple containing the dbus type characters for a sequence of
115 * C++ types.
116 *
117 * @tparam T - The first type to get the dbus type character(s) for.
118 * @tparam ...Args - The remaining types.
119 */
Andrew Geissler072da3e2018-01-18 07:21:42 -0800120template <typename T, typename... Args> constexpr auto type_id_multiple();
Patrick Williams51103a42016-07-20 17:43:38 -0500121
122/** @struct type_id
123 * @brief Defined dbus type tuple for a C++ type.
124 *
125 * @tparam T - C++ type.
126 *
127 * Struct must have a 'value' tuple containing the dbus type. The default
Patrick Williamsc8235ce2016-09-11 21:17:07 -0500128 * value is an empty tuple, which is used to indicate an unsupported type.
Patrick Williams51103a42016-07-20 17:43:38 -0500129 */
Andrew Geissler072da3e2018-01-18 07:21:42 -0800130template <typename T> struct type_id : public undefined_type_id
131{
132};
133// Specializations for built-in types.
134template <> struct type_id<bool> : tuple_type_id<SD_BUS_TYPE_BOOLEAN>
135{
136};
137template <> struct type_id<uint8_t> : tuple_type_id<SD_BUS_TYPE_BYTE>
138{
139};
Patrick Williams51103a42016-07-20 17:43:38 -0500140// int8_t isn't supported by dbus.
Andrew Geissler072da3e2018-01-18 07:21:42 -0800141template <> struct type_id<uint16_t> : tuple_type_id<SD_BUS_TYPE_UINT16>
142{
143};
144template <> struct type_id<int16_t> : tuple_type_id<SD_BUS_TYPE_INT16>
145{
146};
147template <> struct type_id<uint32_t> : tuple_type_id<SD_BUS_TYPE_UINT32>
148{
149};
150template <> struct type_id<int32_t> : tuple_type_id<SD_BUS_TYPE_INT32>
151{
152};
153template <> struct type_id<uint64_t> : tuple_type_id<SD_BUS_TYPE_UINT64>
154{
155};
156template <> struct type_id<int64_t> : tuple_type_id<SD_BUS_TYPE_INT64>
157{
158};
Patrick Williams51103a42016-07-20 17:43:38 -0500159// float isn't supported by dbus.
Andrew Geissler072da3e2018-01-18 07:21:42 -0800160template <> struct type_id<double> : tuple_type_id<SD_BUS_TYPE_DOUBLE>
161{
162};
163template <> struct type_id<const char*> : tuple_type_id<SD_BUS_TYPE_STRING>
164{
165};
166template <> struct type_id<char*> : tuple_type_id<SD_BUS_TYPE_STRING>
167{
168};
169template <> struct type_id<std::string> : tuple_type_id<SD_BUS_TYPE_STRING>
170{
171};
172template <> struct type_id<object_path> : tuple_type_id<SD_BUS_TYPE_OBJECT_PATH>
173{
174};
175template <> struct type_id<signature> : tuple_type_id<SD_BUS_TYPE_SIGNATURE>
176{
177};
Patrick Williams51103a42016-07-20 17:43:38 -0500178
Patrick Williams930460c2016-07-20 17:52:55 -0500179template <typename T> struct type_id<std::vector<T>>
180{
Andrew Geissler072da3e2018-01-18 07:21:42 -0800181 static constexpr auto value =
182 std::tuple_cat(tuple_type_id<SD_BUS_TYPE_ARRAY>::value,
183 type_id<type_id_downcast_t<T>>::value);
Patrick Williams930460c2016-07-20 17:52:55 -0500184};
185
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500186template <typename T1, typename T2> struct type_id<std::pair<T1, T2>>
187{
Andrew Geissler072da3e2018-01-18 07:21:42 -0800188 static constexpr auto value =
189 std::tuple_cat(tuple_type_id<SD_BUS_TYPE_DICT_ENTRY_BEGIN>::value,
190 type_id<type_id_downcast_t<T1>>::value,
191 type_id<type_id_downcast_t<T2>>::value,
192 tuple_type_id<SD_BUS_TYPE_DICT_ENTRY_END>::value);
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500193};
194
195template <typename T1, typename T2> struct type_id<std::map<T1, T2>>
196{
Andrew Geissler072da3e2018-01-18 07:21:42 -0800197 static constexpr auto value =
198 std::tuple_cat(tuple_type_id<SD_BUS_TYPE_ARRAY>::value,
199 type_id<typename std::map<T1, T2>::value_type>::value);
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500200};
201
Andrew Geissler072da3e2018-01-18 07:21:42 -0800202template <typename... Args> struct type_id<std::tuple<Args...>>
Patrick Williamsaa2f48a2016-09-10 14:23:34 -0500203{
Andrew Geissler072da3e2018-01-18 07:21:42 -0800204 static constexpr auto value =
205 std::tuple_cat(tuple_type_id<SD_BUS_TYPE_STRUCT_BEGIN>::value,
206 type_id<type_id_downcast_t<Args>>::value...,
207 tuple_type_id<SD_BUS_TYPE_STRUCT_END>::value);
Patrick Williamsaa2f48a2016-09-10 14:23:34 -0500208};
209
Andrew Geissler072da3e2018-01-18 07:21:42 -0800210template <typename... Args>
211struct type_id<variant<Args...>> : tuple_type_id<SD_BUS_TYPE_VARIANT>
212{
213};
Patrick Williams75596782016-09-11 21:14:10 -0500214
Brad Bishopf7c23072018-02-14 23:45:30 -0500215template <typename T> constexpr auto type_id_single()
Patrick Williams51103a42016-07-20 17:43:38 -0500216{
217 static_assert(!std::is_base_of<undefined_type_id, type_id<T>>::value,
Andrew Geissler072da3e2018-01-18 07:21:42 -0800218 "No dbus type conversion provided for type.");
Patrick Williams51103a42016-07-20 17:43:38 -0500219 return type_id<T>::value;
220}
221
Andrew Geissler072da3e2018-01-18 07:21:42 -0800222template <typename T, typename... Args> constexpr auto type_id_multiple()
Patrick Williams51103a42016-07-20 17:43:38 -0500223{
Andrew Geissler072da3e2018-01-18 07:21:42 -0800224 return std::tuple_cat(type_id_single<T>(), type_id_single<Args>()...);
Patrick Williams51103a42016-07-20 17:43:38 -0500225}
226
Patrick Williams51103a42016-07-20 17:43:38 -0500227} // namespace details
228
Andrew Geissler072da3e2018-01-18 07:21:42 -0800229template <typename... Args> constexpr auto type_id()
Patrick Williams51103a42016-07-20 17:43:38 -0500230{
231 return std::tuple_cat(
232 details::type_id_multiple<details::type_id_downcast_t<Args>...>(),
Andrew Geissler072da3e2018-01-18 07:21:42 -0800233 std::make_tuple('\0') /* null terminator for C-string */);
Patrick Williams51103a42016-07-20 17:43:38 -0500234}
235
Andrew Geissler072da3e2018-01-18 07:21:42 -0800236template <typename... Args> constexpr auto type_id_nonull()
Patrick Williamsbbe0e432016-09-10 08:57:03 -0500237{
238 return details::type_id_multiple<details::type_id_downcast_t<Args>...>();
239}
240
Patrick Williams51103a42016-07-20 17:43:38 -0500241} // namespace types
242
243} // namespace message
244
245} // namespace sdbusplus