#ifndef REFLECTIVE_RAPIDJSON_BINARY_REFLECTOR_H #define REFLECTIVE_RAPIDJSON_BINARY_REFLECTOR_H /*! * \file reflector.h * \brief Contains BinaryReader and BinaryWriter supporting binary (de)serialization * of primitive and custom types. */ #include "../traits.h" #include #include #include #include #include #include #include namespace ReflectiveRapidJSON { /*! * \brief The AdaptedBinarySerializable class allows considering 3rd party classes as serializable. */ template struct AdaptedBinarySerializable : public Traits::Bool { static constexpr const char *name = "AdaptedBinarySerializable"; static constexpr const char *qualifiedName = "ReflectiveRapidJSON::AdaptedBinarySerializable"; }; template struct BinarySerializable; /*! * \brief The BinaryReflector namespace contains BinaryReader and BinaryWriter for automatic binary (de)serialization. */ namespace BinaryReflector { // define traits to distinguish between "built-in" types like int, std::string, std::vector, ... and custom structs/classes template using IsBuiltInType = Traits::Any, Traits::IsIteratable, Traits::IsSpecializationOf, std::is_enum>; template using IsCustomType = Traits::Not>; template using IsSerializable = Traits::All< Traits::Any>, std::is_base_of, Type>, AdaptedBinarySerializable>, Traits::Not>>; class BinaryDeserializer; class BinarySerializer; template > * = nullptr> void readCustomType(BinaryDeserializer &deserializer, Type &customType); template > * = nullptr> void writeCustomType(BinarySerializer &serializer, const Type &customType); class BinaryDeserializer : public IoUtilities::BinaryReader { public: BinaryDeserializer(std::istream *stream); using IoUtilities::BinaryReader::read; template > * = nullptr> void read(Type &pair); template , Traits::IsResizable> * = nullptr> void read(Type &iteratable); template > * = nullptr> void read(Type &iteratable); template , Traits::None, Traits::All, Traits::IsResizable>>> * = nullptr> void read(Type &iteratable); template > * = nullptr> void read(Type &customType); template > * = nullptr> void read(Type &customType); }; class BinarySerializer : public IoUtilities::BinaryWriter { public: BinarySerializer(std::ostream *stream); using IoUtilities::BinaryWriter::write; template > * = nullptr> void write(const Type &pair); template , Traits::HasSize> * = nullptr> void write(const Type &iteratable); template > * = nullptr> void write(const Type &customType); template > * = nullptr> void write(const Type &customType); }; inline BinaryDeserializer::BinaryDeserializer(std::istream *stream) : IoUtilities::BinaryReader(stream) { } template > *> void BinaryDeserializer::read(Type &pair) { read(pair.first); read(pair.second); } template , Traits::IsResizable> *> void BinaryDeserializer::read(Type &iteratable) { const auto size = readVariableLengthUIntBE(); iteratable.resize(size); for (auto &element : iteratable) { read(element); } } template > *> void BinaryDeserializer::read(Type &iteratable) { const auto size = readVariableLengthUIntBE(); for (size_t i = 0; i != size; ++i) { std::pair::type, typename Type::value_type::second_type> value; read(value); iteratable.emplace(std::move(value)); } } template , Traits::None, Traits::All, Traits::IsResizable>>> *> void BinaryDeserializer::read(Type &iteratable) { const auto size = readVariableLengthUIntBE(); for (size_t i = 0; i != size; ++i) { typename Type::value_type value; read(value); iteratable.emplace(std::move(value)); } } template > *> void BinaryDeserializer::read(Type &enumValue) { typename std::underlying_type::type value; read(value); enumValue = static_cast(value); } template > *> void BinaryDeserializer::read(Type &customType) { readCustomType(*this, customType); } inline BinarySerializer::BinarySerializer(std::ostream *stream) : IoUtilities::BinaryWriter(stream) { } template > *> void BinarySerializer::write(const Type &pair) { write(pair.first); write(pair.second); } template , Traits::HasSize> *> void BinarySerializer::write(const Type &iteratable) { writeVariableLengthUIntBE(iteratable.size()); for (const auto &element : iteratable) { write(element); } } template > *> void BinarySerializer::write(const Type &enumValue) { write(static_cast::type>(enumValue)); } template > *> void BinarySerializer::write(const Type &customType) { writeCustomType(*this, customType); } } // namespace BinaryReflector } // namespace ReflectiveRapidJSON #endif // REFLECTIVE_RAPIDJSON_BINARY_REFLECTOR_H