HELLO·Android
系统源代码
IT资讯
技术文章
我的收藏
注册
登录
-
我收藏的文章
创建代码块
我的代码块
我的账号
Oreo
|
8.0.0_r4
下载
查看原文件
收藏
根目录
frameworks
native
libs
vr
libpdx
private
pdx
rpc
serialization.h
#ifndef ANDROID_PDX_RPC_SERIALIZATION_H_ #define ANDROID_PDX_RPC_SERIALIZATION_H_ #include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "array_wrapper.h" #include "default_initialization_allocator.h" #include "encoding.h" #include "pointer_wrapper.h" #include "string_wrapper.h" #include "variant.h" namespace android { namespace pdx { namespace rpc { // Automatic serialization/deserialization library based on MessagePack // (http://msgpack.org). This library provides top level Serialize() and // Deserialize() functions to encode/decode a variety of data types. // // The following data types are supported: // * Standard signed integer types: int8_t, int16_t, int32_t, and int64_t. // * Regular signed integer types equivalent to the standard types: // signed char, short, int, long, and long long. // * Standard unsigned integer types: uint8_t, uint16_t, uint32_t, and // uint64_t. // * Regular unsigned integer types equivalent to the standard types: // unsigned char, unsigned short, unsigned int, unsigned long, // and unsigned long long. // * char without signed/unsigned qualifiers. // * bool. // * std::vector with value type of any supported type, including nesting. // * std::string. // * std::tuple with elements of any supported type, including nesting. // * std::pair with elements of any supported type, including nesting. // * std::map with keys and values of any supported type, including nesting. // * std::unordered_map with keys and values of any supported type, including // nesting. // * std::array with values of any supported type, including nesting. // * ArrayWrapper of any supported basic type. // * BufferWrapper of any POD type. // * StringWrapper of any supported char type. // * User types with correctly defined SerializableMembers member type. // // Planned support for: // * std::basic_string with all supported char types. // Counting template for managing template recursion. template
struct Index {}; // Forward declaration of traits type to access types with a SerializedMembers // member type. template
class SerializableTraits; template
struct SerializableMembersType; // Utility to deduce the template type from a derived type. template
class TT, typename... Ts> std::true_type DeduceTemplateType(const TT
*); template
class TT> std::false_type DeduceTemplateType(...); // Utility determining whether template type TT<...> is a base of type T. template
class TT, typename T> using IsTemplateBaseOf = decltype(DeduceTemplateType
(std::declval
())); // Utility type for SFINAE in HasHasSerializableMembers. template
using TrySerializableMembersType = void; // Determines whether type T has a member type named SerializableMembers of // template type SerializableMembersType. template
struct HasSerializableMembers : std::false_type {}; template
struct HasSerializableMembers< T, TrySerializableMembersType
> : std::integral_constant< bool, IsTemplateBaseOf
::value> {}; // Utility to simplify overload enable expressions for types with correctly // defined SerializableMembers. template
using EnableIfHasSerializableMembers = typename std::enable_if
::value>::type; // Utility to simplify overload enable expressions for enum types. template
using EnableIfEnum = typename std::enable_if
::value, ReturnType>::type; /////////////////////////////////////////////////////////////////////////////// // Error Reporting // /////////////////////////////////////////////////////////////////////////////// // Error codes returned by the deserialization code. enum class ErrorCode { NO_ERROR = 0, UNEXPECTED_ENCODING, UNEXPECTED_TYPE_SIZE, INSUFFICIENT_BUFFER, INSUFFICIENT_DESTINATION_SIZE, GET_FILE_DESCRIPTOR_FAILED, GET_CHANNEL_HANDLE_FAILED, INVALID_VARIANT_ELEMENT, }; // Type for errors returned by the deserialization code. class ErrorType { public: ErrorType() : error_code_(ErrorCode::NO_ERROR) {} // ErrorType constructor for generic error codes. Explicitly not explicit, // implicit conversion from ErrorCode to ErrorType is desirable behavior. // NOLINTNEXTLINE(runtime/explicit) ErrorType(ErrorCode error_code) : error_code_(error_code) {} // ErrorType constructor for encoding type errors. ErrorType(ErrorCode error_code, EncodingClass encoding_class, EncodingType encoding_type) : error_code_(error_code) { unexpected_encoding_.encoding_class = encoding_class; unexpected_encoding_.encoding_type = encoding_type; } // Evaluates to true if the ErrorType represents an error. explicit operator bool() const { return error_code_ != ErrorCode::NO_ERROR; } operator ErrorCode() const { return error_code_; } ErrorCode error_code() const { return error_code_; } // Accessors for extra info about unexpected encoding errors. EncodingClass encoding_class() const { return unexpected_encoding_.encoding_class; } EncodingType encoding_type() const { return unexpected_encoding_.encoding_type; } operator std::string() const { std::ostringstream stream; switch (error_code_) { case ErrorCode::NO_ERROR: return "NO_ERROR"; case ErrorCode::UNEXPECTED_ENCODING: stream << "UNEXPECTED_ENCODING: " << static_cast
(encoding_class()) << ", " << static_cast
(encoding_type()); return stream.str(); case ErrorCode::UNEXPECTED_TYPE_SIZE: return "UNEXPECTED_TYPE_SIZE"; case ErrorCode::INSUFFICIENT_BUFFER: return "INSUFFICIENT_BUFFER"; case ErrorCode::INSUFFICIENT_DESTINATION_SIZE: return "INSUFFICIENT_DESTINATION_SIZE"; default: return "[Unknown Error]"; } } private: ErrorCode error_code_; // Union of extra information for different error code types. union { // UNEXPECTED_ENCODING. struct { EncodingClass encoding_class; EncodingType encoding_type; } unexpected_encoding_; }; }; /////////////////////////////////////////////////////////////////////////////// // Object Size // /////////////////////////////////////////////////////////////////////////////// inline constexpr std::size_t GetSerializedSize(const bool& b) { return GetEncodingSize(EncodeType(b)); } // Overloads of GetSerializedSize() for standard integer types. inline constexpr std::size_t GetSerializedSize(const char& c) { return GetEncodingSize(EncodeType(c)); } inline constexpr std::size_t GetSerializedSize(const std::uint8_t& i) { return GetEncodingSize(EncodeType(i)); } inline constexpr std::size_t GetSerializedSize(const std::int8_t& i) { return GetEncodingSize(EncodeType(i)); } inline constexpr std::size_t GetSerializedSize(const std::uint16_t& i) { return GetEncodingSize(EncodeType(i)); } inline constexpr std::size_t GetSerializedSize(const std::int16_t& i) { return GetEncodingSize(EncodeType(i)); } inline constexpr std::size_t GetSerializedSize(const std::uint32_t& i) { return GetEncodingSize(EncodeType(i)); } inline constexpr std::size_t GetSerializedSize(const std::int32_t& i) { return GetEncodingSize(EncodeType(i)); } inline constexpr std::size_t GetSerializedSize(const std::uint64_t& i) { return GetEncodingSize(EncodeType(i)); } inline constexpr std::size_t GetSerializedSize(const std::int64_t& i) { return GetEncodingSize(EncodeType(i)); } inline constexpr std::size_t GetSerializedSize(const float& f) { return GetEncodingSize(EncodeType(f)); } inline constexpr std::size_t GetSerializedSize(const double& d) { return GetEncodingSize(EncodeType(d)); } // Overload for enum types. template
inline EnableIfEnum
GetSerializedSize(T v) { return GetSerializedSize(static_cast
>(v)); } // Forward declaration for nested definitions. inline std::size_t GetSerializedSize(const EmptyVariant&); template
inline std::size_t GetSerializedSize(const Variant
&); template
> inline constexpr std::size_t GetSerializedSize(const T&); template
inline constexpr std::size_t GetSerializedSize(const PointerWrapper
&); inline constexpr std::size_t GetSerializedSize(const std::string&); template
inline constexpr std::size_t GetSerializedSize(const StringWrapper
&); template
inline constexpr std::size_t GetSerializedSize(const BufferWrapper
&); template
inline constexpr std::size_t GetSerializedSize(const FileHandle
&); template
inline constexpr std::size_t GetSerializedSize(const ChannelHandle
&); template
inline std::size_t GetSerializedSize(const std::vector
& v); template
inline std::size_t GetSerializedSize( const std::map
& m); template
inline std::size_t GetSerializedSize( const std::unordered_map
&); template
inline std::size_t GetSerializedSize(const ArrayWrapper
&); template
inline std::size_t GetSerializedSize(const std::array
& v); template
inline std::size_t GetSerializedSize(const std::pair
& p); template
inline std::size_t GetSerializedSize(const std::tuple
& tuple); // Overload for empty variant type. inline std::size_t GetSerializedSize(const EmptyVariant& empty) { return GetEncodingSize(EncodeType(empty)); } // Overload for Variant types. template
inline std::size_t GetSerializedSize(const Variant
& variant) { return GetEncodingSize(EncodeType(variant)) + GetSerializedSize(variant.index()) + variant.Visit( [](const auto& value) { return GetSerializedSize(value); }); } // Overload for structs/classes with SerializableMembers defined. template
inline constexpr std::size_t GetSerializedSize(const T& value) { return SerializableTraits
::GetSerializedSize(value); } // Overload for PointerWrapper. template
inline constexpr std::size_t GetSerializedSize(const PointerWrapper
& p) { return GetSerializedSize(p.Dereference()); } // Overload for std::string. inline constexpr std::size_t GetSerializedSize(const std::string& s) { return GetEncodingSize(EncodeType(s)) + s.length() * sizeof(std::string::value_type); } // Overload for StringWrapper. template
inline constexpr std::size_t GetSerializedSize(const StringWrapper
& s) { return GetEncodingSize(EncodeType(s)) + s.length() * sizeof(typename StringWrapper
::value_type); } // Overload for BufferWrapper types. template
inline constexpr std::size_t GetSerializedSize(const BufferWrapper
& b) { return GetEncodingSize(EncodeType(b)) + b.size() * sizeof(typename BufferWrapper
::value_type); } // Overload for FileHandle. FileHandle is encoded as a FIXEXT2, with a type code // of "FileHandle" and a signed 16-bit offset into the pushed fd array. Empty // FileHandles are encoded with an array index of -1. template
inline constexpr std::size_t GetSerializedSize(const FileHandle
& fd) { return GetEncodingSize(EncodeType(fd)) + sizeof(std::int16_t); } // Overload for ChannelHandle. ChannelHandle is encoded as a FIXEXT4, with a // type code of "ChannelHandle" and a signed 32-bit offset into the pushed // channel array. Empty ChannelHandles are encoded with an array index of -1. template
inline constexpr std::size_t GetSerializedSize( const ChannelHandle
& channel_handle) { return GetEncodingSize(EncodeType(channel_handle)) + sizeof(std::int32_t); } // Overload for standard vector types. template
inline std::size_t GetSerializedSize(const std::vector
& v) { return std::accumulate(v.begin(), v.end(), GetEncodingSize(EncodeType(v)), [](const std::size_t& sum, const T& object) { return sum + GetSerializedSize(object); }); } // Overload for standard map types. template
inline std::size_t GetSerializedSize( const std::map
& v) { return std::accumulate( v.begin(), v.end(), GetEncodingSize(EncodeType(v)), [](const std::size_t& sum, const std::pair
& object) { return sum + GetSerializedSize(object.first) + GetSerializedSize(object.second); }); } // Overload for standard unordered_map types. template
inline std::size_t GetSerializedSize( const std::unordered_map
& v) { return std::accumulate( v.begin(), v.end(), GetEncodingSize(EncodeType(v)), [](const std::size_t& sum, const std::pair
& object) { return sum + GetSerializedSize(object.first) + GetSerializedSize(object.second); }); } // Overload for ArrayWrapper types. template
inline std::size_t GetSerializedSize(const ArrayWrapper
& v) { return std::accumulate(v.begin(), v.end(), GetEncodingSize(EncodeType(v)), [](const std::size_t& sum, const T& object) { return sum + GetSerializedSize(object); }); } // Overload for std::array types. template
inline std::size_t GetSerializedSize(const std::array
& v) { return std::accumulate(v.begin(), v.end(), GetEncodingSize(EncodeType(v)), [](const std::size_t& sum, const T& object) { return sum + GetSerializedSize(object); }); } // Overload for std::pair. template
inline std::size_t GetSerializedSize(const std::pair
& p) { return GetEncodingSize(EncodeType(p)) + GetSerializedSize(p.first) + GetSerializedSize(p.second); } // Stops template recursion when the last tuple element is reached. template
inline std::size_t GetTupleSize(const std::tuple
&, Index<0>) { return 0; } // Gets the size of each element in a tuple recursively. template
inline std::size_t GetTupleSize(const std::tuple
& tuple, Index
) { return GetTupleSize(tuple, Index
()) + GetSerializedSize(std::get
(tuple)); } // Overload for tuple types. Gets the size of the tuple, recursing // through the elements. template
inline std::size_t GetSerializedSize(const std::tuple
& tuple) { return GetEncodingSize(EncodeType(tuple)) + GetTupleSize(tuple, Index
()); } // Stops template recursion when the last member of a Serializable // type is reached. template
inline std::size_t GetMemberSize(const T&, Index<0>) { return 0; } // Gets the size of each member of a Serializable type recursively. template
inline std::size_t GetMemberSize(const T& object, Index
) { return GetMemberSize
(object, Index
()) + GetSerializedSize(Members::template At
::Resolve(object)); } // Gets the size of a type using the given SerializableMembersType // type. template
inline std::size_t GetMembersSize(const T& object) { return GetMemberSize
(object, Index
()); } /////////////////////////////////////////////////////////////////////////////// // Object Serialization // /////////////////////////////////////////////////////////////////////////////// // // SerializeRaw() converts a primitive array or type into a raw byte string. // These functions are named differently from SerializeObject() expressly to // avoid catch-all specialization of that template, which can be difficult to // detect otherwise. // inline void WriteRawData(void*& dest, const void* src, size_t size) { memcpy(dest, src, size); dest = static_cast
(dest) + size; } // Serializes a primitive array into a raw byte string. template
::value>::type> inline void SerializeRaw(const T& value, void*& buffer) { WriteRawData(buffer, &value, sizeof(value)); } inline void SerializeEncoding(EncodingType encoding, void*& buffer) { SerializeRaw(encoding, buffer); } inline void SerializeType(const bool& value, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeEncoding(encoding, buffer); } // Serializes the type code, extended type code, and size for // extension types. inline void SerializeExtEncoding(EncodingType encoding, EncodingExtType ext_type, std::size_t size, void*& buffer) { SerializeEncoding(encoding, buffer); if (encoding == ENCODING_TYPE_EXT8) { std::uint8_t length = size; SerializeRaw(length, buffer); } else if (encoding == ENCODING_TYPE_EXT16) { std::uint16_t length = size; SerializeRaw(length, buffer); } else if (encoding == ENCODING_TYPE_EXT32) { std::uint32_t length = size; SerializeRaw(length, buffer); } else /* if (IsFixextEncoding(encoding) */ { // Encoding byte contains the fixext length, nothing else to do. } SerializeRaw(ext_type, buffer); } // Serializes the type code for file descriptor types. template
inline void SerializeType(const FileHandle
& value, void*& buffer) { SerializeExtEncoding(EncodeType(value), ENCODING_EXT_TYPE_FILE_DESCRIPTOR, 2, buffer); } // Serializes the type code for channel handle types. template
inline void SerializeType(const ChannelHandle
& handle, void*& buffer) { SerializeExtEncoding(EncodeType(handle), ENCODING_EXT_TYPE_CHANNEL_HANDLE, 4, buffer); } // Serializes type code for variant types. template
inline void SerializeType(const Variant
& value, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeEncoding(encoding, buffer); } // Serializes the type code for string types. template
inline void SerializeStringType(const StringType& value, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeEncoding(encoding, buffer); if (encoding == ENCODING_TYPE_STR8) { std::uint8_t length = value.length(); SerializeRaw(length, buffer); } else if (encoding == ENCODING_TYPE_STR16) { std::uint16_t length = value.length(); SerializeRaw(length, buffer); } else if (encoding == ENCODING_TYPE_STR32) { std::uint32_t length = value.length(); SerializeRaw(length, buffer); } else /* if (IsFixstrEncoding(encoding) */ { // Encoding byte contains the fixstr length, nothing else to do. } } // Serializes the type code for std::string and StringWrapper. These types are // interchangeable and must serialize to the same format. inline void SerializeType(const std::string& value, void*& buffer) { SerializeStringType(value, buffer); } template
inline void SerializeType(const StringWrapper
& value, void*& buffer) { SerializeStringType(value, buffer); } // Serializes the type code for bin types. inline void SerializeBinEncoding(EncodingType encoding, std::size_t size, void*& buffer) { SerializeEncoding(encoding, buffer); if (encoding == ENCODING_TYPE_BIN8) { std::uint8_t length = size; SerializeRaw(length, buffer); } else if (encoding == ENCODING_TYPE_BIN16) { std::uint16_t length = size; SerializeRaw(length, buffer); } else if (encoding == ENCODING_TYPE_BIN32) { std::uint32_t length = size; SerializeRaw(length, buffer); } else { // Invalid encoding for BIN type. } } // Serializes the type code for BufferWrapper types. template
inline void SerializeType(const BufferWrapper
& value, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeBinEncoding( encoding, value.size() * sizeof(typename BufferWrapper
::value_type), buffer); } // Serializes the array encoding type and length. inline void SerializeArrayEncoding(EncodingType encoding, std::size_t size, void*& buffer) { SerializeEncoding(encoding, buffer); if (encoding == ENCODING_TYPE_ARRAY16) { std::uint16_t length = size; SerializeRaw(length, buffer); } else if (encoding == ENCODING_TYPE_ARRAY32) { std::uint32_t length = size; SerializeRaw(length, buffer); } else /* if (IsFixarrayEncoding(encoding) */ { // Encoding byte contains the fixarray length, nothing else to do. } } // Serializes the map encoding type and length. inline void SerializeMapEncoding(EncodingType encoding, std::size_t size, void*& buffer) { SerializeEncoding(encoding, buffer); if (encoding == ENCODING_TYPE_MAP16) { std::uint16_t length = size; SerializeRaw(length, buffer); } else if (encoding == ENCODING_TYPE_MAP32) { std::uint32_t length = size; SerializeRaw(length, buffer); } else /* if (IsFixmapEncoding(encoding) */ { // Encoding byte contains the fixmap length, nothing else to do. } } // Serializes the type code for array types. template
inline void SerializeArrayType(const ArrayType& value, std::size_t size, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeArrayEncoding(encoding, size, buffer); } // Serializes the type code for map types. template
inline void SerializeMapType(const MapType& value, std::size_t size, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeMapEncoding(encoding, size, buffer); } // Serializes the type code for std::vector and ArrayWrapper. These types are // interchangeable and must serialize to the same format. template
inline void SerializeType(const std::vector
& value, void*& buffer) { SerializeArrayType(value, value.size(), buffer); } template
inline void SerializeType(const ArrayWrapper
& value, void*& buffer) { SerializeArrayType(value, value.size(), buffer); } // Serializes the type code for std::array. This type serializes to the same // format as std::vector and ArrayWrapper and is interchangeable in certain // situations. template
inline void SerializeType(const std::array
& value, void*& buffer) { SerializeArrayType(value, Size, buffer); } // Serializes the type code for std::map types. template
inline void SerializeType(const std::map
& value, void*& buffer) { SerializeMapType(value, value.size(), buffer); } // Serializes the type code for std::unordered_map types. template
inline void SerializeType( const std::unordered_map
& value, void*& buffer) { SerializeMapType(value, value.size(), buffer); } // Serializes the type code for std::pair types. template
inline void SerializeType(const std::pair
& value, void*& buffer) { SerializeArrayType(value, 2, buffer); } // Serializes the type code for std::tuple types. template
inline void SerializeType(const std::tuple
& value, void*& buffer) { SerializeArrayType(value, sizeof...(T), buffer); } // Specialization of SerializeObject for boolean type. inline void SerializeObject(const bool& value, MessageWriter* /*writer*/, void*& buffer) { SerializeType(value, buffer); // Encoding contains the boolean value, nothing else to do. } // Overloads of SerializeObject for float and double types. inline void SerializeObject(const float& value, MessageWriter* /*writer*/, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeEncoding(encoding, buffer); SerializeRaw(value, buffer); } inline void SerializeObject(const double& value, MessageWriter* /*writer*/, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeEncoding(encoding, buffer); SerializeRaw(value, buffer); } // Overloads of SerializeObject() for standard integer types. inline void SerializeObject(const char& value, MessageWriter* /*writer*/, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeEncoding(encoding, buffer); if (encoding == ENCODING_TYPE_UINT8) { SerializeRaw(value, buffer); } else /* if (IsUnsignedFixintEncoding(encoding) */ { // Encoding byte contains the value, nothing else to do. } } inline void SerializeObject(const int8_t& value, MessageWriter* /*writer*/, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeEncoding(encoding, buffer); if (encoding == ENCODING_TYPE_INT8) { SerializeRaw(value, buffer); } else /* if (IsFixintEncoding(encoding) */ { // Encoding byte contains the value, nothing else to do. } } inline void SerializeObject(const uint8_t& value, MessageWriter* /*writer*/, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeEncoding(encoding, buffer); if (encoding == ENCODING_TYPE_UINT8) { SerializeRaw(value, buffer); } else /* if (IsUnsignedFixintEncoding(encoding) */ { // Encoding byte contains the value, nothing else to do. } } inline void SerializeObject(const int16_t& value, MessageWriter* /*writer*/, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeEncoding(encoding, buffer); if (encoding == ENCODING_TYPE_INT8) { const int8_t byte = value; SerializeRaw(byte, buffer); } else if (encoding == ENCODING_TYPE_INT16) { SerializeRaw(value, buffer); } else /* if (IsFixintEncoding(encoding) */ { // Encoding byte contains the value, nothing else to do. } } inline void SerializeObject(const uint16_t& value, MessageWriter* /*writer*/, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeEncoding(encoding, buffer); if (encoding == ENCODING_TYPE_UINT8) { const uint8_t byte = value; SerializeRaw(byte, buffer); } else if (encoding == ENCODING_TYPE_UINT16) { SerializeRaw(value, buffer); } else /* if (IsUnsignedFixintEncoding(encoding) */ { // Encoding byte contains the value, nothing else to do. } } inline void SerializeObject(const int32_t& value, MessageWriter* /*writer*/, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeEncoding(encoding, buffer); if (encoding == ENCODING_TYPE_INT8) { const int8_t byte = value; SerializeRaw(byte, buffer); } else if (encoding == ENCODING_TYPE_INT16) { const int16_t half = value; SerializeRaw(half, buffer); } else if (encoding == ENCODING_TYPE_INT32) { SerializeRaw(value, buffer); } else /* if (IsFixintEncoding(encoding) */ { // Encoding byte contains the value, nothing else to do. } } inline void SerializeObject(const uint32_t& value, MessageWriter* /*writer*/, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeEncoding(encoding, buffer); if (encoding == ENCODING_TYPE_UINT8) { const uint8_t byte = value; SerializeRaw(byte, buffer); } else if (encoding == ENCODING_TYPE_UINT16) { const uint16_t half = value; SerializeRaw(half, buffer); } else if (encoding == ENCODING_TYPE_UINT32) { SerializeRaw(value, buffer); } else /* if (IsUnsignedFixintEncoding(encoding) */ { // Encoding byte contains the value, nothing else to do. } } inline void SerializeObject(const int64_t& value, MessageWriter* /*writer*/, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeEncoding(encoding, buffer); if (encoding == ENCODING_TYPE_INT8) { const int8_t byte = value; SerializeRaw(byte, buffer); } else if (encoding == ENCODING_TYPE_INT16) { const int16_t half = value; SerializeRaw(half, buffer); } else if (encoding == ENCODING_TYPE_INT32) { const int32_t word = value; SerializeRaw(word, buffer); } else if (encoding == ENCODING_TYPE_INT64) { SerializeRaw(value, buffer); } else /* if (IsFixintEncoding(encoding) */ { // Encoding byte contains the value, nothing else to do. } } inline void SerializeObject(const uint64_t& value, MessageWriter* /*writer*/, void*& buffer) { const EncodingType encoding = EncodeType(value); SerializeEncoding(encoding, buffer); if (encoding == ENCODING_TYPE_UINT8) { const uint8_t byte = value; SerializeRaw(byte, buffer); } else if (encoding == ENCODING_TYPE_UINT16) { const uint16_t half = value; SerializeRaw(half, buffer); } else if (encoding == ENCODING_TYPE_UINT32) { const uint32_t word = value; SerializeRaw(word, buffer); } else if (encoding == ENCODING_TYPE_UINT64) { SerializeRaw(value, buffer); } else /* if (IsUnsignedFixintEncoding(encoding) */ { // Encoding byte contains the value, nothing else to do. } } // Serialize enum types. template
inline EnableIfEnum
SerializeObject(const T& value, MessageWriter* writer, void*& buffer) { SerializeObject(static_cast
>(value), writer, buffer); } // Forward declaration for nested definitions. inline void SerializeObject(const EmptyVariant&, MessageWriter*, void*&); template
inline void SerializeObject(const Variant
&, MessageWriter*, void*&); template
> inline void SerializeObject(const T&, MessageWriter*, void*&); template
inline void SerializeObject(const PointerWrapper
&, MessageWriter*, void*&); template
inline void SerializeObject(const FileHandle
&, MessageWriter*, void*&); template
inline void SerializeObject(const ChannelHandle
&, MessageWriter*, void*&); template
inline void SerializeObject(const BufferWrapper
>&, MessageWriter*, void*&); template
inline void SerializeObject(const BufferWrapper
&, MessageWriter*, void*&); inline void SerializeObject(const std::string&, MessageWriter*, void*&); template
inline void SerializeObject(const StringWrapper
&, MessageWriter*, void*&); template
inline void SerializeObject(const std::vector
&, MessageWriter*, void*&); template
inline void SerializeObject(const ArrayWrapper
&, MessageWriter*, void*&); template
inline void SerializeObject(const std::array
&, MessageWriter*, void*&); template
inline void SerializeObject(const std::map
&, MessageWriter*, void*&); template
inline void SerializeObject( const std::unordered_map
&, MessageWriter*, void*&); template
inline void SerializeObject(const std::pair
&, MessageWriter*, void*&); template
inline void SerializeObject(const std::tuple
&, MessageWriter*, void*&); // Overload for empty variant type. inline void SerializeObject(const EmptyVariant& empty, MessageWriter* /*writer*/, void*& buffer) { const EncodingType encoding = EncodeType(empty); SerializeEncoding(encoding, buffer); } // Overload for Variant types. template
inline void SerializeObject(const Variant
& variant, MessageWriter* writer, void*& buffer) { SerializeType(variant, buffer); SerializeObject(variant.index(), writer, buffer); return variant.Visit([writer, &buffer](const auto& value) { return SerializeObject(value, writer, buffer); }); } // Overload for serializable structure/class types. template
inline void SerializeObject(const T& value, MessageWriter* writer, void*& buffer) { SerializableTraits
::SerializeObject(value, writer, buffer); } // Serializes the payload of a PointerWrapper. template
inline void SerializeObject(const PointerWrapper
& pointer, MessageWriter* writer, void*& buffer) { SerializeObject(pointer.Dereference(), writer, buffer); } // Serializes the payload of file descriptor types. template
inline void SerializeObject(const FileHandle
& fd, MessageWriter* writer, void*& buffer) { SerializeType(fd, buffer); const Status
status = writer->GetOutputResourceMapper()->PushFileHandle(fd); FileReference value = status ? status.get() : -status.error(); SerializeRaw(value, buffer); } // Serializes the payload of channel handle types. template
inline void SerializeObject(const ChannelHandle
& handle, MessageWriter* writer, void*& buffer) { SerializeType(handle, buffer); const Status
status = writer->GetOutputResourceMapper()->PushChannelHandle(handle); ChannelReference value = status ? status.get() : -status.error(); SerializeRaw(value, buffer); } // Serializes the payload of BufferWrapper types. template
inline void SerializeObject(const BufferWrapper
>& b, MessageWriter* /*writer*/, void*& buffer) { const auto value_type_size = sizeof(typename BufferWrapper
>::value_type); SerializeType(b, buffer); WriteRawData(buffer, b.data(), b.size() * value_type_size); } template
inline void SerializeObject(const BufferWrapper
& b, MessageWriter* /*writer*/, void*& buffer) { const auto value_type_size = sizeof(typename BufferWrapper
::value_type); SerializeType(b, buffer); WriteRawData(buffer, b.data(), b.size() * value_type_size); } // Serializes the payload of string types. template
inline void SerializeString(const StringType& s, void*& buffer) { const auto value_type_size = sizeof(typename StringType::value_type); SerializeType(s, buffer); WriteRawData(buffer, s.data(), s.length() * value_type_size); } // Overload of SerializeObject() for std::string and StringWrapper. These types // are interchangeable and must serialize to the same format. inline void SerializeObject(const std::string& s, MessageWriter* /*writer*/, void*& buffer) { SerializeString(s, buffer); } template
inline void SerializeObject(const StringWrapper
& s, MessageWriter* /*writer*/, void*& buffer) { SerializeString(s, buffer); } // Serializes the payload of array types. template
inline void SerializeArray(const ArrayType& v, MessageWriter* writer, void*& buffer) { SerializeType(v, buffer); for (const auto& element : v) SerializeObject(element, writer, buffer); } // Serializes the payload for map types. template
inline void SerializeMap(const MapType& v, MessageWriter* writer, void*& buffer) { SerializeType(v, buffer); for (const auto& element : v) { SerializeObject(element.first, writer, buffer); SerializeObject(element.second, writer, buffer); } } // Overload of SerializeObject() for std::vector and ArrayWrapper types. These // types are interchangeable and must serialize to the same format. template
inline void SerializeObject(const std::vector
& v, MessageWriter* writer, void*& buffer) { SerializeArray(v, writer, buffer); } template
inline void SerializeObject(const ArrayWrapper
& v, MessageWriter* writer, void*& buffer) { SerializeArray(v, writer, buffer); } // Overload of SerializeObject() for std::array types. These types serialize to // the same format at std::vector and ArrayWrapper and are interchangeable in // certain situations. template
inline void SerializeObject(const std::array
& v, MessageWriter* writer, void*& buffer) { SerializeArray(v, writer, buffer); } // Overload of SerializeObject() for std::map types. template
inline void SerializeObject(const std::map
& v, MessageWriter* writer, void*& buffer) { SerializeMap(v, writer, buffer); } // Overload of SerializeObject() for std::unordered_map types. template
inline void SerializeObject( const std::unordered_map
& v, MessageWriter* writer, void*& buffer) { SerializeMap(v, writer, buffer); } // Overload of SerializeObject() for std:pair types. template
inline void SerializeObject(const std::pair
& pair, MessageWriter* writer, void*& buffer) { SerializeType(pair, buffer); SerializeObject(pair.first, writer, buffer); SerializeObject(pair.second, writer, buffer); } // Stops template recursion when the last tuple element is reached. template
inline void SerializeTuple(const std::tuple
&, MessageWriter*, void*&, Index<0>) {} // Serializes each element of a tuple recursively. template
inline void SerializeTuple(const std::tuple
& tuple, MessageWriter* writer, void*& buffer, Index
) { SerializeTuple(tuple, writer, buffer, Index
()); SerializeObject(std::get
(tuple), writer, buffer); } // Overload of SerializeObject() for tuple types. template
inline void SerializeObject(const std::tuple
& tuple, MessageWriter* writer, void*& buffer) { SerializeType(tuple, buffer); SerializeTuple(tuple, writer, buffer, Index
()); } // Stops template recursion when the last member pointer is reached. template
inline void SerializeMember(const T&, MessageWriter*, void*&, Index<0>) {} // Serializes each member pointer recursively. template
inline void SerializeMember(const T& object, MessageWriter* writer, void*& buffer, Index
) { SerializeMember
(object, writer, buffer, Index
()); SerializeObject(Members::template At
::Resolve(object), writer, buffer); } // Serializes the members of a type using the given SerializableMembersType // type. template
inline void SerializeMembers(const T& object, MessageWriter* writer, void*& buffer) { SerializeMember
(object, writer, buffer, Index
()); } // Top level serialization function that replaces the buffer's contents. template
inline void Serialize(const T& object, MessageWriter* writer) { PDX_TRACE_NAME("Serialize"); const std::size_t size = GetSerializedSize(object); // Reserve the space needed for the object(s). void* buffer = writer->GetNextWriteBufferSection(size); SerializeObject(object, writer, buffer); } /////////////////////////////////////////////////////////////////////////////// // Object Deserialization // /////////////////////////////////////////////////////////////////////////////// inline ErrorType ReadRawDataFromNextSection(void* dest, MessageReader* reader, const void*& start, const void*& end, size_t size) { while (AdvancePointer(start, size) > end) { auto remaining_size = PointerDistance(end, start); if (remaining_size > 0) { memcpy(dest, start, remaining_size); dest = AdvancePointer(dest, remaining_size); size -= remaining_size; } reader->ConsumeReadBufferSectionData(AdvancePointer(start, remaining_size)); std::tie(start, end) = reader->GetNextReadBufferSection(); if (start == end) return ErrorCode::INSUFFICIENT_BUFFER; } memcpy(dest, start, size); start = AdvancePointer(start, size); return ErrorCode::NO_ERROR; } inline ErrorType ReadRawData(void* dest, MessageReader* /*reader*/, const void*& start, const void*& end, size_t size) { if (PDX_UNLIKELY(AdvancePointer(start, size) > end)) { // TODO(avakulenko): Enabling reading from next sections of input buffer // (using ReadRawDataFromNextSection) screws up clang compiler optimizations // (probably inefficient inlining) making the whole deserialization // code path about twice as slow. Investigate and enable more generic // deserialization code, but right now we don't really need/support this // scenario, so I keep this commented out for the time being... // return ReadRawDataFromNextSection(dest, reader, start, end, size); return ErrorCode::INSUFFICIENT_BUFFER; } memcpy(dest, start, size); start = AdvancePointer(start, size); return ErrorCode::NO_ERROR; } // Deserializes a primitive object from raw bytes. template
::value>::type> inline ErrorType DeserializeRaw(T* value, MessageReader* reader, const void*& start, const void*& end) { return ReadRawData(value, reader, start, end, sizeof(T)); } // Utility to deserialize POD types when the serialized type is different // (smaller) than the target real type. This happens when values are serialized // into more compact encodings. template
ErrorType DeserializeValue(RealType* real_value, MessageReader* reader, const void*& start, const void*& end) { SerializedType serialized_value; if (const auto error = DeserializeRaw(&serialized_value, reader, start, end)) { return error; } else { *real_value = serialized_value; return ErrorCode::NO_ERROR; } } inline ErrorType DeserializeEncoding(EncodingType* encoding, MessageReader* reader, const void*& start, const void*& end) { return DeserializeRaw(encoding, reader, start, end); } // Overload to deserialize bool type. inline ErrorType DeserializeObject(bool* value, MessageReader* reader, const void*& start, const void*& end) { EncodingType encoding; if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { return error; } else if (IsBoolEncoding(encoding)) { *value = (encoding == ENCODING_TYPE_TRUE); return ErrorCode::NO_ERROR; } else { return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_BOOL, encoding); } } // Specializations to deserialize float and double types. inline ErrorType DeserializeObject(float* value, MessageReader* reader, const void*& start, const void*& end) { EncodingType encoding; if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { return error; } else if (IsFloat32Encoding(encoding)) { return DeserializeValue
(value, reader, start, end); } else { return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_FLOAT, encoding); } } inline ErrorType DeserializeObject(double* value, MessageReader* reader, const void*& start, const void*& end) { EncodingType encoding; if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { return error; } else if (IsFloat32Encoding(encoding)) { return DeserializeValue
(value, reader, start, end); } else if (IsFloat64Encoding(encoding)) { return DeserializeValue
(value, reader, start, end); } else { return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_FLOAT, encoding); } } // Specializations to deserialize standard integer types. inline ErrorType DeserializeObject(char* value, MessageReader* reader, const void*& start, const void*& end) { EncodingType encoding; if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { return error; } else if (IsUnsignedFixintEncoding(encoding)) { *value = static_cast
(encoding); return ErrorCode::NO_ERROR; } else if (IsUInt8Encoding(encoding)) { return DeserializeValue
(value, reader, start, end); } else { return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_UINT, encoding); } } inline ErrorType DeserializeObject(std::int8_t* value, MessageReader* reader, const void*& start, const void*& end) { EncodingType encoding; if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { return error; } else if (IsFixintEncoding(encoding)) { *value = static_cast
(encoding); return ErrorCode::NO_ERROR; } else if (IsInt8Encoding(encoding)) { return DeserializeValue
(value, reader, start, end); } else { return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_INT, encoding); } } inline ErrorType DeserializeObject(std::uint8_t* value, MessageReader* reader, const void*& start, const void*& end) { EncodingType encoding; if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { return error; } else if (IsUnsignedFixintEncoding(encoding)) { *value = encoding; return ErrorCode::NO_ERROR; } else if (IsUInt8Encoding(encoding)) { return DeserializeValue
(value, reader, start, end); } else { return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_UINT, encoding); } } inline ErrorType DeserializeObject(std::int16_t* value, MessageReader* reader, const void*& start, const void*& end) { EncodingType encoding; if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { return error; } else if (IsFixintEncoding(encoding)) { *value = static_cast
(encoding); return ErrorCode::NO_ERROR; } else if (IsInt8Encoding(encoding)) { return DeserializeValue
(value, reader, start, end); } else if (IsInt16Encoding(encoding)) { return DeserializeValue
(value, reader, start, end); } else { return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_INT, encoding); } } inline ErrorType DeserializeObject(std::uint16_t* value, MessageReader* reader, const void*& start, const void*& end) { EncodingType encoding; if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { return error; } else if (IsUnsignedFixintEncoding(encoding)) { *value = encoding; return ErrorCode::NO_ERROR; } else if (IsUInt8Encoding(encoding)) { return DeserializeValue
(value, reader, start, end); } else if (IsUInt16Encoding(encoding)) { return DeserializeValue
(value, reader, start, end); } else { return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_UINT, encoding); } } inline ErrorType DeserializeObject(std::int32_t* value, MessageReader* reader, const void*& start, const void*& end) { EncodingType encoding; if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { return error; } else if (IsFixintEncoding(encoding)) { *value = static_cast
(encoding); return ErrorCode::NO_ERROR; } else if (IsInt8Encoding(encoding)) { return DeserializeValue
(value, reader, start, end); } else if (IsInt16Encoding(encoding)) { return DeserializeValue
(value, reader, start, end); } else if (IsInt32Encoding(encoding)) { return DeserializeValue
(value, reader, start, end); } else { return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_INT, encoding); } } inline ErrorType DeserializeObject(std::uint32_t* value, MessageReader* reader, const void*& start, const void*& end) { EncodingType encoding; if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) { return error; } else if (IsUnsignedFixintEncoding(encoding)) { *value = encoding; return ErrorCode::NO_ERROR; } else if (IsUInt8Encoding(encoding)) { return DeserializeValue