1 #ifndef ANDROID_PDX_RPC_SERIALIZABLE_H_ 2 #define ANDROID_PDX_RPC_SERIALIZABLE_H_ 3 4 #include <cstddef> 5 #include <string> 6 #include <tuple> 7 8 #include <pdx/message_reader.h> 9 #include <pdx/message_writer.h> 10 11 #include "macros.h" 12 #include "serialization.h" 13 14 namespace android { 15 namespace pdx { 16 namespace rpc { 17 18 // This file provides utilities to define serializable types for communication 19 // between clients and services. Supporting efficient, typed communication 20 // protocols is the primary goal, NOT providing a general-purpose solution for 21 // all your C++ serialization needs. Features that are not aligned to the goals 22 // are not supported, such as static/const member serialization and serializable 23 // types with virtual methods (requiring a virtual destructor). 24 25 // Captures the type and value of a pointer to member. Pointer to members are 26 // essentially compile-time constant offsets that can be stored in the type 27 // system without adding to the size of the structures they describe. This 28 // library uses this property to implement a limited form of reflection for 29 // serialization/deserialization functions. 30 template <typename T, T> 31 struct MemberPointer; 32 33 template <typename Type, typename Class, Type Class::*Pointer> 34 struct MemberPointer<Type Class::*, Pointer> { 35 // Type of the member pointer this type represents. 36 using PointerType = Type Class::*; 37 38 // Resolves a pointer to member with the given instance, yielding a 39 // reference to the member in that instance. 40 static Type& Resolve(Class& instance) { return (instance.*Pointer); } 41 static const Type& Resolve(const Class& instance) { 42 return (instance.*Pointer); 43 } 44 }; 45 46 // Describes a set of members to be serialized/deserialized by this library. The 47 // parameter pack MemberPointers takes a list of MemberPointer types that 48 // describe each member to participate in serialization/deserialization. 49 template <typename T, typename... MemberPointers> 50 struct SerializableMembersType { 51 using Type = T; 52 53 // The number of member pointers described by this type. 54 enum : std::size_t { MemberCount = sizeof...(MemberPointers) }; 55 56 // The member pointers described by this type. 57 using Members = std::tuple<MemberPointers...>; 58 59 // Accessor for individual member pointer types. 60 template <std::size_t Index> 61 using At = typename std::tuple_element<Index, Members>::type; 62 }; 63 64 // Classes must do the following to correctly define a serializable type: 65 // 1. Define a type called "SerializableMembers" as a template instantiation 66 // of SerializableMembersType, describing the members of the class to 67 // participate in serialization (presumably all of them). Use the macro 68 // PDX_SERIALIZABLE_MEMBERS(...) below to aid the correct type 69 // definition. This type should be private to prevent leaking member 70 // access information. 71 // 2. Make SerializableTraits and HasSerilizableMembers types a friend of 72 // the class. The macro PDX_SERIALIZABLE_MEMEBRS(...) takes care of 73 // this automatically. 74 // 3. Define a public default constructor, if necessary. Deserialization 75 // requires instances to be default-constructible. 76 // 77 // Example usage: 78 // class MySerializableType : public AnotherBaseType { 79 // public: 80 // MySerializableType(); 81 // ... 82 // private: 83 // int a; 84 // string b; 85 // PDX_SERIALIZABLE_MEMBERS(MySerializableType, a, b); 86 // }; 87 // 88 // Note that const and static member serialization is not supported. 89 90 template <typename T> 91 class SerializableTraits { 92 public: 93 // Gets the serialized size of type T. 94 static std::size_t GetSerializedSize(const T& value) { 95 return GetEncodingSize(EncodeArrayType(SerializableMembers::MemberCount)) + 96 GetMembersSize<SerializableMembers>(value); 97 } 98 99 // Serializes type T. 100 static void SerializeObject(const T& value, MessageWriter* writer, 101 void*& buffer) { 102 SerializeArrayEncoding(EncodeArrayType(SerializableMembers::MemberCount), 103 SerializableMembers::MemberCount, buffer); 104 SerializeMembers<SerializableMembers>(value, writer, buffer); 105 } 106 107 // Deserializes type T. 108 static ErrorType DeserializeObject(T* value, MessageReader* reader, 109 const void*& start, const void* end) { 110 EncodingType encoding; 111 std::size_t size; 112 113 if (const auto error = 114 DeserializeArrayType(&encoding, &size, reader, start, end)) { 115 return error; 116 } else if (size != SerializableMembers::MemberCount) { 117 return ErrorCode::UNEXPECTED_TYPE_SIZE; 118 } else { 119 return DeserializeMembers<SerializableMembers>(value, reader, start, end); 120 } 121 } 122 123 private: 124 using SerializableMembers = typename T::SerializableMembers; 125 }; 126 127 // Utility macro to define a MemberPointer type for a member name. 128 #define PDX_MEMBER_POINTER(type, member) \ 129 ::android::pdx::rpc::MemberPointer<decltype(&type::member), &type::member> 130 131 // Defines a list of MemberPointer types given a list of member names. 132 #define PDX_MEMBERS(type, ... /*members*/) \ 133 PDX_FOR_EACH_BINARY_LIST(PDX_MEMBER_POINTER, type, __VA_ARGS__) 134 135 // Defines the serializable members of a type given a list of member names and 136 // befriends SerializableTraits and HasSerializableMembers for the class. This 137 // macro handles requirements #1 and #2 above. 138 #define PDX_SERIALIZABLE_MEMBERS(type, ... /*members*/) \ 139 template <typename T> \ 140 friend class ::android::pdx::rpc::SerializableTraits; \ 141 template <typename, typename> \ 142 friend struct ::android::pdx::rpc::HasSerializableMembers; \ 143 using SerializableMembers = ::android::pdx::rpc::SerializableMembersType< \ 144 type, PDX_MEMBERS(type, __VA_ARGS__)> 145 146 } // namespace rpc 147 } // namespace pdx 148 } // namespace android 149 150 #endif // ANDROID_PDX_RPC_SERIALIZABLE_H_ 151