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