• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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