2001 lines
76 KiB
C++
2001 lines
76 KiB
C++
#ifndef ANDROID_PDX_RPC_SERIALIZATION_H_
|
|
#define ANDROID_PDX_RPC_SERIALIZATION_H_
|
|
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <iterator>
|
|
#include <map>
|
|
#include <numeric>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <type_traits>
|
|
#include <unordered_map>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include <pdx/channel_handle.h>
|
|
#include <pdx/file_handle.h>
|
|
#include <pdx/message_reader.h>
|
|
#include <pdx/message_writer.h>
|
|
#include <pdx/trace.h>
|
|
#include <pdx/utility.h>
|
|
|
|
#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 <std::size_t N>
|
|
struct Index {};
|
|
|
|
// Forward declaration of traits type to access types with a SerializedMembers
|
|
// member type.
|
|
template <typename T>
|
|
class SerializableTraits;
|
|
|
|
template <typename T, typename... MemberPointers>
|
|
struct SerializableMembersType;
|
|
|
|
// Utility to deduce the template type from a derived type.
|
|
template <template <typename...> class TT, typename... Ts>
|
|
std::true_type DeduceTemplateType(const TT<Ts...>*);
|
|
template <template <typename...> class TT>
|
|
std::false_type DeduceTemplateType(...);
|
|
|
|
// Utility determining whether template type TT<...> is a base of type T.
|
|
template <template <typename...> class TT, typename T>
|
|
using IsTemplateBaseOf = decltype(DeduceTemplateType<TT>(std::declval<T*>()));
|
|
|
|
// Utility type for SFINAE in HasHasSerializableMembers.
|
|
template <typename... Ts>
|
|
using TrySerializableMembersType = void;
|
|
|
|
// Determines whether type T has a member type named SerializableMembers of
|
|
// template type SerializableMembersType.
|
|
template <typename, typename = void>
|
|
struct HasSerializableMembers : std::false_type {};
|
|
template <typename T>
|
|
struct HasSerializableMembers<
|
|
T, TrySerializableMembersType<typename T::SerializableMembers>>
|
|
: std::integral_constant<
|
|
bool, IsTemplateBaseOf<SerializableMembersType,
|
|
typename T::SerializableMembers>::value> {};
|
|
|
|
// Utility to simplify overload enable expressions for types with correctly
|
|
// defined SerializableMembers.
|
|
template <typename T>
|
|
using EnableIfHasSerializableMembers =
|
|
typename std::enable_if<HasSerializableMembers<T>::value>::type;
|
|
|
|
// Utility to simplify overload enable expressions for enum types.
|
|
template <typename T, typename ReturnType = void>
|
|
using EnableIfEnum =
|
|
typename std::enable_if<std::is_enum<T>::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(google-explicit-constructor)
|
|
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; }
|
|
|
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
|
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;
|
|
}
|
|
|
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
|
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<int>(encoding_class())
|
|
<< ", " << static_cast<int>(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 <typename T>
|
|
inline EnableIfEnum<T, std::size_t> GetSerializedSize(T v) {
|
|
return GetSerializedSize(static_cast<std::underlying_type_t<T>>(v));
|
|
}
|
|
|
|
// Forward declaration for nested definitions.
|
|
inline std::size_t GetSerializedSize(const EmptyVariant&);
|
|
template <typename... Types>
|
|
inline std::size_t GetSerializedSize(const Variant<Types...>&);
|
|
template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>>
|
|
inline constexpr std::size_t GetSerializedSize(const T&);
|
|
template <typename T>
|
|
inline constexpr std::size_t GetSerializedSize(const PointerWrapper<T>&);
|
|
inline constexpr std::size_t GetSerializedSize(const std::string&);
|
|
template <typename T>
|
|
inline constexpr std::size_t GetSerializedSize(const StringWrapper<T>&);
|
|
template <typename T>
|
|
inline constexpr std::size_t GetSerializedSize(const BufferWrapper<T>&);
|
|
template <FileHandleMode Mode>
|
|
inline constexpr std::size_t GetSerializedSize(const FileHandle<Mode>&);
|
|
template <ChannelHandleMode Mode>
|
|
inline constexpr std::size_t GetSerializedSize(const ChannelHandle<Mode>&);
|
|
template <typename T, typename Allocator>
|
|
inline std::size_t GetSerializedSize(const std::vector<T, Allocator>& v);
|
|
template <typename Key, typename T, typename Compare, typename Allocator>
|
|
inline std::size_t GetSerializedSize(
|
|
const std::map<Key, T, Compare, Allocator>& m);
|
|
template <typename Key, typename T, typename Hash, typename KeyEqual,
|
|
typename Allocator>
|
|
inline std::size_t GetSerializedSize(
|
|
const std::unordered_map<Key, T, Hash, KeyEqual, Allocator>&);
|
|
template <typename T>
|
|
inline std::size_t GetSerializedSize(const ArrayWrapper<T>&);
|
|
template <typename T, std::size_t Size>
|
|
inline std::size_t GetSerializedSize(const std::array<T, Size>& v);
|
|
template <typename T, typename U>
|
|
inline std::size_t GetSerializedSize(const std::pair<T, U>& p);
|
|
template <typename... T>
|
|
inline std::size_t GetSerializedSize(const std::tuple<T...>& tuple);
|
|
|
|
// Overload for empty variant type.
|
|
inline std::size_t GetSerializedSize(const EmptyVariant& empty) {
|
|
return GetEncodingSize(EncodeType(empty));
|
|
}
|
|
|
|
// Overload for Variant types.
|
|
template <typename... Types>
|
|
inline std::size_t GetSerializedSize(const Variant<Types...>& variant) {
|
|
return GetEncodingSize(EncodeType(variant)) +
|
|
GetSerializedSize(variant.index()) +
|
|
variant.Visit(
|
|
[](const auto& value) { return GetSerializedSize(value); });
|
|
}
|
|
|
|
// Overload for structs/classes with SerializableMembers defined.
|
|
template <typename T, typename Enabled>
|
|
inline constexpr std::size_t GetSerializedSize(const T& value) {
|
|
return SerializableTraits<T>::GetSerializedSize(value);
|
|
}
|
|
|
|
// Overload for PointerWrapper.
|
|
template <typename T>
|
|
inline constexpr std::size_t GetSerializedSize(const PointerWrapper<T>& 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 <typename T>
|
|
inline constexpr std::size_t GetSerializedSize(const StringWrapper<T>& s) {
|
|
return GetEncodingSize(EncodeType(s)) +
|
|
s.length() * sizeof(typename StringWrapper<T>::value_type);
|
|
}
|
|
|
|
// Overload for BufferWrapper types.
|
|
template <typename T>
|
|
inline constexpr std::size_t GetSerializedSize(const BufferWrapper<T>& b) {
|
|
return GetEncodingSize(EncodeType(b)) +
|
|
b.size() * sizeof(typename BufferWrapper<T>::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 <FileHandleMode Mode>
|
|
inline constexpr std::size_t GetSerializedSize(const FileHandle<Mode>& 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 <ChannelHandleMode Mode>
|
|
inline constexpr std::size_t GetSerializedSize(
|
|
const ChannelHandle<Mode>& channel_handle) {
|
|
return GetEncodingSize(EncodeType(channel_handle)) + sizeof(std::int32_t);
|
|
}
|
|
|
|
// Overload for standard vector types.
|
|
template <typename T, typename Allocator>
|
|
inline std::size_t GetSerializedSize(const std::vector<T, Allocator>& 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 <typename Key, typename T, typename Compare, typename Allocator>
|
|
inline std::size_t GetSerializedSize(
|
|
const std::map<Key, T, Compare, Allocator>& v) {
|
|
return std::accumulate(
|
|
v.begin(), v.end(), GetEncodingSize(EncodeType(v)),
|
|
[](const std::size_t& sum, const std::pair<Key, T>& object) {
|
|
return sum + GetSerializedSize(object.first) +
|
|
GetSerializedSize(object.second);
|
|
});
|
|
}
|
|
|
|
// Overload for standard unordered_map types.
|
|
template <typename Key, typename T, typename Hash, typename KeyEqual,
|
|
typename Allocator>
|
|
inline std::size_t GetSerializedSize(
|
|
const std::unordered_map<Key, T, Hash, KeyEqual, Allocator>& v) {
|
|
return std::accumulate(
|
|
v.begin(), v.end(), GetEncodingSize(EncodeType(v)),
|
|
[](const std::size_t& sum, const std::pair<Key, T>& object) {
|
|
return sum + GetSerializedSize(object.first) +
|
|
GetSerializedSize(object.second);
|
|
});
|
|
}
|
|
|
|
// Overload for ArrayWrapper types.
|
|
template <typename T>
|
|
inline std::size_t GetSerializedSize(const ArrayWrapper<T>& 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 <typename T, std::size_t Size>
|
|
inline std::size_t GetSerializedSize(const std::array<T, Size>& 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 <typename T, typename U>
|
|
inline std::size_t GetSerializedSize(const std::pair<T, U>& p) {
|
|
return GetEncodingSize(EncodeType(p)) + GetSerializedSize(p.first) +
|
|
GetSerializedSize(p.second);
|
|
}
|
|
|
|
// Stops template recursion when the last tuple element is reached.
|
|
template <typename... T>
|
|
inline std::size_t GetTupleSize(const std::tuple<T...>&, Index<0>) {
|
|
return 0;
|
|
}
|
|
|
|
// Gets the size of each element in a tuple recursively.
|
|
template <typename... T, std::size_t index>
|
|
inline std::size_t GetTupleSize(const std::tuple<T...>& tuple, Index<index>) {
|
|
return GetTupleSize(tuple, Index<index - 1>()) +
|
|
GetSerializedSize(std::get<index - 1>(tuple));
|
|
}
|
|
|
|
// Overload for tuple types. Gets the size of the tuple, recursing
|
|
// through the elements.
|
|
template <typename... T>
|
|
inline std::size_t GetSerializedSize(const std::tuple<T...>& tuple) {
|
|
return GetEncodingSize(EncodeType(tuple)) +
|
|
GetTupleSize(tuple, Index<sizeof...(T)>());
|
|
}
|
|
|
|
// Stops template recursion when the last member of a Serializable
|
|
// type is reached.
|
|
template <typename Members, typename T>
|
|
inline std::size_t GetMemberSize(const T&, Index<0>) {
|
|
return 0;
|
|
}
|
|
|
|
// Gets the size of each member of a Serializable type recursively.
|
|
template <typename Members, typename T, std::size_t index>
|
|
inline std::size_t GetMemberSize(const T& object, Index<index>) {
|
|
return GetMemberSize<Members>(object, Index<index - 1>()) +
|
|
GetSerializedSize(Members::template At<index - 1>::Resolve(object));
|
|
}
|
|
|
|
// Gets the size of a type using the given SerializableMembersType
|
|
// type.
|
|
template <typename Members, typename T>
|
|
inline std::size_t GetMembersSize(const T& object) {
|
|
return GetMemberSize<Members>(object, Index<Members::MemberCount>());
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// 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<uint8_t*>(dest) + size;
|
|
}
|
|
|
|
// Serializes a primitive array into a raw byte string.
|
|
template <typename T,
|
|
typename = typename std::enable_if<std::is_pod<T>::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 <FileHandleMode Mode>
|
|
inline void SerializeType(const FileHandle<Mode>& value, void*& buffer) {
|
|
SerializeExtEncoding(EncodeType(value), ENCODING_EXT_TYPE_FILE_DESCRIPTOR, 2,
|
|
buffer);
|
|
}
|
|
|
|
// Serializes the type code for channel handle types.
|
|
template <ChannelHandleMode Mode>
|
|
inline void SerializeType(const ChannelHandle<Mode>& handle, void*& buffer) {
|
|
SerializeExtEncoding(EncodeType(handle), ENCODING_EXT_TYPE_CHANNEL_HANDLE, 4,
|
|
buffer);
|
|
}
|
|
|
|
// Serializes type code for variant types.
|
|
template <typename... Types>
|
|
inline void SerializeType(const Variant<Types...>& value, void*& buffer) {
|
|
const EncodingType encoding = EncodeType(value);
|
|
SerializeEncoding(encoding, buffer);
|
|
}
|
|
|
|
// Serializes the type code for string types.
|
|
template <typename StringType>
|
|
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 <typename T>
|
|
inline void SerializeType(const StringWrapper<T>& 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 <typename T>
|
|
inline void SerializeType(const BufferWrapper<T>& value, void*& buffer) {
|
|
const EncodingType encoding = EncodeType(value);
|
|
SerializeBinEncoding(
|
|
encoding, value.size() * sizeof(typename BufferWrapper<T>::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 <typename ArrayType>
|
|
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 <typename MapType>
|
|
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 <typename T, typename Allocator>
|
|
inline void SerializeType(const std::vector<T, Allocator>& value,
|
|
void*& buffer) {
|
|
SerializeArrayType(value, value.size(), buffer);
|
|
}
|
|
template <typename T>
|
|
inline void SerializeType(const ArrayWrapper<T>& 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 <typename T, std::size_t Size>
|
|
inline void SerializeType(const std::array<T, Size>& value, void*& buffer) {
|
|
SerializeArrayType(value, Size, buffer);
|
|
}
|
|
|
|
// Serializes the type code for std::map types.
|
|
template <typename Key, typename T, typename Compare, typename Allocator>
|
|
inline void SerializeType(const std::map<Key, T, Compare, Allocator>& value,
|
|
void*& buffer) {
|
|
SerializeMapType(value, value.size(), buffer);
|
|
}
|
|
|
|
// Serializes the type code for std::unordered_map types.
|
|
template <typename Key, typename T, typename Hash, typename KeyEqual,
|
|
typename Allocator>
|
|
inline void SerializeType(
|
|
const std::unordered_map<Key, T, Hash, KeyEqual, Allocator>& value,
|
|
void*& buffer) {
|
|
SerializeMapType(value, value.size(), buffer);
|
|
}
|
|
|
|
// Serializes the type code for std::pair types.
|
|
template <typename T, typename U>
|
|
inline void SerializeType(const std::pair<T, U>& value, void*& buffer) {
|
|
SerializeArrayType(value, 2, buffer);
|
|
}
|
|
|
|
// Serializes the type code for std::tuple types.
|
|
template <typename... T>
|
|
inline void SerializeType(const std::tuple<T...>& 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 <typename T>
|
|
inline EnableIfEnum<T> SerializeObject(const T& value, MessageWriter* writer,
|
|
void*& buffer) {
|
|
SerializeObject(static_cast<std::underlying_type_t<T>>(value), writer,
|
|
buffer);
|
|
}
|
|
|
|
// Forward declaration for nested definitions.
|
|
inline void SerializeObject(const EmptyVariant&, MessageWriter*, void*&);
|
|
template <typename... Types>
|
|
inline void SerializeObject(const Variant<Types...>&, MessageWriter*, void*&);
|
|
template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>>
|
|
inline void SerializeObject(const T&, MessageWriter*, void*&);
|
|
template <typename T>
|
|
inline void SerializeObject(const PointerWrapper<T>&, MessageWriter*, void*&);
|
|
template <FileHandleMode Mode>
|
|
inline void SerializeObject(const FileHandle<Mode>&, MessageWriter*, void*&);
|
|
template <ChannelHandleMode Mode>
|
|
inline void SerializeObject(const ChannelHandle<Mode>&, MessageWriter*, void*&);
|
|
template <typename T, typename Allocator>
|
|
inline void SerializeObject(const BufferWrapper<std::vector<T, Allocator>>&, MessageWriter*, void*&);
|
|
template <typename T>
|
|
inline void SerializeObject(const BufferWrapper<T*>&, MessageWriter*, void*&);
|
|
inline void SerializeObject(const std::string&, MessageWriter*, void*&);
|
|
template <typename T>
|
|
inline void SerializeObject(const StringWrapper<T>&, MessageWriter*, void*&);
|
|
template <typename T, typename Allocator>
|
|
inline void SerializeObject(const std::vector<T, Allocator>&, MessageWriter*, void*&);
|
|
template <typename T>
|
|
inline void SerializeObject(const ArrayWrapper<T>&, MessageWriter*, void*&);
|
|
template <typename T, std::size_t Size>
|
|
inline void SerializeObject(const std::array<T, Size>&, MessageWriter*, void*&);
|
|
template <typename Key, typename T, typename Compare, typename Allocator>
|
|
inline void SerializeObject(const std::map<Key, T, Compare, Allocator>&, MessageWriter*, void*&);
|
|
template <typename Key, typename T, typename Hash, typename KeyEqual,
|
|
typename Allocator>
|
|
inline void SerializeObject(
|
|
const std::unordered_map<Key, T, Hash, KeyEqual, Allocator>&, MessageWriter*, void*&);
|
|
template <typename T, typename U>
|
|
inline void SerializeObject(const std::pair<T, U>&, MessageWriter*, void*&);
|
|
template <typename... T>
|
|
inline void SerializeObject(const std::tuple<T...>&, 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 <typename... Types>
|
|
inline void SerializeObject(const Variant<Types...>& 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 <typename T, typename Enabled>
|
|
inline void SerializeObject(const T& value, MessageWriter* writer,
|
|
void*& buffer) {
|
|
SerializableTraits<T>::SerializeObject(value, writer, buffer);
|
|
}
|
|
|
|
// Serializes the payload of a PointerWrapper.
|
|
template <typename T>
|
|
inline void SerializeObject(const PointerWrapper<T>& pointer,
|
|
MessageWriter* writer, void*& buffer) {
|
|
SerializeObject(pointer.Dereference(), writer, buffer);
|
|
}
|
|
|
|
// Serializes the payload of file descriptor types.
|
|
template <FileHandleMode Mode>
|
|
inline void SerializeObject(const FileHandle<Mode>& fd, MessageWriter* writer,
|
|
void*& buffer) {
|
|
SerializeType(fd, buffer);
|
|
const Status<FileReference> status =
|
|
writer->GetOutputResourceMapper()->PushFileHandle(fd);
|
|
FileReference value = status ? status.get() : -status.error();
|
|
SerializeRaw(value, buffer);
|
|
}
|
|
|
|
// Serializes the payload of channel handle types.
|
|
template <ChannelHandleMode Mode>
|
|
inline void SerializeObject(const ChannelHandle<Mode>& handle,
|
|
MessageWriter* writer, void*& buffer) {
|
|
SerializeType(handle, buffer);
|
|
const Status<ChannelReference> status =
|
|
writer->GetOutputResourceMapper()->PushChannelHandle(handle);
|
|
ChannelReference value = status ? status.get() : -status.error();
|
|
SerializeRaw(value, buffer);
|
|
}
|
|
|
|
// Serializes the payload of BufferWrapper types.
|
|
template <typename T, typename Allocator>
|
|
inline void SerializeObject(const BufferWrapper<std::vector<T, Allocator>>& b,
|
|
MessageWriter* /*writer*/, void*& buffer) {
|
|
const auto value_type_size =
|
|
sizeof(typename BufferWrapper<std::vector<T, Allocator>>::value_type);
|
|
SerializeType(b, buffer);
|
|
WriteRawData(buffer, b.data(), b.size() * value_type_size);
|
|
}
|
|
template <typename T>
|
|
inline void SerializeObject(const BufferWrapper<T*>& b,
|
|
MessageWriter* /*writer*/, void*& buffer) {
|
|
const auto value_type_size = sizeof(typename BufferWrapper<T*>::value_type);
|
|
SerializeType(b, buffer);
|
|
WriteRawData(buffer, b.data(), b.size() * value_type_size);
|
|
}
|
|
|
|
// Serializes the payload of string types.
|
|
template <typename StringType>
|
|
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 <typename T>
|
|
inline void SerializeObject(const StringWrapper<T>& s,
|
|
MessageWriter* /*writer*/, void*& buffer) {
|
|
SerializeString(s, buffer);
|
|
}
|
|
|
|
// Serializes the payload of array types.
|
|
template <typename ArrayType>
|
|
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 <typename MapType>
|
|
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 <typename T, typename Allocator>
|
|
inline void SerializeObject(const std::vector<T, Allocator>& v,
|
|
MessageWriter* writer, void*& buffer) {
|
|
SerializeArray(v, writer, buffer);
|
|
}
|
|
template <typename T>
|
|
inline void SerializeObject(const ArrayWrapper<T>& 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 <typename T, std::size_t Size>
|
|
inline void SerializeObject(const std::array<T, Size>& v, MessageWriter* writer,
|
|
void*& buffer) {
|
|
SerializeArray(v, writer, buffer);
|
|
}
|
|
|
|
// Overload of SerializeObject() for std::map types.
|
|
template <typename Key, typename T, typename Compare, typename Allocator>
|
|
inline void SerializeObject(const std::map<Key, T, Compare, Allocator>& v,
|
|
MessageWriter* writer, void*& buffer) {
|
|
SerializeMap(v, writer, buffer);
|
|
}
|
|
|
|
// Overload of SerializeObject() for std::unordered_map types.
|
|
template <typename Key, typename T, typename Hash, typename KeyEqual,
|
|
typename Allocator>
|
|
inline void SerializeObject(
|
|
const std::unordered_map<Key, T, Hash, KeyEqual, Allocator>& v,
|
|
MessageWriter* writer, void*& buffer) {
|
|
SerializeMap(v, writer, buffer);
|
|
}
|
|
|
|
// Overload of SerializeObject() for std:pair types.
|
|
template <typename T, typename U>
|
|
inline void SerializeObject(const std::pair<T, U>& 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 <typename... T>
|
|
inline void SerializeTuple(const std::tuple<T...>&, MessageWriter*, void*&,
|
|
Index<0>) {}
|
|
|
|
// Serializes each element of a tuple recursively.
|
|
template <typename... T, std::size_t index>
|
|
inline void SerializeTuple(const std::tuple<T...>& tuple, MessageWriter* writer,
|
|
void*& buffer, Index<index>) {
|
|
SerializeTuple(tuple, writer, buffer, Index<index - 1>());
|
|
SerializeObject(std::get<index - 1>(tuple), writer, buffer);
|
|
}
|
|
|
|
// Overload of SerializeObject() for tuple types.
|
|
template <typename... T>
|
|
inline void SerializeObject(const std::tuple<T...>& tuple,
|
|
MessageWriter* writer, void*& buffer) {
|
|
SerializeType(tuple, buffer);
|
|
SerializeTuple(tuple, writer, buffer, Index<sizeof...(T)>());
|
|
}
|
|
|
|
// Stops template recursion when the last member pointer is reached.
|
|
template <typename Members, typename T>
|
|
inline void SerializeMember(const T&, MessageWriter*, void*&, Index<0>) {}
|
|
|
|
// Serializes each member pointer recursively.
|
|
template <typename Members, typename T, std::size_t index>
|
|
inline void SerializeMember(const T& object, MessageWriter* writer,
|
|
void*& buffer, Index<index>) {
|
|
SerializeMember<Members>(object, writer, buffer, Index<index - 1>());
|
|
SerializeObject(Members::template At<index - 1>::Resolve(object), writer,
|
|
buffer);
|
|
}
|
|
|
|
// Serializes the members of a type using the given SerializableMembersType
|
|
// type.
|
|
template <typename Members, typename T>
|
|
inline void SerializeMembers(const T& object, MessageWriter* writer,
|
|
void*& buffer) {
|
|
SerializeMember<Members>(object, writer, buffer,
|
|
Index<Members::MemberCount>());
|
|
}
|
|
|
|
// Top level serialization function that replaces the buffer's contents.
|
|
template <typename T>
|
|
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 <typename T,
|
|
typename = typename std::enable_if<std::is_pod<T>::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 <typename SerializedType, typename RealType>
|
|
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<float>(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<float>(value, reader, start, end);
|
|
} else if (IsFloat64Encoding(encoding)) {
|
|
return DeserializeValue<double>(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<char>(encoding);
|
|
return ErrorCode::NO_ERROR;
|
|
} else if (IsUInt8Encoding(encoding)) {
|
|
return DeserializeValue<char>(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<std::int8_t>(encoding);
|
|
return ErrorCode::NO_ERROR;
|
|
} else if (IsInt8Encoding(encoding)) {
|
|
return DeserializeValue<std::int8_t>(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<std::uint8_t>(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<std::int8_t>(encoding);
|
|
return ErrorCode::NO_ERROR;
|
|
} else if (IsInt8Encoding(encoding)) {
|
|
return DeserializeValue<std::int8_t>(value, reader, start, end);
|
|
} else if (IsInt16Encoding(encoding)) {
|
|
return DeserializeValue<std::int16_t>(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<std::uint8_t>(value, reader, start, end);
|
|
} else if (IsUInt16Encoding(encoding)) {
|
|
return DeserializeValue<std::uint16_t>(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<std::int8_t>(encoding);
|
|
return ErrorCode::NO_ERROR;
|
|
} else if (IsInt8Encoding(encoding)) {
|
|
return DeserializeValue<std::int8_t>(value, reader, start, end);
|
|
} else if (IsInt16Encoding(encoding)) {
|
|
return DeserializeValue<std::int16_t>(value, reader, start, end);
|
|
} else if (IsInt32Encoding(encoding)) {
|
|
return DeserializeValue<std::int32_t>(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<std::uint8_t>(value, reader, start, end);
|
|
} else if (IsUInt16Encoding(encoding)) {
|
|
return DeserializeValue<std::uint16_t>(value, reader, start, end);
|
|
} else if (IsUInt32Encoding(encoding)) {
|
|
return DeserializeValue<std::uint32_t>(value, reader, start, end);
|
|
} else {
|
|
return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_UINT,
|
|
encoding);
|
|
}
|
|
}
|
|
|
|
inline ErrorType DeserializeObject(std::int64_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<std::int8_t>(encoding);
|
|
return ErrorCode::NO_ERROR;
|
|
} else if (IsInt8Encoding(encoding)) {
|
|
return DeserializeValue<std::int8_t>(value, reader, start, end);
|
|
} else if (IsInt16Encoding(encoding)) {
|
|
return DeserializeValue<std::int16_t>(value, reader, start, end);
|
|
} else if (IsInt32Encoding(encoding)) {
|
|
return DeserializeValue<std::int32_t>(value, reader, start, end);
|
|
} else if (IsInt64Encoding(encoding)) {
|
|
return DeserializeValue<std::int64_t>(value, reader, start, end);
|
|
} else {
|
|
return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_INT,
|
|
encoding);
|
|
}
|
|
}
|
|
|
|
inline ErrorType DeserializeObject(std::uint64_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<std::uint8_t>(value, reader, start, end);
|
|
} else if (IsUInt16Encoding(encoding)) {
|
|
return DeserializeValue<std::uint16_t>(value, reader, start, end);
|
|
} else if (IsUInt32Encoding(encoding)) {
|
|
return DeserializeValue<std::uint32_t>(value, reader, start, end);
|
|
} else if (IsUInt64Encoding(encoding)) {
|
|
return DeserializeValue<std::uint64_t>(value, reader, start, end);
|
|
} else {
|
|
return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_UINT,
|
|
encoding);
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
inline EnableIfEnum<T, ErrorType> DeserializeObject(T* value,
|
|
MessageReader* reader,
|
|
const void*& start,
|
|
const void*& end) {
|
|
std::underlying_type_t<T> enum_value;
|
|
ErrorType error = DeserializeObject(&enum_value, reader, start, end);
|
|
if (!error)
|
|
*value = static_cast<T>(enum_value);
|
|
return error;
|
|
}
|
|
|
|
// Forward declarations for nested definitions.
|
|
template <typename T, typename Enabled = EnableIfHasSerializableMembers<T>>
|
|
inline ErrorType DeserializeObject(T*, MessageReader*, const void*&,
|
|
const void*&);
|
|
template <typename T>
|
|
inline ErrorType DeserializeObject(PointerWrapper<T>*, MessageReader*,
|
|
const void*&, const void*&);
|
|
inline ErrorType DeserializeObject(LocalHandle*, MessageReader*, const void*&,
|
|
const void*&);
|
|
inline ErrorType DeserializeObject(LocalChannelHandle*, MessageReader*,
|
|
const void*&, const void*&);
|
|
template <typename T, typename Allocator>
|
|
inline ErrorType DeserializeObject(BufferWrapper<std::vector<T, Allocator>>*,
|
|
MessageReader*, const void*&, const void*&);
|
|
template <typename T>
|
|
inline ErrorType DeserializeObject(BufferWrapper<T*>*, MessageReader*,
|
|
const void*&, const void*&);
|
|
inline ErrorType DeserializeObject(std::string*, MessageReader*, const void*&,
|
|
const void*&);
|
|
template <typename T>
|
|
inline ErrorType DeserializeObject(StringWrapper<T>*, MessageReader*,
|
|
const void*&, const void*&);
|
|
template <typename T, typename U>
|
|
inline ErrorType DeserializeObject(std::pair<T, U>*, MessageReader*,
|
|
const void*&, const void*&);
|
|
template <typename... T>
|
|
inline ErrorType DeserializeObject(std::tuple<T...>*, MessageReader*,
|
|
const void*&, const void*&);
|
|
template <typename T, typename Allocator>
|
|
inline ErrorType DeserializeObject(std::vector<T, Allocator>*, MessageReader*,
|
|
const void*&, const void*&);
|
|
template <typename Key, typename T, typename Compare, typename Allocator>
|
|
inline ErrorType DeserializeObject(std::map<Key, T, Compare, Allocator>*,
|
|
MessageReader*, const void*&, const void*&);
|
|
template <typename Key, typename T, typename Hash, typename KeyEqual,
|
|
typename Allocator>
|
|
inline ErrorType DeserializeObject(
|
|
std::unordered_map<Key, T, Hash, KeyEqual, Allocator>*, MessageReader*,
|
|
const void*&, const void*&);
|
|
template <typename T>
|
|
inline ErrorType DeserializeObject(ArrayWrapper<T>*, MessageReader*,
|
|
const void*&, const void*&);
|
|
template <typename T, std::size_t Size>
|
|
inline ErrorType DeserializeObject(std::array<T, Size>*, MessageReader*,
|
|
const void*&, const void*&);
|
|
template <typename T, typename U>
|
|
inline ErrorType DeserializeObject(std::pair<T, U>*, MessageReader*,
|
|
const void*&, const void*&);
|
|
template <typename... T>
|
|
inline ErrorType DeserializeObject(std::tuple<T...>*, MessageReader*,
|
|
const void*&, const void*&);
|
|
inline ErrorType DeserializeObject(EmptyVariant*,
|
|
MessageReader*, const void*&,
|
|
const void*&);
|
|
template <typename... Types>
|
|
inline ErrorType DeserializeObject(Variant<Types...>*,
|
|
MessageReader*, const void*&,
|
|
const void*&);
|
|
|
|
// Deserializes a Serializable type.
|
|
template <typename T, typename Enable>
|
|
inline ErrorType DeserializeObject(T* value, MessageReader* reader,
|
|
const void*& start, const void*& end) {
|
|
return SerializableTraits<T>::DeserializeObject(value, reader, start, end);
|
|
}
|
|
|
|
// Deserializes a PointerWrapper.
|
|
template <typename T>
|
|
inline ErrorType DeserializeObject(PointerWrapper<T>* pointer,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
return DeserializeObject(&pointer->Dereference(), reader, start, end);
|
|
}
|
|
|
|
// Deserializes the type code and size for extension types.
|
|
inline ErrorType DeserializeExtType(EncodingType* encoding,
|
|
EncodingExtType* type, std::size_t* size,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
if (const auto error = DeserializeEncoding(encoding, reader, start, end)) {
|
|
return error;
|
|
} else if (IsFixextEncoding(*encoding)) {
|
|
*size = GetFixextSize(*encoding);
|
|
} else if (*encoding == ENCODING_TYPE_EXT8) {
|
|
if (const auto error =
|
|
DeserializeValue<std::uint8_t>(size, reader, start, end))
|
|
return error;
|
|
} else if (*encoding == ENCODING_TYPE_EXT16) {
|
|
if (const auto error =
|
|
DeserializeValue<std::uint16_t>(size, reader, start, end))
|
|
return error;
|
|
} else if (*encoding == ENCODING_TYPE_EXT32) {
|
|
if (const auto error =
|
|
DeserializeValue<std::uint32_t>(size, reader, start, end))
|
|
return error;
|
|
} else {
|
|
return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_EXTENSION,
|
|
*encoding);
|
|
}
|
|
|
|
// The extension type code follows the encoding and size.
|
|
return DeserializeRaw(type, reader, start, end);
|
|
}
|
|
|
|
// Deserializes a file handle and performs handle space translation, if
|
|
// required.
|
|
inline ErrorType DeserializeObject(LocalHandle* value, MessageReader* reader,
|
|
const void*& start, const void*& end) {
|
|
EncodingType encoding;
|
|
EncodingExtType type;
|
|
std::size_t size;
|
|
|
|
if (const auto error =
|
|
DeserializeExtType(&encoding, &type, &size, reader, start, end)) {
|
|
return error;
|
|
} else if (size != 2) {
|
|
return ErrorType(ErrorCode::UNEXPECTED_TYPE_SIZE, ENCODING_CLASS_EXTENSION,
|
|
encoding);
|
|
} else if (type == ENCODING_EXT_TYPE_FILE_DESCRIPTOR) {
|
|
// Read the encoded file descriptor value.
|
|
FileReference ref;
|
|
if (const auto error = DeserializeRaw(&ref, reader, start, end)) {
|
|
return error;
|
|
}
|
|
|
|
return reader->GetInputResourceMapper()->GetFileHandle(ref, value)
|
|
? ErrorCode::NO_ERROR
|
|
: ErrorCode::GET_FILE_DESCRIPTOR_FAILED;
|
|
} else {
|
|
return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_EXTENSION,
|
|
encoding);
|
|
}
|
|
}
|
|
|
|
inline ErrorType DeserializeObject(LocalChannelHandle* value,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
EncodingType encoding;
|
|
EncodingExtType type;
|
|
std::size_t size;
|
|
|
|
if (const auto error =
|
|
DeserializeExtType(&encoding, &type, &size, reader, start, end)) {
|
|
return error;
|
|
} else if (size != 4) {
|
|
return ErrorType(ErrorCode::UNEXPECTED_TYPE_SIZE, ENCODING_CLASS_EXTENSION,
|
|
encoding);
|
|
} else if (type == ENCODING_EXT_TYPE_CHANNEL_HANDLE) {
|
|
// Read the encoded channel handle value.
|
|
ChannelReference ref;
|
|
if (const auto error = DeserializeRaw(&ref, reader, start, end)) {
|
|
return error;
|
|
}
|
|
return reader->GetInputResourceMapper()->GetChannelHandle(ref, value)
|
|
? ErrorCode::NO_ERROR
|
|
: ErrorCode::GET_CHANNEL_HANDLE_FAILED;
|
|
} else {
|
|
return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_EXTENSION,
|
|
encoding);
|
|
}
|
|
}
|
|
|
|
// Deserializes the type code and size for bin types.
|
|
inline ErrorType DeserializeBinType(EncodingType* encoding, std::size_t* size,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
if (const auto error = DeserializeEncoding(encoding, reader, start, end)) {
|
|
return error;
|
|
} else if (*encoding == ENCODING_TYPE_BIN8) {
|
|
return DeserializeValue<std::uint8_t>(size, reader, start, end);
|
|
} else if (*encoding == ENCODING_TYPE_BIN16) {
|
|
return DeserializeValue<std::uint16_t>(size, reader, start, end);
|
|
} else if (*encoding == ENCODING_TYPE_BIN32) {
|
|
return DeserializeValue<std::uint32_t>(size, reader, start, end);
|
|
} else {
|
|
return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_BINARY,
|
|
*encoding);
|
|
}
|
|
}
|
|
|
|
// Overload of DeserializeObject() for BufferWrapper types.
|
|
template <typename T, typename Allocator>
|
|
inline ErrorType DeserializeObject(
|
|
BufferWrapper<std::vector<T, Allocator>>* value, MessageReader* reader,
|
|
const void*& start, const void*& end) {
|
|
const auto value_type_size =
|
|
sizeof(typename BufferWrapper<std::vector<T, Allocator>>::value_type);
|
|
EncodingType encoding;
|
|
std::size_t size;
|
|
|
|
if (const auto error =
|
|
DeserializeBinType(&encoding, &size, reader, start, end))
|
|
return error;
|
|
|
|
// Try to resize the BufferWrapper to the size of the payload.
|
|
value->resize(size / value_type_size);
|
|
|
|
if (size > value->size() * value_type_size || size % value_type_size != 0) {
|
|
return ErrorCode::INSUFFICIENT_DESTINATION_SIZE;
|
|
} else if (size == 0U) {
|
|
return ErrorCode::NO_ERROR;
|
|
} else {
|
|
return ReadRawData(value->data(), reader, start, end, size);
|
|
}
|
|
}
|
|
template <typename T>
|
|
inline ErrorType DeserializeObject(BufferWrapper<T*>* value,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
const auto value_type_size = sizeof(typename BufferWrapper<T*>::value_type);
|
|
EncodingType encoding;
|
|
std::size_t size;
|
|
|
|
if (const auto error =
|
|
DeserializeBinType(&encoding, &size, reader, start, end))
|
|
return error;
|
|
|
|
// Try to resize the BufferWrapper to the size of the payload.
|
|
value->resize(size / value_type_size);
|
|
|
|
if (size > value->size() * value_type_size || size % value_type_size != 0) {
|
|
return ErrorCode::INSUFFICIENT_DESTINATION_SIZE;
|
|
} else if (size == 0U) {
|
|
return ErrorCode::NO_ERROR;
|
|
} else {
|
|
return ReadRawData(value->data(), reader, start, end, size);
|
|
}
|
|
}
|
|
|
|
// Deserializes the type code and size for string types.
|
|
inline ErrorType DeserializeStringType(EncodingType* encoding,
|
|
std::size_t* size, MessageReader* reader,
|
|
const void*& start, const void*& end) {
|
|
if (const auto error = DeserializeEncoding(encoding, reader, start, end)) {
|
|
return error;
|
|
} else if (IsFixstrEncoding(*encoding)) {
|
|
*size = GetFixstrSize(*encoding);
|
|
return ErrorCode::NO_ERROR;
|
|
} else if (*encoding == ENCODING_TYPE_STR8) {
|
|
return DeserializeValue<std::uint8_t>(size, reader, start, end);
|
|
} else if (*encoding == ENCODING_TYPE_STR16) {
|
|
return DeserializeValue<std::uint16_t>(size, reader, start, end);
|
|
} else if (*encoding == ENCODING_TYPE_STR32) {
|
|
return DeserializeValue<std::uint32_t>(size, reader, start, end);
|
|
} else {
|
|
return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_STRING,
|
|
*encoding);
|
|
}
|
|
}
|
|
|
|
// Overload of DeserializeObject() for std::string types.
|
|
inline ErrorType DeserializeObject(std::string* value, MessageReader* reader,
|
|
const void*& start, const void*& end) {
|
|
EncodingType encoding;
|
|
std::size_t size;
|
|
|
|
if (const auto error =
|
|
DeserializeStringType(&encoding, &size, reader, start, end)) {
|
|
return error;
|
|
} else if (size == 0U) {
|
|
value->clear();
|
|
return ErrorCode::NO_ERROR;
|
|
} else {
|
|
value->resize(size);
|
|
return ReadRawData(&(*value)[0], reader, start, end, size);
|
|
}
|
|
}
|
|
|
|
// Overload of DeserializeObject() for StringWrapper types.
|
|
template <typename T>
|
|
inline ErrorType DeserializeObject(StringWrapper<T>* value,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
const auto value_type_size = sizeof(typename StringWrapper<T>::value_type);
|
|
EncodingType encoding;
|
|
std::size_t size;
|
|
|
|
if (const auto error =
|
|
DeserializeStringType(&encoding, &size, reader, start, end))
|
|
return error;
|
|
|
|
// Try to resize the StringWrapper to the size of the payload
|
|
// string.
|
|
value->resize(size / value_type_size);
|
|
|
|
if (size > value->length() * value_type_size || size % value_type_size != 0) {
|
|
return ErrorCode::INSUFFICIENT_DESTINATION_SIZE;
|
|
} else if (size == 0U) {
|
|
return ErrorCode::NO_ERROR;
|
|
} else {
|
|
return ReadRawData(value->data(), reader, start, end, size);
|
|
}
|
|
}
|
|
|
|
// Deserializes the type code and size of array types.
|
|
inline ErrorType DeserializeArrayType(EncodingType* encoding, std::size_t* size,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
if (const auto error = DeserializeEncoding(encoding, reader, start, end)) {
|
|
return error;
|
|
} else if (IsFixarrayEncoding(*encoding)) {
|
|
*size = GetFixarraySize(*encoding);
|
|
return ErrorCode::NO_ERROR;
|
|
} else if (*encoding == ENCODING_TYPE_ARRAY16) {
|
|
return DeserializeValue<std::uint16_t>(size, reader, start, end);
|
|
} else if (*encoding == ENCODING_TYPE_ARRAY32) {
|
|
return DeserializeValue<std::uint32_t>(size, reader, start, end);
|
|
} else {
|
|
return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_ARRAY,
|
|
*encoding);
|
|
}
|
|
}
|
|
|
|
// Deserializes the type code and size of map types.
|
|
inline ErrorType DeserializeMapType(EncodingType* encoding, std::size_t* size,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
if (const auto error = DeserializeEncoding(encoding, reader, start, end)) {
|
|
return error;
|
|
} else if (IsFixmapEncoding(*encoding)) {
|
|
*size = GetFixmapSize(*encoding);
|
|
return ErrorCode::NO_ERROR;
|
|
} else if (*encoding == ENCODING_TYPE_MAP16) {
|
|
return DeserializeValue<std::uint16_t>(size, reader, start, end);
|
|
} else if (*encoding == ENCODING_TYPE_MAP32) {
|
|
return DeserializeValue<std::uint32_t>(size, reader, start, end);
|
|
} else {
|
|
return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_MAP,
|
|
*encoding);
|
|
}
|
|
}
|
|
|
|
// Overload for std::vector types.
|
|
template <typename T, typename Allocator>
|
|
inline ErrorType DeserializeObject(std::vector<T, Allocator>* value,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
EncodingType encoding;
|
|
std::size_t size;
|
|
|
|
if (const auto error =
|
|
DeserializeArrayType(&encoding, &size, reader, start, end))
|
|
return error;
|
|
|
|
std::vector<T, Allocator> result(size);
|
|
for (std::size_t i = 0; i < size; i++) {
|
|
if (const auto error = DeserializeObject(&result[i], reader, start, end))
|
|
return error;
|
|
}
|
|
|
|
*value = std::move(result);
|
|
return ErrorCode::NO_ERROR;
|
|
|
|
// TODO(eieio): Consider the benefits and trade offs of this alternative.
|
|
#if 0
|
|
value->resize(size);
|
|
for (std::size_t i = 0; i < size; i++) {
|
|
if (const auto error = DeserializeObject(&(*value)[i], reader, start, end))
|
|
return error;
|
|
}
|
|
return ErrorCode::NO_ERROR;
|
|
#endif
|
|
}
|
|
|
|
// Deserializes an EmptyVariant value.
|
|
inline ErrorType DeserializeObject(EmptyVariant* /*empty*/,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
EncodingType encoding;
|
|
|
|
if (const auto error = DeserializeEncoding(&encoding, reader, start, end)) {
|
|
return error;
|
|
} else if (encoding != ENCODING_TYPE_NIL) {
|
|
return ErrorType(ErrorCode::UNEXPECTED_ENCODING, ENCODING_CLASS_MAP,
|
|
encoding);
|
|
} else {
|
|
return ErrorCode::NO_ERROR;
|
|
}
|
|
}
|
|
|
|
// Deserializes a Variant type.
|
|
template <typename... Types>
|
|
inline ErrorType DeserializeObject(Variant<Types...>* variant,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
EncodingType encoding;
|
|
std::size_t size;
|
|
|
|
if (const auto error =
|
|
DeserializeMapType(&encoding, &size, reader, start, end)) {
|
|
return error;
|
|
}
|
|
|
|
if (size != 1)
|
|
return ErrorType(ErrorCode::UNEXPECTED_TYPE_SIZE, ENCODING_CLASS_MAP,
|
|
encoding);
|
|
|
|
std::int32_t type;
|
|
if (const auto error = DeserializeObject(&type, reader, start, end)) {
|
|
return error;
|
|
} else if (type < Variant<Types...>::kEmptyIndex ||
|
|
type >= static_cast<std::int32_t>(sizeof...(Types))) {
|
|
return ErrorCode::INVALID_VARIANT_ELEMENT;
|
|
} else {
|
|
variant->Become(type);
|
|
return variant->Visit([reader, &start, &end](auto&& value) {
|
|
return DeserializeObject(&value, reader, start, end);
|
|
});
|
|
}
|
|
}
|
|
|
|
// Deserializes map types.
|
|
template <typename MapType>
|
|
inline ErrorType DeserializeMap(MapType* value, MessageReader* reader,
|
|
const void*& start, const void*& end) {
|
|
EncodingType encoding;
|
|
std::size_t size;
|
|
|
|
if (const auto error =
|
|
DeserializeMapType(&encoding, &size, reader, start, end))
|
|
return error;
|
|
|
|
MapType result;
|
|
for (std::size_t i = 0; i < size; i++) {
|
|
std::pair<typename MapType::key_type, typename MapType::mapped_type>
|
|
element;
|
|
if (const auto error =
|
|
DeserializeObject(&element.first, reader, start, end))
|
|
return error;
|
|
if (const auto error =
|
|
DeserializeObject(&element.second, reader, start, end))
|
|
return error;
|
|
result.emplace(std::move(element));
|
|
}
|
|
|
|
*value = std::move(result);
|
|
return ErrorCode::NO_ERROR;
|
|
}
|
|
|
|
// Overload for std::map types.
|
|
template <typename Key, typename T, typename Compare, typename Allocator>
|
|
inline ErrorType DeserializeObject(std::map<Key, T, Compare, Allocator>* value,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
return DeserializeMap(value, reader, start, end);
|
|
}
|
|
|
|
// Overload for std::unordered_map types.
|
|
template <typename Key, typename T, typename Hash, typename KeyEqual,
|
|
typename Allocator>
|
|
inline ErrorType DeserializeObject(
|
|
std::unordered_map<Key, T, Hash, KeyEqual, Allocator>* value,
|
|
MessageReader* reader, const void*& start, const void*& end) {
|
|
return DeserializeMap(value, reader, start, end);
|
|
}
|
|
|
|
// Overload for ArrayWrapper types.
|
|
template <typename T>
|
|
inline ErrorType DeserializeObject(ArrayWrapper<T>* value,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
EncodingType encoding;
|
|
std::size_t size;
|
|
|
|
if (const auto error =
|
|
DeserializeArrayType(&encoding, &size, reader, start, end)) {
|
|
return error;
|
|
}
|
|
|
|
// Try to resize the wrapper.
|
|
value->resize(size);
|
|
|
|
// Make sure there is enough space in the ArrayWrapper for the
|
|
// payload.
|
|
if (size > value->capacity())
|
|
return ErrorCode::INSUFFICIENT_DESTINATION_SIZE;
|
|
|
|
for (std::size_t i = 0; i < size; i++) {
|
|
if (const auto error = DeserializeObject(&(*value)[i], reader, start, end))
|
|
return error;
|
|
}
|
|
|
|
return ErrorCode::NO_ERROR;
|
|
}
|
|
|
|
// Overload for std::array types.
|
|
template <typename T, std::size_t Size>
|
|
inline ErrorType DeserializeObject(std::array<T, Size>* value,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
EncodingType encoding;
|
|
std::size_t size;
|
|
|
|
if (const auto error =
|
|
DeserializeArrayType(&encoding, &size, reader, start, end)) {
|
|
return error;
|
|
}
|
|
|
|
if (size != Size)
|
|
return ErrorCode::INSUFFICIENT_DESTINATION_SIZE;
|
|
|
|
for (std::size_t i = 0; i < size; i++) {
|
|
if (const auto error = DeserializeObject(&(*value)[i], reader, start, end))
|
|
return error;
|
|
}
|
|
|
|
return ErrorCode::NO_ERROR;
|
|
}
|
|
|
|
// Deserializes std::pair types.
|
|
template <typename T, typename U>
|
|
inline ErrorType DeserializeObject(std::pair<T, U>* value,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
EncodingType encoding;
|
|
std::size_t size;
|
|
|
|
if (const auto error =
|
|
DeserializeArrayType(&encoding, &size, reader, start, end)) {
|
|
return error;
|
|
} else if (size != 2) {
|
|
return ErrorCode::UNEXPECTED_TYPE_SIZE;
|
|
} else if (const auto error =
|
|
DeserializeObject(&value->first, reader, start, end)) {
|
|
return error;
|
|
} else if (const auto error =
|
|
DeserializeObject(&value->second, reader, start, end)) {
|
|
return error;
|
|
} else {
|
|
return ErrorCode::NO_ERROR;
|
|
}
|
|
}
|
|
|
|
// Stops template recursion when the last tuple element is reached.
|
|
template <typename... T>
|
|
inline ErrorType DeserializeTuple(std::tuple<T...>*, MessageReader*,
|
|
const void*&, const void*, Index<0>) {
|
|
return ErrorCode::NO_ERROR;
|
|
}
|
|
|
|
// Deserializes each element of a tuple recursively.
|
|
template <typename... T, std::size_t index>
|
|
inline ErrorType DeserializeTuple(std::tuple<T...>* tuple,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end, Index<index>) {
|
|
if (const auto error =
|
|
DeserializeTuple(tuple, reader, start, end, Index<index - 1>()))
|
|
return error;
|
|
else
|
|
return DeserializeObject(&std::get<index - 1>(*tuple), reader, start, end);
|
|
}
|
|
|
|
// Overload for standard tuple types.
|
|
template <typename... T>
|
|
inline ErrorType DeserializeObject(std::tuple<T...>* value,
|
|
MessageReader* reader, const void*& start,
|
|
const void*& end) {
|
|
EncodingType encoding;
|
|
std::size_t size;
|
|
|
|
if (const auto error =
|
|
DeserializeArrayType(&encoding, &size, reader, start, end)) {
|
|
return error;
|
|
} else if (size != sizeof...(T)) {
|
|
return ErrorCode::UNEXPECTED_TYPE_SIZE;
|
|
} else {
|
|
return DeserializeTuple(value, reader, start, end, Index<sizeof...(T)>());
|
|
}
|
|
}
|
|
|
|
// Stops template recursion when the last member of a Serializable type is
|
|
// reached.
|
|
template <typename Members, typename T>
|
|
inline ErrorType DeserializeMember(T*, MessageReader*, const void*&,
|
|
const void*, Index<0>) {
|
|
return ErrorCode::NO_ERROR;
|
|
}
|
|
|
|
// Deserializes each member of a Serializable type recursively.
|
|
template <typename Members, typename T, std::size_t index>
|
|
inline ErrorType DeserializeMember(T* value, MessageReader* reader,
|
|
const void*& start, const void*& end,
|
|
Index<index>) {
|
|
if (const auto error = DeserializeMember<Members>(value, reader, start, end,
|
|
Index<index - 1>()))
|
|
return error;
|
|
else
|
|
return DeserializeObject(&Members::template At<index - 1>::Resolve(*value),
|
|
reader, start, end);
|
|
}
|
|
|
|
// Deserializes the members of a Serializable type using the given
|
|
// SerializableMembersType type.
|
|
template <typename Members, typename T>
|
|
inline ErrorType DeserializeMembers(T* value, MessageReader* reader,
|
|
const void*& start, const void*& end) {
|
|
return DeserializeMember<Members>(value, reader, start, end,
|
|
Index<Members::MemberCount>());
|
|
}
|
|
|
|
// Top level deserialization function.
|
|
template <typename T>
|
|
inline ErrorType Deserialize(T* value, MessageReader* reader) {
|
|
PDX_TRACE_NAME("Deserialize");
|
|
MessageReader::BufferSection section = reader->GetNextReadBufferSection();
|
|
if (section.first == section.second)
|
|
return ErrorCode::INSUFFICIENT_BUFFER;
|
|
ErrorType error =
|
|
DeserializeObject(value, reader, section.first, section.second);
|
|
reader->ConsumeReadBufferSectionData(section.first);
|
|
return error;
|
|
}
|
|
|
|
} // namespace rpc
|
|
} // namespace pdx
|
|
} // namespace android
|
|
|
|
#endif // ANDROID_PDX_RPC_SERIALIZATION_H_
|