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