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