xref: /aosp_15_r20/external/libbrillo/brillo/dbus/data_serialization.h (revision 1a96fba65179ea7d3f56207137718607415c5953)
1*1a96fba6SXin Li // Copyright 2014 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li 
5*1a96fba6SXin Li #ifndef LIBBRILLO_BRILLO_DBUS_DATA_SERIALIZATION_H_
6*1a96fba6SXin Li #define LIBBRILLO_BRILLO_DBUS_DATA_SERIALIZATION_H_
7*1a96fba6SXin Li 
8*1a96fba6SXin Li // The main functionality provided by this header file is methods to serialize
9*1a96fba6SXin Li // native C++ data over D-Bus. This includes three major parts:
10*1a96fba6SXin Li // - Methods to get the D-Bus signature for a given C++ type:
11*1a96fba6SXin Li //     std::string GetDBusSignature<T>();
12*1a96fba6SXin Li // - Methods to write arbitrary C++ data to D-Bus MessageWriter:
13*1a96fba6SXin Li //     void AppendValueToWriter(dbus::MessageWriter* writer, const T& value);
14*1a96fba6SXin Li //     void AppendValueToWriterAsVariant(dbus::MessageWriter*, const T&);
15*1a96fba6SXin Li // - Methods to read arbitrary C++ data from D-Bus MessageReader:
16*1a96fba6SXin Li //     bool PopValueFromReader(dbus::MessageReader* reader, T* value);
17*1a96fba6SXin Li //     bool PopVariantValueFromReader(dbus::MessageReader* reader, T* value);
18*1a96fba6SXin Li //
19*1a96fba6SXin Li // There are a number of overloads to handle C++ equivalents of basic D-Bus
20*1a96fba6SXin Li // types:
21*1a96fba6SXin Li //   D-Bus Type  | D-Bus Signature | Native C++ type
22*1a96fba6SXin Li //  --------------------------------------------------
23*1a96fba6SXin Li //   BYTE        |        y        |  uint8_t
24*1a96fba6SXin Li //   BOOL        |        b        |  bool
25*1a96fba6SXin Li //   INT16       |        n        |  int16_t
26*1a96fba6SXin Li //   UINT16      |        q        |  uint16_t
27*1a96fba6SXin Li //   INT32       |        i        |  int32_t (int)
28*1a96fba6SXin Li //   UINT32      |        u        |  uint32_t (unsigned)
29*1a96fba6SXin Li //   INT64       |        x        |  int64_t
30*1a96fba6SXin Li //   UINT64      |        t        |  uint64_t
31*1a96fba6SXin Li //   DOUBLE      |        d        |  double
32*1a96fba6SXin Li //   STRING      |        s        |  std::string
33*1a96fba6SXin Li //   OBJECT_PATH |        o        |  dbus::ObjectPath
34*1a96fba6SXin Li //   ARRAY       |        aT       |  std::vector<T>
35*1a96fba6SXin Li //   STRUCT      |       (UV)      |  std::pair<U,V>
36*1a96fba6SXin Li //               |     (UVW...)    |  std::tuple<U,V,W,...>
37*1a96fba6SXin Li //   DICT        |       a{KV}     |  std::map<K,V>
38*1a96fba6SXin Li //   VARIANT     |        v        |  brillo::Any
39*1a96fba6SXin Li //   UNIX_FD     |        h        |  brillo::dbus_utils::FileDescriptor (write)
40*1a96fba6SXin Li //               |                 |  base::ScopedFD (read)
41*1a96fba6SXin Li //   SIGNATURE   |        g        |  (unsupported)
42*1a96fba6SXin Li //
43*1a96fba6SXin Li // Additional overloads/specialization can be provided for custom types.
44*1a96fba6SXin Li // In order to do that, provide overloads of AppendValueToWriter() and
45*1a96fba6SXin Li // PopValueFromReader() functions in brillo::dbus_utils namespace for the
46*1a96fba6SXin Li // CustomType. As well as a template specialization of DBusType<> for the same
47*1a96fba6SXin Li // CustomType. This specialization must provide three static functions:
48*1a96fba6SXin Li //  - static std::string GetSignature();
49*1a96fba6SXin Li //  - static void Write(dbus::MessageWriter* writer, const CustomType& value);
50*1a96fba6SXin Li //  - static bool Read(dbus::MessageReader* reader, CustomType* value);
51*1a96fba6SXin Li // See an example in DBusUtils.CustomStruct unit test in
52*1a96fba6SXin Li // brillo/dbus/data_serialization_test.cc.
53*1a96fba6SXin Li 
54*1a96fba6SXin Li #include <map>
55*1a96fba6SXin Li #include <memory>
56*1a96fba6SXin Li #include <string>
57*1a96fba6SXin Li #include <tuple>
58*1a96fba6SXin Li #include <utility>
59*1a96fba6SXin Li #include <vector>
60*1a96fba6SXin Li 
61*1a96fba6SXin Li #include <base/files/scoped_file.h>
62*1a96fba6SXin Li #include <base/logging.h>
63*1a96fba6SXin Li #include <base/files/scoped_file.h>
64*1a96fba6SXin Li #include <brillo/brillo_export.h>
65*1a96fba6SXin Li #include <brillo/dbus/file_descriptor.h>
66*1a96fba6SXin Li #include <brillo/type_name_undecorate.h>
67*1a96fba6SXin Li #include <dbus/message.h>
68*1a96fba6SXin Li 
69*1a96fba6SXin Li namespace google {
70*1a96fba6SXin Li namespace protobuf {
71*1a96fba6SXin Li class MessageLite;
72*1a96fba6SXin Li }  // namespace protobuf
73*1a96fba6SXin Li }  // namespace google
74*1a96fba6SXin Li 
75*1a96fba6SXin Li namespace brillo {
76*1a96fba6SXin Li 
77*1a96fba6SXin Li // Forward-declare only. Can't include any.h right now because it needs
78*1a96fba6SXin Li // AppendValueToWriter() declared below.
79*1a96fba6SXin Li class Any;
80*1a96fba6SXin Li 
81*1a96fba6SXin Li namespace dbus_utils {
82*1a96fba6SXin Li 
83*1a96fba6SXin Li // Base class for DBusType<T> for T not supported by D-Bus. This used to
84*1a96fba6SXin Li // implement IsTypeSupported<> below.
85*1a96fba6SXin Li struct Unsupported {};
86*1a96fba6SXin Li 
87*1a96fba6SXin Li // Generic definition of DBusType<T> which will be specialized for particular
88*1a96fba6SXin Li // types later.
89*1a96fba6SXin Li // The second template parameter is used only in SFINAE situations to resolve
90*1a96fba6SXin Li // class hierarchy chains for protobuf-derived classes. This type is defaulted
91*1a96fba6SXin Li // to be 'void' in all other cases and simply ignored.
92*1a96fba6SXin Li // See DBusType specialization for google::protobuf::MessageLite below for more
93*1a96fba6SXin Li // detailed information.
94*1a96fba6SXin Li template<typename T, typename = void>
95*1a96fba6SXin Li struct DBusType : public Unsupported {};
96*1a96fba6SXin Li 
97*1a96fba6SXin Li // A helper type trait to determine if all of the types listed in Types... are
98*1a96fba6SXin Li // supported by D-Bus. This is a generic forward-declaration which will be
99*1a96fba6SXin Li // specialized for different type combinations.
100*1a96fba6SXin Li template<typename... Types>
101*1a96fba6SXin Li struct IsTypeSupported;
102*1a96fba6SXin Li 
103*1a96fba6SXin Li // Both T and the Types... must be supported for the complete set to be
104*1a96fba6SXin Li // supported.
105*1a96fba6SXin Li template<typename T, typename... Types>
106*1a96fba6SXin Li struct IsTypeSupported<T, Types...>
107*1a96fba6SXin Li     : public std::integral_constant<
108*1a96fba6SXin Li           bool,
109*1a96fba6SXin Li           IsTypeSupported<T>::value && IsTypeSupported<Types...>::value> {};
110*1a96fba6SXin Li 
111*1a96fba6SXin Li // For a single type T, check if DBusType<T> derives from Unsupported.
112*1a96fba6SXin Li // If it does, then the type is not supported by the D-Bus.
113*1a96fba6SXin Li template<typename T>
114*1a96fba6SXin Li struct IsTypeSupported<T>
115*1a96fba6SXin Li     : public std::integral_constant<
116*1a96fba6SXin Li           bool,
117*1a96fba6SXin Li           !std::is_base_of<Unsupported, DBusType<T>>::value> {};
118*1a96fba6SXin Li 
119*1a96fba6SXin Li // Empty set is not supported.
120*1a96fba6SXin Li template<>
121*1a96fba6SXin Li struct IsTypeSupported<> : public std::false_type {};
122*1a96fba6SXin Li 
123*1a96fba6SXin Li //----------------------------------------------------------------------------
124*1a96fba6SXin Li // AppendValueToWriter<T>(dbus::MessageWriter* writer, const T& value)
125*1a96fba6SXin Li // Write the |value| of type T to D-Bus message.
126*1a96fba6SXin Li // Explicitly delete the overloads for scalar types that are not supported by
127*1a96fba6SXin Li // D-Bus.
128*1a96fba6SXin Li void AppendValueToWriter(::dbus::MessageWriter* writer, char value) = delete;
129*1a96fba6SXin Li void AppendValueToWriter(::dbus::MessageWriter* writer, float value) = delete;
130*1a96fba6SXin Li 
131*1a96fba6SXin Li //----------------------------------------------------------------------------
132*1a96fba6SXin Li // PopValueFromReader<T>(dbus::MessageWriter* writer, T* value)
133*1a96fba6SXin Li // Reads the |value| of type T from D-Bus message.
134*1a96fba6SXin Li // Explicitly delete the overloads for scalar types that are not supported by
135*1a96fba6SXin Li // D-Bus.
136*1a96fba6SXin Li void PopValueFromReader(::dbus::MessageReader* reader, char* value) = delete;
137*1a96fba6SXin Li void PopValueFromReader(::dbus::MessageReader* reader, float* value) = delete;
138*1a96fba6SXin Li 
139*1a96fba6SXin Li //----------------------------------------------------------------------------
140*1a96fba6SXin Li // Get D-Bus data signature from C++ data types.
141*1a96fba6SXin Li // Specializations of a generic GetDBusSignature<T>() provide signature strings
142*1a96fba6SXin Li // for native C++ types. This function is available only for type supported
143*1a96fba6SXin Li // by D-Bus.
144*1a96fba6SXin Li template<typename T>
145*1a96fba6SXin Li inline typename std::enable_if<IsTypeSupported<T>::value, std::string>::type
146*1a96fba6SXin Li GetDBusSignature() {
147*1a96fba6SXin Li   return DBusType<T>::GetSignature();
148*1a96fba6SXin Li }
149*1a96fba6SXin Li 
150*1a96fba6SXin Li namespace details {
151*1a96fba6SXin Li // Helper method used by the many overloads of PopValueFromReader().
152*1a96fba6SXin Li // If the current value in the reader is of Variant type, the method descends
153*1a96fba6SXin Li // into the Variant and updates the |*reader_ref| with the transient
154*1a96fba6SXin Li // |variant_reader| MessageReader instance passed in.
155*1a96fba6SXin Li // Returns false if it fails to descend into the Variant.
156*1a96fba6SXin Li inline bool DescendIntoVariantIfPresent(::dbus::MessageReader** reader_ref,
157*1a96fba6SXin Li                                         ::dbus::MessageReader* variant_reader) {
158*1a96fba6SXin Li   if ((*reader_ref)->GetDataType() != ::dbus::Message::VARIANT)
159*1a96fba6SXin Li     return true;
160*1a96fba6SXin Li   if (!(*reader_ref)->PopVariant(variant_reader))
161*1a96fba6SXin Li     return false;
162*1a96fba6SXin Li   *reader_ref = variant_reader;
163*1a96fba6SXin Li   return true;
164*1a96fba6SXin Li }
165*1a96fba6SXin Li 
166*1a96fba6SXin Li // Helper method to format the type string of an array.
167*1a96fba6SXin Li // Essentially it adds "a" in front of |element_signature|.
168*1a96fba6SXin Li inline std::string GetArrayDBusSignature(const std::string& element_signature) {
169*1a96fba6SXin Li   return DBUS_TYPE_ARRAY_AS_STRING + element_signature;
170*1a96fba6SXin Li }
171*1a96fba6SXin Li 
172*1a96fba6SXin Li // Helper method to get a signature string for DICT_ENTRY.
173*1a96fba6SXin Li // Returns "{KV}", where "K" and "V" are the type signatures for types
174*1a96fba6SXin Li // KEY/VALUE. For example, GetDBusDictEntryType<std::string, int>() would return
175*1a96fba6SXin Li // "{si}".
176*1a96fba6SXin Li template<typename KEY, typename VALUE>
177*1a96fba6SXin Li inline std::string GetDBusDictEntryType() {
178*1a96fba6SXin Li   return DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING +
179*1a96fba6SXin Li          GetDBusSignature<KEY>() + GetDBusSignature<VALUE>() +
180*1a96fba6SXin Li          DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
181*1a96fba6SXin Li }
182*1a96fba6SXin Li 
183*1a96fba6SXin Li }  // namespace details
184*1a96fba6SXin Li 
185*1a96fba6SXin Li //=============================================================================
186*1a96fba6SXin Li // Specializations/overloads for AppendValueToWriter, PopValueFromReader and
187*1a96fba6SXin Li // DBusType<T> for various C++ types that can be serialized over D-Bus.
188*1a96fba6SXin Li 
189*1a96fba6SXin Li // bool -----------------------------------------------------------------------
190*1a96fba6SXin Li BRILLO_EXPORT void AppendValueToWriter(::dbus::MessageWriter* writer,
191*1a96fba6SXin Li                                        bool value);
192*1a96fba6SXin Li BRILLO_EXPORT bool PopValueFromReader(::dbus::MessageReader* reader,
193*1a96fba6SXin Li                                       bool* value);
194*1a96fba6SXin Li 
195*1a96fba6SXin Li template<>
196*1a96fba6SXin Li struct DBusType<bool> {
197*1a96fba6SXin Li   inline static std::string GetSignature() {
198*1a96fba6SXin Li     return DBUS_TYPE_BOOLEAN_AS_STRING;
199*1a96fba6SXin Li   }
200*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer, bool value) {
201*1a96fba6SXin Li     AppendValueToWriter(writer, value);
202*1a96fba6SXin Li   }
203*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader, bool* value) {
204*1a96fba6SXin Li     return PopValueFromReader(reader, value);
205*1a96fba6SXin Li   }
206*1a96fba6SXin Li };
207*1a96fba6SXin Li 
208*1a96fba6SXin Li // uint8_t --------------------------------------------------------------------
209*1a96fba6SXin Li BRILLO_EXPORT void AppendValueToWriter(::dbus::MessageWriter* writer,
210*1a96fba6SXin Li                                        uint8_t value);
211*1a96fba6SXin Li BRILLO_EXPORT bool PopValueFromReader(::dbus::MessageReader* reader,
212*1a96fba6SXin Li                                       uint8_t* value);
213*1a96fba6SXin Li 
214*1a96fba6SXin Li template<>
215*1a96fba6SXin Li struct DBusType<uint8_t> {
216*1a96fba6SXin Li   inline static std::string GetSignature() { return DBUS_TYPE_BYTE_AS_STRING; }
217*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer, uint8_t value) {
218*1a96fba6SXin Li     AppendValueToWriter(writer, value);
219*1a96fba6SXin Li   }
220*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader, uint8_t* value) {
221*1a96fba6SXin Li     return PopValueFromReader(reader, value);
222*1a96fba6SXin Li   }
223*1a96fba6SXin Li };
224*1a96fba6SXin Li 
225*1a96fba6SXin Li // int16_t --------------------------------------------------------------------
226*1a96fba6SXin Li BRILLO_EXPORT void AppendValueToWriter(::dbus::MessageWriter* writer,
227*1a96fba6SXin Li                                        int16_t value);
228*1a96fba6SXin Li BRILLO_EXPORT bool PopValueFromReader(::dbus::MessageReader* reader,
229*1a96fba6SXin Li                                       int16_t* value);
230*1a96fba6SXin Li 
231*1a96fba6SXin Li template<>
232*1a96fba6SXin Li struct DBusType<int16_t> {
233*1a96fba6SXin Li   inline static std::string GetSignature() { return DBUS_TYPE_INT16_AS_STRING; }
234*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer, int16_t value) {
235*1a96fba6SXin Li     AppendValueToWriter(writer, value);
236*1a96fba6SXin Li   }
237*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader, int16_t* value) {
238*1a96fba6SXin Li     return PopValueFromReader(reader, value);
239*1a96fba6SXin Li   }
240*1a96fba6SXin Li };
241*1a96fba6SXin Li 
242*1a96fba6SXin Li // uint16_t -------------------------------------------------------------------
243*1a96fba6SXin Li BRILLO_EXPORT void AppendValueToWriter(::dbus::MessageWriter* writer,
244*1a96fba6SXin Li                                        uint16_t value);
245*1a96fba6SXin Li BRILLO_EXPORT bool PopValueFromReader(::dbus::MessageReader* reader,
246*1a96fba6SXin Li                                       uint16_t* value);
247*1a96fba6SXin Li 
248*1a96fba6SXin Li template<>
249*1a96fba6SXin Li struct DBusType<uint16_t> {
250*1a96fba6SXin Li   inline static std::string GetSignature() {
251*1a96fba6SXin Li     return DBUS_TYPE_UINT16_AS_STRING;
252*1a96fba6SXin Li   }
253*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer, uint16_t value) {
254*1a96fba6SXin Li     AppendValueToWriter(writer, value);
255*1a96fba6SXin Li   }
256*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader, uint16_t* value) {
257*1a96fba6SXin Li     return PopValueFromReader(reader, value);
258*1a96fba6SXin Li   }
259*1a96fba6SXin Li };
260*1a96fba6SXin Li 
261*1a96fba6SXin Li // int32_t --------------------------------------------------------------------
262*1a96fba6SXin Li BRILLO_EXPORT void AppendValueToWriter(::dbus::MessageWriter* writer,
263*1a96fba6SXin Li                                        int32_t value);
264*1a96fba6SXin Li BRILLO_EXPORT bool PopValueFromReader(::dbus::MessageReader* reader,
265*1a96fba6SXin Li                                       int32_t* value);
266*1a96fba6SXin Li 
267*1a96fba6SXin Li template<>
268*1a96fba6SXin Li struct DBusType<int32_t> {
269*1a96fba6SXin Li   inline static std::string GetSignature() { return DBUS_TYPE_INT32_AS_STRING; }
270*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer, int32_t value) {
271*1a96fba6SXin Li     AppendValueToWriter(writer, value);
272*1a96fba6SXin Li   }
273*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader, int32_t* value) {
274*1a96fba6SXin Li     return PopValueFromReader(reader, value);
275*1a96fba6SXin Li   }
276*1a96fba6SXin Li };
277*1a96fba6SXin Li 
278*1a96fba6SXin Li // uint32_t -------------------------------------------------------------------
279*1a96fba6SXin Li BRILLO_EXPORT void AppendValueToWriter(::dbus::MessageWriter* writer,
280*1a96fba6SXin Li                                        uint32_t value);
281*1a96fba6SXin Li BRILLO_EXPORT bool PopValueFromReader(::dbus::MessageReader* reader,
282*1a96fba6SXin Li                                       uint32_t* value);
283*1a96fba6SXin Li 
284*1a96fba6SXin Li template<>
285*1a96fba6SXin Li struct DBusType<uint32_t> {
286*1a96fba6SXin Li   inline static std::string GetSignature() {
287*1a96fba6SXin Li     return DBUS_TYPE_UINT32_AS_STRING;
288*1a96fba6SXin Li   }
289*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer, uint32_t value) {
290*1a96fba6SXin Li     AppendValueToWriter(writer, value);
291*1a96fba6SXin Li   }
292*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader, uint32_t* value) {
293*1a96fba6SXin Li     return PopValueFromReader(reader, value);
294*1a96fba6SXin Li   }
295*1a96fba6SXin Li };
296*1a96fba6SXin Li 
297*1a96fba6SXin Li // int64_t --------------------------------------------------------------------
298*1a96fba6SXin Li BRILLO_EXPORT void AppendValueToWriter(::dbus::MessageWriter* writer,
299*1a96fba6SXin Li                                        int64_t value);
300*1a96fba6SXin Li BRILLO_EXPORT bool PopValueFromReader(::dbus::MessageReader* reader,
301*1a96fba6SXin Li                                       int64_t* value);
302*1a96fba6SXin Li 
303*1a96fba6SXin Li template<>
304*1a96fba6SXin Li struct DBusType<int64_t> {
305*1a96fba6SXin Li   inline static std::string GetSignature() { return DBUS_TYPE_INT64_AS_STRING; }
306*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer, int64_t value) {
307*1a96fba6SXin Li     AppendValueToWriter(writer, value);
308*1a96fba6SXin Li   }
309*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader, int64_t* value) {
310*1a96fba6SXin Li     return PopValueFromReader(reader, value);
311*1a96fba6SXin Li   }
312*1a96fba6SXin Li };
313*1a96fba6SXin Li 
314*1a96fba6SXin Li // uint64_t -------------------------------------------------------------------
315*1a96fba6SXin Li BRILLO_EXPORT void AppendValueToWriter(::dbus::MessageWriter* writer,
316*1a96fba6SXin Li                                        uint64_t value);
317*1a96fba6SXin Li BRILLO_EXPORT bool PopValueFromReader(::dbus::MessageReader* reader,
318*1a96fba6SXin Li                                       uint64_t* value);
319*1a96fba6SXin Li 
320*1a96fba6SXin Li template<>
321*1a96fba6SXin Li struct DBusType<uint64_t> {
322*1a96fba6SXin Li   inline static std::string GetSignature() {
323*1a96fba6SXin Li     return DBUS_TYPE_UINT64_AS_STRING;
324*1a96fba6SXin Li   }
325*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer, uint64_t value) {
326*1a96fba6SXin Li     AppendValueToWriter(writer, value);
327*1a96fba6SXin Li   }
328*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader, uint64_t* value) {
329*1a96fba6SXin Li     return PopValueFromReader(reader, value);
330*1a96fba6SXin Li   }
331*1a96fba6SXin Li };
332*1a96fba6SXin Li 
333*1a96fba6SXin Li // double ---------------------------------------------------------------------
334*1a96fba6SXin Li BRILLO_EXPORT void AppendValueToWriter(::dbus::MessageWriter* writer,
335*1a96fba6SXin Li                                        double value);
336*1a96fba6SXin Li BRILLO_EXPORT bool PopValueFromReader(::dbus::MessageReader* reader,
337*1a96fba6SXin Li                                       double* value);
338*1a96fba6SXin Li 
339*1a96fba6SXin Li template<>
340*1a96fba6SXin Li struct DBusType<double> {
341*1a96fba6SXin Li   inline static std::string GetSignature() {
342*1a96fba6SXin Li     return DBUS_TYPE_DOUBLE_AS_STRING;
343*1a96fba6SXin Li   }
344*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer, double value) {
345*1a96fba6SXin Li     AppendValueToWriter(writer, value);
346*1a96fba6SXin Li   }
347*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader, double* value) {
348*1a96fba6SXin Li     return PopValueFromReader(reader, value);
349*1a96fba6SXin Li   }
350*1a96fba6SXin Li };
351*1a96fba6SXin Li 
352*1a96fba6SXin Li // std::string ----------------------------------------------------------------
353*1a96fba6SXin Li BRILLO_EXPORT void AppendValueToWriter(::dbus::MessageWriter* writer,
354*1a96fba6SXin Li                                        const std::string& value);
355*1a96fba6SXin Li BRILLO_EXPORT bool PopValueFromReader(::dbus::MessageReader* reader,
356*1a96fba6SXin Li                                       std::string* value);
357*1a96fba6SXin Li 
358*1a96fba6SXin Li template<>
359*1a96fba6SXin Li struct DBusType<std::string> {
360*1a96fba6SXin Li   inline static std::string GetSignature() {
361*1a96fba6SXin Li     return DBUS_TYPE_STRING_AS_STRING;
362*1a96fba6SXin Li   }
363*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer,
364*1a96fba6SXin Li                            const std::string& value) {
365*1a96fba6SXin Li     AppendValueToWriter(writer, value);
366*1a96fba6SXin Li   }
367*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader, std::string* value) {
368*1a96fba6SXin Li     return PopValueFromReader(reader, value);
369*1a96fba6SXin Li   }
370*1a96fba6SXin Li };
371*1a96fba6SXin Li 
372*1a96fba6SXin Li // const char*
373*1a96fba6SXin Li BRILLO_EXPORT void AppendValueToWriter(::dbus::MessageWriter* writer,
374*1a96fba6SXin Li                                        const char* value);
375*1a96fba6SXin Li 
376*1a96fba6SXin Li template<>
377*1a96fba6SXin Li struct DBusType<const char*> {
378*1a96fba6SXin Li   inline static std::string GetSignature() {
379*1a96fba6SXin Li     return DBUS_TYPE_STRING_AS_STRING;
380*1a96fba6SXin Li   }
381*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer, const char* value) {
382*1a96fba6SXin Li     AppendValueToWriter(writer, value);
383*1a96fba6SXin Li   }
384*1a96fba6SXin Li };
385*1a96fba6SXin Li 
386*1a96fba6SXin Li // const char[]
387*1a96fba6SXin Li template<>
388*1a96fba6SXin Li struct DBusType<const char[]> {
389*1a96fba6SXin Li   inline static std::string GetSignature() {
390*1a96fba6SXin Li     return DBUS_TYPE_STRING_AS_STRING;
391*1a96fba6SXin Li   }
392*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer, const char* value) {
393*1a96fba6SXin Li     AppendValueToWriter(writer, value);
394*1a96fba6SXin Li   }
395*1a96fba6SXin Li };
396*1a96fba6SXin Li 
397*1a96fba6SXin Li // dbus::ObjectPath -----------------------------------------------------------
398*1a96fba6SXin Li BRILLO_EXPORT void AppendValueToWriter(::dbus::MessageWriter* writer,
399*1a96fba6SXin Li                                        const ::dbus::ObjectPath& value);
400*1a96fba6SXin Li BRILLO_EXPORT bool PopValueFromReader(::dbus::MessageReader* reader,
401*1a96fba6SXin Li                                       ::dbus::ObjectPath* value);
402*1a96fba6SXin Li 
403*1a96fba6SXin Li template <>
404*1a96fba6SXin Li struct DBusType<::dbus::ObjectPath> {
405*1a96fba6SXin Li   inline static std::string GetSignature() {
406*1a96fba6SXin Li     return DBUS_TYPE_OBJECT_PATH_AS_STRING;
407*1a96fba6SXin Li   }
408*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer,
409*1a96fba6SXin Li                            const ::dbus::ObjectPath& value) {
410*1a96fba6SXin Li     AppendValueToWriter(writer, value);
411*1a96fba6SXin Li   }
412*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader,
413*1a96fba6SXin Li                           ::dbus::ObjectPath* value) {
414*1a96fba6SXin Li     return PopValueFromReader(reader, value);
415*1a96fba6SXin Li   }
416*1a96fba6SXin Li };
417*1a96fba6SXin Li 
418*1a96fba6SXin Li // brillo::dbus_utils::FileDescriptor/base::ScopedFD --------------------------
419*1a96fba6SXin Li BRILLO_EXPORT void AppendValueToWriter(::dbus::MessageWriter* writer,
420*1a96fba6SXin Li                                        const FileDescriptor& value);
421*1a96fba6SXin Li BRILLO_EXPORT bool PopValueFromReader(::dbus::MessageReader* reader,
422*1a96fba6SXin Li                                       base::ScopedFD* value);
423*1a96fba6SXin Li 
424*1a96fba6SXin Li template<>
425*1a96fba6SXin Li struct DBusType<FileDescriptor> {
426*1a96fba6SXin Li   inline static std::string GetSignature() {
427*1a96fba6SXin Li     return DBUS_TYPE_UNIX_FD_AS_STRING;
428*1a96fba6SXin Li   }
429*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer,
430*1a96fba6SXin Li                            const FileDescriptor& value) {
431*1a96fba6SXin Li     AppendValueToWriter(writer, value);
432*1a96fba6SXin Li   }
433*1a96fba6SXin Li };
434*1a96fba6SXin Li 
435*1a96fba6SXin Li template<>
436*1a96fba6SXin Li struct DBusType<base::ScopedFD> {
437*1a96fba6SXin Li   inline static std::string GetSignature() {
438*1a96fba6SXin Li     return DBUS_TYPE_UNIX_FD_AS_STRING;
439*1a96fba6SXin Li   }
440*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader,
441*1a96fba6SXin Li                           base::ScopedFD* value) {
442*1a96fba6SXin Li     return PopValueFromReader(reader, value);
443*1a96fba6SXin Li   }
444*1a96fba6SXin Li };
445*1a96fba6SXin Li 
446*1a96fba6SXin Li // brillo::Any --------------------------------------------------------------
447*1a96fba6SXin Li BRILLO_EXPORT void AppendValueToWriter(::dbus::MessageWriter* writer,
448*1a96fba6SXin Li                                        const brillo::Any& value);
449*1a96fba6SXin Li BRILLO_EXPORT bool PopValueFromReader(::dbus::MessageReader* reader,
450*1a96fba6SXin Li                                       brillo::Any* value);
451*1a96fba6SXin Li 
452*1a96fba6SXin Li template<>
453*1a96fba6SXin Li struct DBusType<brillo::Any> {
454*1a96fba6SXin Li   inline static std::string GetSignature() {
455*1a96fba6SXin Li     return DBUS_TYPE_VARIANT_AS_STRING;
456*1a96fba6SXin Li   }
457*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer,
458*1a96fba6SXin Li                            const brillo::Any& value) {
459*1a96fba6SXin Li     AppendValueToWriter(writer, value);
460*1a96fba6SXin Li   }
461*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader, brillo::Any* value) {
462*1a96fba6SXin Li     return PopValueFromReader(reader, value);
463*1a96fba6SXin Li   }
464*1a96fba6SXin Li };
465*1a96fba6SXin Li 
466*1a96fba6SXin Li // std::vector = D-Bus ARRAY. -------------------------------------------------
467*1a96fba6SXin Li template <typename T, typename ALLOC>
468*1a96fba6SXin Li typename std::enable_if<IsTypeSupported<T>::value>::type AppendValueToWriter(
469*1a96fba6SXin Li     ::dbus::MessageWriter* writer, const std::vector<T, ALLOC>& value) {
470*1a96fba6SXin Li   ::dbus::MessageWriter array_writer(nullptr);
471*1a96fba6SXin Li   writer->OpenArray(GetDBusSignature<T>(), &array_writer);
472*1a96fba6SXin Li   for (const auto& element : value) {
473*1a96fba6SXin Li     // Use DBusType<T>::Write() instead of AppendValueToWriter() to delay
474*1a96fba6SXin Li     // binding to AppendValueToWriter() to the point of instantiation of this
475*1a96fba6SXin Li     // template.
476*1a96fba6SXin Li     DBusType<T>::Write(&array_writer, element);
477*1a96fba6SXin Li   }
478*1a96fba6SXin Li   writer->CloseContainer(&array_writer);
479*1a96fba6SXin Li }
480*1a96fba6SXin Li 
481*1a96fba6SXin Li template <typename T, typename ALLOC>
482*1a96fba6SXin Li typename std::enable_if<IsTypeSupported<T>::value, bool>::type
483*1a96fba6SXin Li PopValueFromReader(::dbus::MessageReader* reader,
484*1a96fba6SXin Li                    std::vector<T, ALLOC>* value) {
485*1a96fba6SXin Li   ::dbus::MessageReader variant_reader(nullptr);
486*1a96fba6SXin Li   ::dbus::MessageReader array_reader(nullptr);
487*1a96fba6SXin Li   if (!details::DescendIntoVariantIfPresent(&reader, &variant_reader) ||
488*1a96fba6SXin Li       !reader->PopArray(&array_reader))
489*1a96fba6SXin Li     return false;
490*1a96fba6SXin Li   value->clear();
491*1a96fba6SXin Li   while (array_reader.HasMoreData()) {
492*1a96fba6SXin Li     T data;
493*1a96fba6SXin Li     // Use DBusType<T>::Read() instead of PopValueFromReader() to delay
494*1a96fba6SXin Li     // binding to PopValueFromReader() to the point of instantiation of this
495*1a96fba6SXin Li     // template.
496*1a96fba6SXin Li     if (!DBusType<T>::Read(&array_reader, &data))
497*1a96fba6SXin Li       return false;
498*1a96fba6SXin Li     value->push_back(std::move(data));
499*1a96fba6SXin Li   }
500*1a96fba6SXin Li   return true;
501*1a96fba6SXin Li }
502*1a96fba6SXin Li 
503*1a96fba6SXin Li namespace details {
504*1a96fba6SXin Li // DBusArrayType<> is a helper base class for DBusType<vector<T>> that provides
505*1a96fba6SXin Li // GetSignature/Write/Read methods for T types that are supported by D-Bus
506*1a96fba6SXin Li // and not having those methods for types that are not supported by D-Bus.
507*1a96fba6SXin Li template<bool inner_type_supported, typename T, typename ALLOC>
508*1a96fba6SXin Li struct DBusArrayType {
509*1a96fba6SXin Li   // Returns "aT", where "T" is the signature string for type T.
510*1a96fba6SXin Li   inline static std::string GetSignature() {
511*1a96fba6SXin Li     return GetArrayDBusSignature(GetDBusSignature<T>());
512*1a96fba6SXin Li   }
513*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer,
514*1a96fba6SXin Li                            const std::vector<T, ALLOC>& value) {
515*1a96fba6SXin Li     AppendValueToWriter(writer, value);
516*1a96fba6SXin Li   }
517*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader,
518*1a96fba6SXin Li                           std::vector<T, ALLOC>* value) {
519*1a96fba6SXin Li     return PopValueFromReader(reader, value);
520*1a96fba6SXin Li   }
521*1a96fba6SXin Li };
522*1a96fba6SXin Li 
523*1a96fba6SXin Li // Explicit specialization for unsupported type T.
524*1a96fba6SXin Li template<typename T, typename ALLOC>
525*1a96fba6SXin Li struct DBusArrayType<false, T, ALLOC> : public Unsupported {};
526*1a96fba6SXin Li 
527*1a96fba6SXin Li }  // namespace details
528*1a96fba6SXin Li 
529*1a96fba6SXin Li template<typename T, typename ALLOC>
530*1a96fba6SXin Li struct DBusType<std::vector<T, ALLOC>>
531*1a96fba6SXin Li     : public details::DBusArrayType<IsTypeSupported<T>::value, T, ALLOC> {};
532*1a96fba6SXin Li 
533*1a96fba6SXin Li // std::pair = D-Bus STRUCT with two elements. --------------------------------
534*1a96fba6SXin Li namespace details {
535*1a96fba6SXin Li 
536*1a96fba6SXin Li // Helper class to get a D-Bus signature of a list of types.
537*1a96fba6SXin Li // For example, TupleTraits<int32_t, bool, std::string>::GetSignature() will
538*1a96fba6SXin Li // return "ibs".
539*1a96fba6SXin Li template<typename... Types>
540*1a96fba6SXin Li struct TupleTraits;
541*1a96fba6SXin Li 
542*1a96fba6SXin Li template<typename FirstType, typename... RestOfTypes>
543*1a96fba6SXin Li struct TupleTraits<FirstType, RestOfTypes...> {
544*1a96fba6SXin Li   static std::string GetSignature() {
545*1a96fba6SXin Li     return GetDBusSignature<FirstType>() +
546*1a96fba6SXin Li            TupleTraits<RestOfTypes...>::GetSignature();
547*1a96fba6SXin Li   }
548*1a96fba6SXin Li };
549*1a96fba6SXin Li 
550*1a96fba6SXin Li template<>
551*1a96fba6SXin Li struct TupleTraits<> {
552*1a96fba6SXin Li   static std::string GetSignature() { return std::string{}; }
553*1a96fba6SXin Li };
554*1a96fba6SXin Li 
555*1a96fba6SXin Li }  // namespace details
556*1a96fba6SXin Li 
557*1a96fba6SXin Li template<typename... Types>
558*1a96fba6SXin Li inline std::string GetStructDBusSignature() {
559*1a96fba6SXin Li   // Returns "(T...)", where "T..." is the signature strings for types T...
560*1a96fba6SXin Li   return DBUS_STRUCT_BEGIN_CHAR_AS_STRING +
561*1a96fba6SXin Li          details::TupleTraits<Types...>::GetSignature() +
562*1a96fba6SXin Li          DBUS_STRUCT_END_CHAR_AS_STRING;
563*1a96fba6SXin Li }
564*1a96fba6SXin Li 
565*1a96fba6SXin Li template <typename U, typename V>
566*1a96fba6SXin Li typename std::enable_if<IsTypeSupported<U, V>::value>::type AppendValueToWriter(
567*1a96fba6SXin Li     ::dbus::MessageWriter* writer, const std::pair<U, V>& value) {
568*1a96fba6SXin Li   ::dbus::MessageWriter struct_writer(nullptr);
569*1a96fba6SXin Li   writer->OpenStruct(&struct_writer);
570*1a96fba6SXin Li   // Use DBusType<T>::Write() instead of AppendValueToWriter() to delay
571*1a96fba6SXin Li   // binding to AppendValueToWriter() to the point of instantiation of this
572*1a96fba6SXin Li   // template.
573*1a96fba6SXin Li   DBusType<U>::Write(&struct_writer, value.first);
574*1a96fba6SXin Li   DBusType<V>::Write(&struct_writer, value.second);
575*1a96fba6SXin Li   writer->CloseContainer(&struct_writer);
576*1a96fba6SXin Li }
577*1a96fba6SXin Li 
578*1a96fba6SXin Li template <typename U, typename V>
579*1a96fba6SXin Li typename std::enable_if<IsTypeSupported<U, V>::value, bool>::type
580*1a96fba6SXin Li PopValueFromReader(::dbus::MessageReader* reader, std::pair<U, V>* value) {
581*1a96fba6SXin Li   ::dbus::MessageReader variant_reader(nullptr);
582*1a96fba6SXin Li   ::dbus::MessageReader struct_reader(nullptr);
583*1a96fba6SXin Li   if (!details::DescendIntoVariantIfPresent(&reader, &variant_reader) ||
584*1a96fba6SXin Li       !reader->PopStruct(&struct_reader))
585*1a96fba6SXin Li     return false;
586*1a96fba6SXin Li   // Use DBusType<T>::Read() instead of PopValueFromReader() to delay
587*1a96fba6SXin Li   // binding to PopValueFromReader() to the point of instantiation of this
588*1a96fba6SXin Li   // template.
589*1a96fba6SXin Li   return DBusType<U>::Read(&struct_reader, &value->first) &&
590*1a96fba6SXin Li          DBusType<V>::Read(&struct_reader, &value->second);
591*1a96fba6SXin Li }
592*1a96fba6SXin Li 
593*1a96fba6SXin Li namespace details {
594*1a96fba6SXin Li 
595*1a96fba6SXin Li // DBusArrayType<> is a helper base class for DBusType<pair<U, V>> that provides
596*1a96fba6SXin Li // GetSignature/Write/Read methods for types that are supported by D-Bus
597*1a96fba6SXin Li // and not having those methods for types that are not supported by D-Bus.
598*1a96fba6SXin Li template<bool inner_type_supported, typename U, typename V>
599*1a96fba6SXin Li struct DBusPairType {
600*1a96fba6SXin Li   // Returns "(UV)", where "U" and "V" are the signature strings for types U, V.
601*1a96fba6SXin Li   inline static std::string GetSignature() {
602*1a96fba6SXin Li     return GetStructDBusSignature<U, V>();
603*1a96fba6SXin Li   }
604*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer,
605*1a96fba6SXin Li                            const std::pair<U, V>& value) {
606*1a96fba6SXin Li     AppendValueToWriter(writer, value);
607*1a96fba6SXin Li   }
608*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader,
609*1a96fba6SXin Li                           std::pair<U, V>* value) {
610*1a96fba6SXin Li     return PopValueFromReader(reader, value);
611*1a96fba6SXin Li   }
612*1a96fba6SXin Li };
613*1a96fba6SXin Li 
614*1a96fba6SXin Li // Either U, or V, or both are not supported by D-Bus.
615*1a96fba6SXin Li template<typename U, typename V>
616*1a96fba6SXin Li struct DBusPairType<false, U, V> : public Unsupported {};
617*1a96fba6SXin Li 
618*1a96fba6SXin Li }  // namespace details
619*1a96fba6SXin Li 
620*1a96fba6SXin Li template<typename U, typename V>
621*1a96fba6SXin Li struct DBusType<std::pair<U, V>>
622*1a96fba6SXin Li     : public details::DBusPairType<IsTypeSupported<U, V>::value, U, V> {};
623*1a96fba6SXin Li 
624*1a96fba6SXin Li // std::tuple = D-Bus STRUCT with arbitrary number of members. ----------------
625*1a96fba6SXin Li namespace details {
626*1a96fba6SXin Li 
627*1a96fba6SXin Li // TupleIterator<I, N, T...> is a helper class to iterate over all the elements
628*1a96fba6SXin Li // of a tuple<T...> from index I to N. TupleIterator<>::Read and ::Write methods
629*1a96fba6SXin Li // are called for each element of the tuple and iteration continues until I == N
630*1a96fba6SXin Li // in which case the specialization for I==N below stops the recursion.
631*1a96fba6SXin Li template<size_t I, size_t N, typename... T>
632*1a96fba6SXin Li struct TupleIterator {
633*1a96fba6SXin Li   // Tuple is just a convenience alias to a tuple containing elements of type T.
634*1a96fba6SXin Li   using Tuple = std::tuple<T...>;
635*1a96fba6SXin Li   // ValueType is the type of the element at index I.
636*1a96fba6SXin Li   using ValueType = typename std::tuple_element<I, Tuple>::type;
637*1a96fba6SXin Li 
638*1a96fba6SXin Li   // Write the tuple element at index I to D-Bus message.
639*1a96fba6SXin Li   static void Write(::dbus::MessageWriter* writer, const Tuple& value) {
640*1a96fba6SXin Li     // Use DBusType<T>::Write() instead of AppendValueToWriter() to delay
641*1a96fba6SXin Li     // binding to AppendValueToWriter() to the point of instantiation of this
642*1a96fba6SXin Li     // template.
643*1a96fba6SXin Li     DBusType<ValueType>::Write(writer, std::get<I>(value));
644*1a96fba6SXin Li     TupleIterator<I + 1, N, T...>::Write(writer, value);
645*1a96fba6SXin Li   }
646*1a96fba6SXin Li 
647*1a96fba6SXin Li   // Read the tuple element at index I from D-Bus message.
648*1a96fba6SXin Li   static bool Read(::dbus::MessageReader* reader, Tuple* value) {
649*1a96fba6SXin Li     // Use DBusType<T>::Read() instead of PopValueFromReader() to delay
650*1a96fba6SXin Li     // binding to PopValueFromReader() to the point of instantiation of this
651*1a96fba6SXin Li     // template.
652*1a96fba6SXin Li     return DBusType<ValueType>::Read(reader, &std::get<I>(*value)) &&
653*1a96fba6SXin Li            TupleIterator<I + 1, N, T...>::Read(reader, value);
654*1a96fba6SXin Li   }
655*1a96fba6SXin Li };
656*1a96fba6SXin Li 
657*1a96fba6SXin Li // Specialization to end the iteration when the index reaches the last element.
658*1a96fba6SXin Li template<size_t N, typename... T>
659*1a96fba6SXin Li struct TupleIterator<N, N, T...> {
660*1a96fba6SXin Li   using Tuple = std::tuple<T...>;
661*1a96fba6SXin Li   static void Write(::dbus::MessageWriter* /* writer */,
662*1a96fba6SXin Li                     const Tuple& /* value */) {}
663*1a96fba6SXin Li   static bool Read(::dbus::MessageReader* /* reader */, Tuple* /* value */) {
664*1a96fba6SXin Li     return true;
665*1a96fba6SXin Li   }
666*1a96fba6SXin Li };
667*1a96fba6SXin Li 
668*1a96fba6SXin Li }  // namespace details
669*1a96fba6SXin Li 
670*1a96fba6SXin Li template <typename... T>
671*1a96fba6SXin Li typename std::enable_if<IsTypeSupported<T...>::value>::type AppendValueToWriter(
672*1a96fba6SXin Li     ::dbus::MessageWriter* writer, const std::tuple<T...>& value) {
673*1a96fba6SXin Li   ::dbus::MessageWriter struct_writer(nullptr);
674*1a96fba6SXin Li   writer->OpenStruct(&struct_writer);
675*1a96fba6SXin Li   details::TupleIterator<0, sizeof...(T), T...>::Write(&struct_writer, value);
676*1a96fba6SXin Li   writer->CloseContainer(&struct_writer);
677*1a96fba6SXin Li }
678*1a96fba6SXin Li 
679*1a96fba6SXin Li template <typename... T>
680*1a96fba6SXin Li typename std::enable_if<IsTypeSupported<T...>::value, bool>::type
681*1a96fba6SXin Li PopValueFromReader(::dbus::MessageReader* reader, std::tuple<T...>* value) {
682*1a96fba6SXin Li   ::dbus::MessageReader variant_reader(nullptr);
683*1a96fba6SXin Li   ::dbus::MessageReader struct_reader(nullptr);
684*1a96fba6SXin Li   if (!details::DescendIntoVariantIfPresent(&reader, &variant_reader) ||
685*1a96fba6SXin Li       !reader->PopStruct(&struct_reader))
686*1a96fba6SXin Li     return false;
687*1a96fba6SXin Li   return details::TupleIterator<0, sizeof...(T), T...>::Read(&struct_reader,
688*1a96fba6SXin Li                                                              value);
689*1a96fba6SXin Li }
690*1a96fba6SXin Li 
691*1a96fba6SXin Li namespace details {
692*1a96fba6SXin Li 
693*1a96fba6SXin Li // DBusTupleType<> is a helper base class for DBusType<tuple<T...>> that
694*1a96fba6SXin Li // provides GetSignature/Write/Read methods for types that are supported by
695*1a96fba6SXin Li // D-Bus and not having those methods for types that are not supported by D-Bus.
696*1a96fba6SXin Li template<bool inner_type_supported, typename... T>
697*1a96fba6SXin Li struct DBusTupleType {
698*1a96fba6SXin Li   // Returns "(T...)", where "T..." are the signature strings for types T...
699*1a96fba6SXin Li   inline static std::string GetSignature() {
700*1a96fba6SXin Li     return GetStructDBusSignature<T...>();
701*1a96fba6SXin Li   }
702*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer,
703*1a96fba6SXin Li                            const std::tuple<T...>& value) {
704*1a96fba6SXin Li     AppendValueToWriter(writer, value);
705*1a96fba6SXin Li   }
706*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader,
707*1a96fba6SXin Li                           std::tuple<T...>* value) {
708*1a96fba6SXin Li     return PopValueFromReader(reader, value);
709*1a96fba6SXin Li   }
710*1a96fba6SXin Li };
711*1a96fba6SXin Li 
712*1a96fba6SXin Li // Some/all of types T... are not supported by D-Bus.
713*1a96fba6SXin Li template<typename... T>
714*1a96fba6SXin Li struct DBusTupleType<false, T...> : public Unsupported {};
715*1a96fba6SXin Li 
716*1a96fba6SXin Li }  // namespace details
717*1a96fba6SXin Li 
718*1a96fba6SXin Li template<typename... T>
719*1a96fba6SXin Li struct DBusType<std::tuple<T...>>
720*1a96fba6SXin Li     : public details::DBusTupleType<IsTypeSupported<T...>::value, T...> {};
721*1a96fba6SXin Li 
722*1a96fba6SXin Li // std::map = D-Bus ARRAY of DICT_ENTRY. --------------------------------------
723*1a96fba6SXin Li template <typename KEY, typename VALUE, typename PRED, typename ALLOC>
724*1a96fba6SXin Li typename std::enable_if<IsTypeSupported<KEY, VALUE>::value>::type
725*1a96fba6SXin Li AppendValueToWriter(::dbus::MessageWriter* writer,
726*1a96fba6SXin Li                     const std::map<KEY, VALUE, PRED, ALLOC>& value) {
727*1a96fba6SXin Li   ::dbus::MessageWriter dict_writer(nullptr);
728*1a96fba6SXin Li   writer->OpenArray(details::GetDBusDictEntryType<KEY, VALUE>(), &dict_writer);
729*1a96fba6SXin Li   for (const auto& pair : value) {
730*1a96fba6SXin Li     ::dbus::MessageWriter entry_writer(nullptr);
731*1a96fba6SXin Li     dict_writer.OpenDictEntry(&entry_writer);
732*1a96fba6SXin Li     // Use DBusType<T>::Write() instead of AppendValueToWriter() to delay
733*1a96fba6SXin Li     // binding to AppendValueToWriter() to the point of instantiation of this
734*1a96fba6SXin Li     // template.
735*1a96fba6SXin Li     DBusType<KEY>::Write(&entry_writer, pair.first);
736*1a96fba6SXin Li     DBusType<VALUE>::Write(&entry_writer, pair.second);
737*1a96fba6SXin Li     dict_writer.CloseContainer(&entry_writer);
738*1a96fba6SXin Li   }
739*1a96fba6SXin Li   writer->CloseContainer(&dict_writer);
740*1a96fba6SXin Li }
741*1a96fba6SXin Li 
742*1a96fba6SXin Li template <typename KEY, typename VALUE, typename PRED, typename ALLOC>
743*1a96fba6SXin Li typename std::enable_if<IsTypeSupported<KEY, VALUE>::value, bool>::type
744*1a96fba6SXin Li PopValueFromReader(::dbus::MessageReader* reader,
745*1a96fba6SXin Li                    std::map<KEY, VALUE, PRED, ALLOC>* value) {
746*1a96fba6SXin Li   ::dbus::MessageReader variant_reader(nullptr);
747*1a96fba6SXin Li   ::dbus::MessageReader array_reader(nullptr);
748*1a96fba6SXin Li   if (!details::DescendIntoVariantIfPresent(&reader, &variant_reader) ||
749*1a96fba6SXin Li       !reader->PopArray(&array_reader))
750*1a96fba6SXin Li     return false;
751*1a96fba6SXin Li   value->clear();
752*1a96fba6SXin Li   while (array_reader.HasMoreData()) {
753*1a96fba6SXin Li     ::dbus::MessageReader dict_entry_reader(nullptr);
754*1a96fba6SXin Li     if (!array_reader.PopDictEntry(&dict_entry_reader))
755*1a96fba6SXin Li       return false;
756*1a96fba6SXin Li     KEY key;
757*1a96fba6SXin Li     VALUE data;
758*1a96fba6SXin Li     // Use DBusType<T>::Read() instead of PopValueFromReader() to delay
759*1a96fba6SXin Li     // binding to PopValueFromReader() to the point of instantiation of this
760*1a96fba6SXin Li     // template.
761*1a96fba6SXin Li     if (!DBusType<KEY>::Read(&dict_entry_reader, &key) ||
762*1a96fba6SXin Li         !DBusType<VALUE>::Read(&dict_entry_reader, &data))
763*1a96fba6SXin Li       return false;
764*1a96fba6SXin Li     value->emplace(std::move(key), std::move(data));
765*1a96fba6SXin Li   }
766*1a96fba6SXin Li   return true;
767*1a96fba6SXin Li }
768*1a96fba6SXin Li 
769*1a96fba6SXin Li namespace details {
770*1a96fba6SXin Li 
771*1a96fba6SXin Li // DBusArrayType<> is a helper base class for DBusType<map<K, V>> that provides
772*1a96fba6SXin Li // GetSignature/Write/Read methods for T types that are supported by D-Bus
773*1a96fba6SXin Li // and not having those methods for types that are not supported by D-Bus.
774*1a96fba6SXin Li template<bool inner_types_supported,
775*1a96fba6SXin Li          typename KEY,
776*1a96fba6SXin Li          typename VALUE,
777*1a96fba6SXin Li          typename PRED,
778*1a96fba6SXin Li          typename ALLOC>
779*1a96fba6SXin Li struct DBusMapType {
780*1a96fba6SXin Li   // Returns "a{KV}", where "K" and "V" are the signature strings for types
781*1a96fba6SXin Li   // KEY/VALUE.
782*1a96fba6SXin Li   inline static std::string GetSignature() {
783*1a96fba6SXin Li     return GetArrayDBusSignature(GetDBusDictEntryType<KEY, VALUE>());
784*1a96fba6SXin Li   }
785*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer,
786*1a96fba6SXin Li                            const std::map<KEY, VALUE, PRED, ALLOC>& value) {
787*1a96fba6SXin Li     AppendValueToWriter(writer, value);
788*1a96fba6SXin Li   }
789*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader,
790*1a96fba6SXin Li                           std::map<KEY, VALUE, PRED, ALLOC>* value) {
791*1a96fba6SXin Li     return PopValueFromReader(reader, value);
792*1a96fba6SXin Li   }
793*1a96fba6SXin Li };
794*1a96fba6SXin Li 
795*1a96fba6SXin Li // Types KEY, VALUE or both are not supported by D-Bus.
796*1a96fba6SXin Li template<typename KEY, typename VALUE, typename PRED, typename ALLOC>
797*1a96fba6SXin Li struct DBusMapType<false, KEY, VALUE, PRED, ALLOC> : public Unsupported {};
798*1a96fba6SXin Li 
799*1a96fba6SXin Li }  // namespace details
800*1a96fba6SXin Li 
801*1a96fba6SXin Li template<typename KEY, typename VALUE, typename PRED, typename ALLOC>
802*1a96fba6SXin Li struct DBusType<std::map<KEY, VALUE, PRED, ALLOC>>
803*1a96fba6SXin Li     : public details::DBusMapType<IsTypeSupported<KEY, VALUE>::value,
804*1a96fba6SXin Li                                   KEY,
805*1a96fba6SXin Li                                   VALUE,
806*1a96fba6SXin Li                                   PRED,
807*1a96fba6SXin Li                                   ALLOC> {};
808*1a96fba6SXin Li 
809*1a96fba6SXin Li // google::protobuf::MessageLite = D-Bus ARRAY of BYTE ------------------------
810*1a96fba6SXin Li inline void AppendValueToWriter(::dbus::MessageWriter* writer,
811*1a96fba6SXin Li                                 const google::protobuf::MessageLite& value) {
812*1a96fba6SXin Li   writer->AppendProtoAsArrayOfBytes(value);
813*1a96fba6SXin Li }
814*1a96fba6SXin Li 
815*1a96fba6SXin Li inline bool PopValueFromReader(::dbus::MessageReader* reader,
816*1a96fba6SXin Li                                google::protobuf::MessageLite* value) {
817*1a96fba6SXin Li   return reader->PopArrayOfBytesAsProto(value);
818*1a96fba6SXin Li }
819*1a96fba6SXin Li 
820*1a96fba6SXin Li // is_protobuf_t<T> is a helper type trait to determine if type T derives from
821*1a96fba6SXin Li // google::protobuf::MessageLite.
822*1a96fba6SXin Li template<typename T>
823*1a96fba6SXin Li using is_protobuf = std::is_base_of<google::protobuf::MessageLite, T>;
824*1a96fba6SXin Li 
825*1a96fba6SXin Li // Specialize DBusType<T> for classes that derive from protobuf::MessageLite.
826*1a96fba6SXin Li // Here we perform a partial specialization of DBusType<T> only for types
827*1a96fba6SXin Li // that derive from google::protobuf::MessageLite. This is done by employing
828*1a96fba6SXin Li // the second template parameter in DBusType and this basically relies on C++
829*1a96fba6SXin Li // SFINAE rules. "typename std::enable_if<is_protobuf<T>::value>::type" will
830*1a96fba6SXin Li // evaluate to "void" for classes T that descend from MessageLite and will be
831*1a96fba6SXin Li // an invalid construct for other types/classes which will automatically
832*1a96fba6SXin Li // remove this particular specialization from name resolution context.
833*1a96fba6SXin Li template<typename T>
834*1a96fba6SXin Li struct DBusType<T, typename std::enable_if<is_protobuf<T>::value>::type> {
835*1a96fba6SXin Li   inline static std::string GetSignature() {
836*1a96fba6SXin Li     return GetDBusSignature<std::vector<uint8_t>>();
837*1a96fba6SXin Li   }
838*1a96fba6SXin Li   inline static void Write(::dbus::MessageWriter* writer, const T& value) {
839*1a96fba6SXin Li     AppendValueToWriter(writer, value);
840*1a96fba6SXin Li   }
841*1a96fba6SXin Li   inline static bool Read(::dbus::MessageReader* reader, T* value) {
842*1a96fba6SXin Li     return PopValueFromReader(reader, value);
843*1a96fba6SXin Li   }
844*1a96fba6SXin Li };
845*1a96fba6SXin Li 
846*1a96fba6SXin Li //----------------------------------------------------------------------------
847*1a96fba6SXin Li // AppendValueToWriterAsVariant<T>(::dbus::MessageWriter* writer, const T&
848*1a96fba6SXin Li // value) Write the |value| of type T to D-Bus message as a VARIANT. This
849*1a96fba6SXin Li // overload is provided only if T is supported by D-Bus.
850*1a96fba6SXin Li template <typename T>
851*1a96fba6SXin Li typename std::enable_if<IsTypeSupported<T>::value>::type
852*1a96fba6SXin Li AppendValueToWriterAsVariant(::dbus::MessageWriter* writer, const T& value) {
853*1a96fba6SXin Li   std::string data_type = GetDBusSignature<T>();
854*1a96fba6SXin Li   ::dbus::MessageWriter variant_writer(nullptr);
855*1a96fba6SXin Li   writer->OpenVariant(data_type, &variant_writer);
856*1a96fba6SXin Li   // Use DBusType<T>::Write() instead of AppendValueToWriter() to delay
857*1a96fba6SXin Li   // binding to AppendValueToWriter() to the point of instantiation of this
858*1a96fba6SXin Li   // template.
859*1a96fba6SXin Li   DBusType<T>::Write(&variant_writer, value);
860*1a96fba6SXin Li   writer->CloseContainer(&variant_writer);
861*1a96fba6SXin Li }
862*1a96fba6SXin Li 
863*1a96fba6SXin Li // Special case: do not allow to write a Variant containing a Variant.
864*1a96fba6SXin Li // Just redirect to normal AppendValueToWriter().
865*1a96fba6SXin Li inline void AppendValueToWriterAsVariant(::dbus::MessageWriter* writer,
866*1a96fba6SXin Li                                          const brillo::Any& value) {
867*1a96fba6SXin Li   return AppendValueToWriter(writer, value);
868*1a96fba6SXin Li }
869*1a96fba6SXin Li 
870*1a96fba6SXin Li //----------------------------------------------------------------------------
871*1a96fba6SXin Li // PopVariantValueFromReader<T>(::dbus::MessageWriter* writer, T* value)
872*1a96fba6SXin Li // Reads a Variant containing the |value| of type T from D-Bus message.
873*1a96fba6SXin Li // Note that the generic PopValueFromReader<T>(...) can do this too.
874*1a96fba6SXin Li // This method is provided for two reasons:
875*1a96fba6SXin Li //   1. For API symmetry with AppendValueToWriter/AppendValueToWriterAsVariant.
876*1a96fba6SXin Li //   2. To be used when it is important to assert that the data was sent
877*1a96fba6SXin Li //      specifically as a Variant.
878*1a96fba6SXin Li // This overload is provided only if T is supported by D-Bus.
879*1a96fba6SXin Li template <typename T>
880*1a96fba6SXin Li typename std::enable_if<IsTypeSupported<T>::value, bool>::type
881*1a96fba6SXin Li PopVariantValueFromReader(::dbus::MessageReader* reader, T* value) {
882*1a96fba6SXin Li   ::dbus::MessageReader variant_reader(nullptr);
883*1a96fba6SXin Li   if (!reader->PopVariant(&variant_reader))
884*1a96fba6SXin Li     return false;
885*1a96fba6SXin Li   // Use DBusType<T>::Read() instead of PopValueFromReader() to delay
886*1a96fba6SXin Li   // binding to PopValueFromReader() to the point of instantiation of this
887*1a96fba6SXin Li   // template.
888*1a96fba6SXin Li   return DBusType<T>::Read(&variant_reader, value);
889*1a96fba6SXin Li }
890*1a96fba6SXin Li 
891*1a96fba6SXin Li // Special handling of request to read a Variant of Variant.
892*1a96fba6SXin Li inline bool PopVariantValueFromReader(::dbus::MessageReader* reader,
893*1a96fba6SXin Li                                       Any* value) {
894*1a96fba6SXin Li   return PopValueFromReader(reader, value);
895*1a96fba6SXin Li }
896*1a96fba6SXin Li 
897*1a96fba6SXin Li }  // namespace dbus_utils
898*1a96fba6SXin Li }  // namespace brillo
899*1a96fba6SXin Li 
900*1a96fba6SXin Li #endif  // LIBBRILLO_BRILLO_DBUS_DATA_SERIALIZATION_H_
901