44namespace BinaryReflector {
47template <
typename Type>
48using IsBuiltInType = Traits::Any<Traits::IsAnyOf<Type, char, std::uint8_t, bool, std::string, std::int16_t, std::uint16_t, std::int32_t,
49 std::uint32_t, std::int64_t, std::uint64_t, float,
double>,
50 Traits::IsIteratable<Type>, Traits::IsSpecializingAnyOf<Type, std::pair, std::unique_ptr, std::shared_ptr, std::optional>, std::is_enum<Type>,
52template <
typename Type>
using IsCustomType = Traits::Not<IsBuiltInType<Type>>;
62template <
typename Type, Traits::EnableIf<IsCustomType<Type>> * =
nullptr>
69template <
typename Type, Traits::EnableIf<IsCustomType<Type>> * =
nullptr>
74 friend class ::BinaryReflectorTests;
79 using CppUtilities::BinaryReader::read;
80 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::pair>> * =
nullptr>
void read(Type &pair);
81 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::unique_ptr>> * =
nullptr>
void read(Type &pointer);
82 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::shared_ptr>> * =
nullptr>
void read(Type &pointer);
83 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::optional>> * =
nullptr>
void read(Type &pointer);
84 template <
typename Type, Traits::EnableIf<IsArray<Type>, Traits::IsResizable<Type>> * =
nullptr>
void read(Type &iteratable);
85 template <
typename Type, Traits::EnableIfAny<IsMapOrHash<Type>, IsMultiMapOrHash<Type>> * =
nullptr>
void read(Type &iteratable);
86 template <
typename Type,
87 Traits::EnableIf<IsIteratableExceptString<Type>,
88 Traits::None<IsMapOrHash<Type>,
IsMultiMapOrHash<Type>, Traits::All<IsArray<Type>, Traits::IsResizable<Type>>>> * =
nullptr>
89 void read(Type &iteratable);
90 template <
typename Type, Traits::EnableIf<std::is_enum<Type>> * =
nullptr>
void read(Type &enumValue);
91 template <
typename Type, Traits::EnableIf<IsVariant<Type>> * =
nullptr>
void read(Type &variant);
96 std::unordered_map<std::uint64_t, std::any> m_pointer;
101 friend class ::BinaryReflectorTests;
106 using CppUtilities::BinaryWriter::write;
107 template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::pair>> * =
nullptr>
void write(
const Type &pair);
108 template <
typename Type, Traits::EnableIf<Traits::IsSpecializingAnyOf<Type, std::unique_ptr, std::optional>> * =
nullptr>
110 template <
typename Type, Traits::EnableIf<Traits::IsSpecializingAnyOf<Type, std::shared_ptr>> * =
nullptr>
void write(
const Type &pointer);
111 template <
typename Type, Traits::EnableIf<IsIteratableExceptString<Type>, Traits::HasSize<Type>> * =
nullptr>
void write(
const Type &iteratable);
112 template <
typename Type, Traits::EnableIf<std::is_enum<Type>> * =
nullptr>
void write(
const Type &enumValue);
113 template <
typename Type, Traits::EnableIf<IsVariant<Type>> * =
nullptr>
void write(
const Type &variant);
114 template <
typename Type, Traits::EnableIf<IsBuiltInType<Type>> * =
nullptr>
void write(
const Type &builtInType,
BinaryVersion version);
115 template <
typename Type, Traits::EnableIf<IsCustomType<Type>> * =
nullptr>
void write(
const Type &customType,
BinaryVersion version = 0);
118 std::unordered_map<std::uint64_t, bool> m_pointer;
122 : CppUtilities::BinaryReader(stream)
132template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::unique_ptr>> *>
void BinaryDeserializer::read(Type &pointer)
138 pointer = std::make_unique<typename Type::element_type>();
142template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::shared_ptr>> *>
void BinaryDeserializer::read(Type &pointer)
144 auto mode = readByte();
151 const auto id = (mode & 0x4) ? readUInt64BE() : readVariableLengthUIntBE();
152 if ((mode & 0x3) == 1) {
154 m_pointer[id] = pointer = std::make_shared<typename Type::element_type>();
160 pointer = std::any_cast<Type>(m_pointer[
id]);
161 }
catch (
const std::bad_any_cast &) {
162 throw CppUtilities::ConversionException(
"Referenced pointer type does not match");
166template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::optional>> *>
void BinaryDeserializer::read(Type &opt)
175template <
typename Type, Traits::EnableIf<IsArray<Type>, Traits::IsResizable<Type>> *>
void BinaryDeserializer::read(Type &iteratable)
177 const auto size = readVariableLengthUIntBE();
178 iteratable.resize(size);
179 for (
auto &element : iteratable) {
184template <
typename Type, Traits::EnableIfAny<IsMapOrHash<Type>, IsMultiMapOrHash<Type>> *>
void BinaryDeserializer::read(Type &iteratable)
186 const auto size = readVariableLengthUIntBE();
187 for (
size_t i = 0; i != size; ++i) {
188 std::pair<typename std::remove_const<typename Type::value_type::first_type>::type,
typename Type::value_type::second_type> value;
190 iteratable.emplace(std::move(value));
194template <
typename Type,
195 Traits::EnableIf<IsIteratableExceptString<Type>,
196 Traits::None<IsMapOrHash<Type>,
IsMultiMapOrHash<Type>, Traits::All<IsArray<Type>, Traits::IsResizable<Type>>>> *>
199 const auto size = readVariableLengthUIntBE();
200 for (
size_t i = 0; i != size; ++i) {
201 typename Type::value_type value;
203 iteratable.emplace(std::move(value));
209 typename std::underlying_type<Type>::type value;
211 enumValue =
static_cast<Type
>(value);
216template <
typename Variant, std::
size_t compiletimeIndex = 0>
217void readVariantValueByRuntimeIndex(std::size_t runtimeIndex, Variant &variant, BinaryDeserializer &deserializer)
219 if constexpr (compiletimeIndex < std::variant_size_v<Variant>) {
220 if (compiletimeIndex == runtimeIndex) {
221 if constexpr (std::is_same_v<std::variant_alternative_t<compiletimeIndex, Variant>, std::monostate>) {
222 variant = std::monostate{};
224 deserializer.read(variant.template emplace<compiletimeIndex>());
227 readVariantValueByRuntimeIndex<Variant, compiletimeIndex + 1>(runtimeIndex, variant, deserializer);
230 throw CppUtilities::ConversionException(
"Variant index is out of expected range");
238 Detail::readVariantValueByRuntimeIndex(readByte(), variant, *
this);
253 : CppUtilities::BinaryWriter(stream)
257template <
typename Type, Traits::EnableIf<Traits::IsSpecializationOf<Type, std::pair>> *>
void BinarySerializer::write(
const Type &pair)
263template <
typename Type, Traits::EnableIf<Traits::IsSpecializingAnyOf<Type, std::unique_ptr, std::optional>> *>
266 writeBool(
static_cast<bool>(opt));
272template <
typename Type, Traits::EnableIf<Traits::IsSpecializingAnyOf<Type, std::shared_ptr>> *>
void BinarySerializer::write(
const Type &pointer)
274 if (pointer ==
nullptr) {
278 const auto id =
reinterpret_cast<std::uintptr_t
>(pointer.get());
279 const auto bigId =
id >= 0x80000000000000;
280 auto &alreadyWritten = m_pointer[id];
281 std::uint8_t mode = alreadyWritten ? 2 : 1;
289 writeVariableLengthUIntBE(
id);
291 if (!alreadyWritten) {
292 alreadyWritten =
true;
297template <
typename Type, Traits::EnableIf<IsIteratableExceptString<Type>, Traits::HasSize<Type>> *>
300 writeVariableLengthUIntBE(iteratable.size());
301 for (
const auto &element : iteratable) {
306template <
typename Type, Traits::EnableIf<std::is_enum<Type>> *>
void BinarySerializer::write(
const Type &enumValue)
308 write(
static_cast<typename std::underlying_type<Type>::type
>(enumValue));
313 static_assert(std::variant_size_v<Type> < std::numeric_limits<std::uint8_t>::max(),
"index will not exceed limit");
314 writeByte(
static_cast<std::uint8_t
>(variant.index()));
316 [
this](
const auto &valueOfActualType) {
317 if constexpr (!std::is_same_v<std::decay_t<
decltype(valueOfActualType)>, std::monostate>) {
318 write(valueOfActualType);
320 CPP_UTILITIES_UNUSED(
this)
328 CPP_UTILITIES_UNUSED(version)
Traits::Any< Traits::IsAnyOf< Type, char, std::uint8_t, bool, std::string, std::int16_t, std::uint16_t, std::int32_t, std::uint32_t, std::int64_t, std::uint64_t, float, double >, Traits::IsIteratable< Type >, Traits::IsSpecializingAnyOf< Type, std::pair, std::unique_ptr, std::shared_ptr, std::optional >, std::is_enum< Type >, IsVariant< Type > > IsBuiltInType