WIP: Versioning
This commit is contained in:
parent
2c6c63579b
commit
db0082c325
|
@ -5,6 +5,10 @@
|
||||||
#include <clang/AST/DeclCXX.h>
|
#include <clang/AST/DeclCXX.h>
|
||||||
#include <clang/AST/DeclFriend.h>
|
#include <clang/AST/DeclFriend.h>
|
||||||
#include <clang/AST/DeclTemplate.h>
|
#include <clang/AST/DeclTemplate.h>
|
||||||
|
#include <clang/AST/Expr.h>
|
||||||
|
#include <clang/AST/RecursiveASTVisitor.h>
|
||||||
|
|
||||||
|
#include <llvm/ADT/APInt.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -61,10 +65,138 @@ string BinarySerializationCodeGenerator::qualifiedNameIfRelevant(clang::CXXRecor
|
||||||
return string();
|
return string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief The RetrieveIntegerLiteralFromDeclaratorDecl struct is used to traverse a variable declaration to get the integer value.
|
||||||
|
struct RetrieveIntegerLiteralFromDeclaratorDecl : public clang::RecursiveASTVisitor<RetrieveIntegerLiteralFromDeclaratorDecl> {
|
||||||
|
explicit RetrieveIntegerLiteralFromDeclaratorDecl(const clang::ASTContext &ctx);
|
||||||
|
bool VisitStmt(clang::Stmt *st);
|
||||||
|
const clang::ASTContext &ctx;
|
||||||
|
std::uint64_t res;
|
||||||
|
bool success;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Constructs a new instance for the specified AST context.
|
||||||
|
RetrieveIntegerLiteralFromDeclaratorDecl::RetrieveIntegerLiteralFromDeclaratorDecl(const clang::ASTContext &ctx)
|
||||||
|
: ctx(ctx)
|
||||||
|
, res(0)
|
||||||
|
, success(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Reads the integer value of \a st for integer literals.
|
||||||
|
bool RetrieveIntegerLiteralFromDeclaratorDecl::VisitStmt(clang::Stmt *st)
|
||||||
|
{
|
||||||
|
if (st->getStmtClass() != clang::Stmt::IntegerLiteralClass) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const auto *const integerLiteral = static_cast<const clang::IntegerLiteral *>(st);
|
||||||
|
auto evaluation = clang::Expr::EvalResult();
|
||||||
|
integerLiteral->EvaluateAsInt(evaluation, ctx, clang::Expr::SE_NoSideEffects, true);
|
||||||
|
if (!evaluation.Val.isInt()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const auto &asInt = evaluation.Val.getInt();
|
||||||
|
if (asInt.getActiveBits() > 64) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
res = asInt.getZExtValue();
|
||||||
|
success = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief The MemberTracking struct is an internal helper for BinarySerializationCodeGenerator::generate().
|
||||||
|
struct MemberTracking {
|
||||||
|
bool membersWritten = false, withinCondition = false;
|
||||||
|
BinaryVersion asOfVersion = BinaryVersion(), lastAsOfVersion = BinaryVersion();
|
||||||
|
BinaryVersion untilVersion = BinaryVersion(), lastUntilVersion = BinaryVersion();
|
||||||
|
|
||||||
|
bool checkForVersionMarker(clang::Decl *decl);
|
||||||
|
void concludeCondition(std::ostream &os);
|
||||||
|
void writeVersionCondition(std::ostream &os);
|
||||||
|
void writeExtraPadding(std::ostream &os);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns whether \a delc is a static member variable and processes special static member variables
|
||||||
|
* for versioning.
|
||||||
|
*/
|
||||||
|
bool MemberTracking::checkForVersionMarker(clang::Decl *decl)
|
||||||
|
{
|
||||||
|
if (decl->getKind() != clang::Decl::Kind::Var) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto *const declarator = static_cast<clang::DeclaratorDecl *>(decl);
|
||||||
|
const auto declarationName = declarator->getName();
|
||||||
|
const auto isAsOfVersion = declarationName.startswith("rrjAsOfVersion");
|
||||||
|
if (isAsOfVersion || declarationName.startswith("rrjUntilVersion")) {
|
||||||
|
auto v = RetrieveIntegerLiteralFromDeclaratorDecl(declarator->getASTContext());
|
||||||
|
v.TraverseDecl(declarator);
|
||||||
|
if (v.success) {
|
||||||
|
if (isAsOfVersion) {
|
||||||
|
asOfVersion = v.res;
|
||||||
|
if (asOfVersion > untilVersion) {
|
||||||
|
untilVersion = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
untilVersion = v.res;
|
||||||
|
if (untilVersion < asOfVersion) {
|
||||||
|
asOfVersion = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Concludes an unfinished version condition if-block.
|
||||||
|
*/
|
||||||
|
void MemberTracking::concludeCondition(std::ostream &os)
|
||||||
|
{
|
||||||
|
if (withinCondition) {
|
||||||
|
os << " }\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Starts a new version condition if-block if versioning parameters have changed.
|
||||||
|
*/
|
||||||
|
void MemberTracking::writeVersionCondition(std::ostream &os)
|
||||||
|
{
|
||||||
|
if (asOfVersion == lastAsOfVersion && untilVersion == lastUntilVersion) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
concludeCondition(os);
|
||||||
|
lastAsOfVersion = asOfVersion;
|
||||||
|
lastUntilVersion = untilVersion;
|
||||||
|
if ((withinCondition = asOfVersion || untilVersion)) {
|
||||||
|
os << " if (";
|
||||||
|
if (asOfVersion) {
|
||||||
|
os << "version >= " << asOfVersion;
|
||||||
|
if (untilVersion) {
|
||||||
|
os << " && ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (untilVersion) {
|
||||||
|
os << "version <= " << untilVersion;
|
||||||
|
}
|
||||||
|
os << ") {\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Writes extra padding (if within a version condition).
|
||||||
|
*/
|
||||||
|
void MemberTracking::writeExtraPadding(std::ostream &os)
|
||||||
|
{
|
||||||
|
if (withinCondition) {
|
||||||
|
os << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Generates pull() and push() helper functions in the ReflectiveRapidJSON::BinaryReflector namespace for the relevant classes.
|
* \brief Generates pull() and push() helper functions in the ReflectiveRapidJSON::BinaryReflector namespace for the relevant classes.
|
||||||
*/
|
*/
|
||||||
void BinarySerializationCodeGenerator::generate(ostream &os) const
|
void BinarySerializationCodeGenerator::generate(std::ostream &os) const
|
||||||
{
|
{
|
||||||
// initialize source manager to make use of isOnlyIncluded() for skipping records which are only included
|
// initialize source manager to make use of isOnlyIncluded() for skipping records which are only included
|
||||||
lazyInitializeSourceManager();
|
lazyInitializeSourceManager();
|
||||||
|
@ -119,20 +251,45 @@ void BinarySerializationCodeGenerator::generate(ostream &os) const
|
||||||
// print writeCustomType method
|
// print writeCustomType method
|
||||||
os << "template <> " << visibility << " void writeCustomType<::" << relevantClass.qualifiedName
|
os << "template <> " << visibility << " void writeCustomType<::" << relevantClass.qualifiedName
|
||||||
<< ">(BinarySerializer &serializer, const ::" << relevantClass.qualifiedName
|
<< ">(BinarySerializer &serializer, const ::" << relevantClass.qualifiedName
|
||||||
<< " &customObject)\n{\n"
|
<< " &customObject, BinaryVersion version)\n{\n"
|
||||||
" // write base classes\n";
|
" // write base classes\n";
|
||||||
for (const RelevantClass *baseClass : relevantBases) {
|
for (const RelevantClass *baseClass : relevantBases) {
|
||||||
os << " serializer.write(static_cast<const ::" << baseClass->qualifiedName << " &>(customObject));\n";
|
os << " serializer.write(static_cast<const ::" << baseClass->qualifiedName << " &>(customObject), version);\n";
|
||||||
}
|
}
|
||||||
os << " // write members\n";
|
os << " // write members\n";
|
||||||
auto membersWritten = false;
|
auto mt = MemberTracking();
|
||||||
for (const clang::FieldDecl *field : relevantClass.record->fields()) {
|
for (clang::Decl *const decl : relevantClass.record->decls()) {
|
||||||
if (writePrivateMembers || field->getAccess() == clang::AS_public) {
|
// check static member variables for version markers
|
||||||
os << " serializer.write(customObject." << field->getName() << ");\n";
|
if (mt.checkForVersionMarker(decl)) {
|
||||||
membersWritten = true;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// skip all further declarations but fields
|
||||||
|
if (decl->getKind() != clang::Decl::Kind::Field) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (relevantBases.empty() && !membersWritten) {
|
|
||||||
|
// skip const members
|
||||||
|
const auto *const field = static_cast<const clang::FieldDecl *>(decl);
|
||||||
|
if (field->getType().isConstant(field->getASTContext())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip private members conditionally
|
||||||
|
if (!writePrivateMembers && field->getAccess() != clang::AS_public) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write version markers
|
||||||
|
mt.writeVersionCondition(os);
|
||||||
|
mt.writeExtraPadding(os);
|
||||||
|
|
||||||
|
// write actual code for serialization
|
||||||
|
os << " serializer.write(customObject." << field->getName() << ", version);\n";
|
||||||
|
mt.membersWritten = true;
|
||||||
|
}
|
||||||
|
mt.concludeCondition(os);
|
||||||
|
if (relevantBases.empty() && !mt.membersWritten) {
|
||||||
os << " (void)serializer;\n (void)customObject;\n";
|
os << " (void)serializer;\n (void)customObject;\n";
|
||||||
}
|
}
|
||||||
os << "}\n";
|
os << "}\n";
|
||||||
|
@ -143,6 +300,7 @@ void BinarySerializationCodeGenerator::generate(ostream &os) const
|
||||||
}
|
}
|
||||||
|
|
||||||
// print readCustomType method
|
// print readCustomType method
|
||||||
|
mt = MemberTracking();
|
||||||
os << "template <> " << visibility << " void readCustomType<::" << relevantClass.qualifiedName
|
os << "template <> " << visibility << " void readCustomType<::" << relevantClass.qualifiedName
|
||||||
<< ">(BinaryDeserializer &deserializer, ::" << relevantClass.qualifiedName
|
<< ">(BinaryDeserializer &deserializer, ::" << relevantClass.qualifiedName
|
||||||
<< " &customObject)\n{\n"
|
<< " &customObject)\n{\n"
|
||||||
|
@ -151,18 +309,34 @@ void BinarySerializationCodeGenerator::generate(ostream &os) const
|
||||||
os << " deserializer.read(static_cast<::" << baseClass->qualifiedName << " &>(customObject));\n";
|
os << " deserializer.read(static_cast<::" << baseClass->qualifiedName << " &>(customObject));\n";
|
||||||
}
|
}
|
||||||
os << " // read members\n";
|
os << " // read members\n";
|
||||||
auto membersRead = false;
|
for (clang::Decl *const decl : relevantClass.record->decls()) {
|
||||||
for (const clang::FieldDecl *field : relevantClass.record->fields()) {
|
// check static member variables for version markers
|
||||||
|
if (mt.checkForVersionMarker(decl)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip all further declarations but fields
|
||||||
|
if (decl->getKind() != clang::Decl::Kind::Field) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// skip const members
|
// skip const members
|
||||||
|
const auto *const field = static_cast<const clang::FieldDecl *>(decl);
|
||||||
if (field->getType().isConstant(field->getASTContext())) {
|
if (field->getType().isConstant(field->getASTContext())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write version markers
|
||||||
|
mt.writeVersionCondition(os);
|
||||||
|
mt.writeExtraPadding(os);
|
||||||
|
|
||||||
if (readPrivateMembers || field->getAccess() == clang::AS_public) {
|
if (readPrivateMembers || field->getAccess() == clang::AS_public) {
|
||||||
os << " deserializer.read(customObject." << field->getName() << ");\n";
|
os << " deserializer.read(customObject." << field->getName() << ");\n";
|
||||||
membersRead = true;
|
mt.membersWritten = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (relevantBases.empty() && !membersRead) {
|
mt.concludeCondition(os);
|
||||||
|
if (relevantBases.empty() && !mt.membersWritten) {
|
||||||
os << " (void)deserializer;\n (void)customObject;\n";
|
os << " (void)deserializer;\n (void)customObject;\n";
|
||||||
}
|
}
|
||||||
os << "}\n\n";
|
os << "}\n\n";
|
||||||
|
|
|
@ -73,6 +73,7 @@ struct PointerStruct : public BinarySerializable<PointerStruct> {
|
||||||
/*!
|
/*!
|
||||||
* \brief The PointerStruct struct is used to test the behavior of the binary (de)serialization with smart pointer.
|
* \brief The PointerStruct struct is used to test the behavior of the binary (de)serialization with smart pointer.
|
||||||
*/
|
*/
|
||||||
|
// clang-format off
|
||||||
struct VersionedStruct : public BinarySerializable<VersionedStruct> {
|
struct VersionedStruct : public BinarySerializable<VersionedStruct> {
|
||||||
std::uint32_t a, b;
|
std::uint32_t a, b;
|
||||||
|
|
||||||
|
@ -82,5 +83,6 @@ until_version(2):
|
||||||
as_of_version(3):
|
as_of_version(3):
|
||||||
std::uint32_t e, f;
|
std::uint32_t e, f;
|
||||||
};
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
#endif // REFLECTIVE_RAPIDJSON_TESTS_MORE_STRUCTS_H
|
#endif // REFLECTIVE_RAPIDJSON_TESTS_MORE_STRUCTS_H
|
||||||
|
|
|
@ -30,7 +30,8 @@ template <typename Type, Traits::EnableIf<IsCustomType<Type>> *> void readCustom
|
||||||
boost::hana::keys(customType), [&deserializer, &customType](auto key) { deserializer.read(boost::hana::at_key(customType, key)); });
|
boost::hana::keys(customType), [&deserializer, &customType](auto key) { deserializer.read(boost::hana::at_key(customType, key)); });
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type, Traits::EnableIf<IsCustomType<Type>> *> void writeCustomType(BinarySerializer &serializer, const Type &customType, BinaryVersion version)
|
template <typename Type, Traits::EnableIf<IsCustomType<Type>> *>
|
||||||
|
void writeCustomType(BinarySerializer &serializer, const Type &customType, BinaryVersion version)
|
||||||
{
|
{
|
||||||
boost::hana::for_each(
|
boost::hana::for_each(
|
||||||
boost::hana::keys(customType), [&serializer, &customType](auto key) { serializer.write(boost::hana::at_key(customType, key)); });
|
boost::hana::keys(customType), [&serializer, &customType](auto key) { serializer.write(boost::hana::at_key(customType, key)); });
|
||||||
|
|
|
@ -21,8 +21,10 @@ template <> inline void readCustomType<CppUtilities::DateTime>(BinaryDeserialize
|
||||||
deserializer.read(dateTime.ticks());
|
deserializer.read(dateTime.ticks());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> inline void writeCustomType<CppUtilities::DateTime>(BinarySerializer &serializer, const CppUtilities::DateTime &dateTime)
|
template <>
|
||||||
|
inline void writeCustomType<CppUtilities::DateTime>(BinarySerializer &serializer, const CppUtilities::DateTime &dateTime, BinaryVersion version)
|
||||||
{
|
{
|
||||||
|
CPP_UTILITIES_UNUSED(version)
|
||||||
serializer.write(dateTime.totalTicks());
|
serializer.write(dateTime.totalTicks());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,8 +33,10 @@ template <> inline void readCustomType<CppUtilities::TimeSpan>(BinaryDeserialize
|
||||||
deserializer.read(timeSpan.ticks());
|
deserializer.read(timeSpan.ticks());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> inline void writeCustomType<CppUtilities::TimeSpan>(BinarySerializer &serializer, const CppUtilities::TimeSpan &timeSpan)
|
template <>
|
||||||
|
inline void writeCustomType<CppUtilities::TimeSpan>(BinarySerializer &serializer, const CppUtilities::TimeSpan &timeSpan, BinaryVersion version)
|
||||||
{
|
{
|
||||||
|
CPP_UTILITIES_UNUSED(version)
|
||||||
serializer.write(timeSpan.totalTicks());
|
serializer.write(timeSpan.totalTicks());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,8 @@ class BinaryDeserializer;
|
||||||
class BinarySerializer;
|
class BinarySerializer;
|
||||||
|
|
||||||
template <typename Type, Traits::EnableIf<IsCustomType<Type>> * = nullptr> void readCustomType(BinaryDeserializer &deserializer, Type &customType);
|
template <typename Type, Traits::EnableIf<IsCustomType<Type>> * = nullptr> void readCustomType(BinaryDeserializer &deserializer, Type &customType);
|
||||||
template <typename Type, Traits::EnableIf<IsCustomType<Type>> * = nullptr> void writeCustomType(BinarySerializer &serializer, const Type &customType, BinaryVersion version = 0);
|
template <typename Type, Traits::EnableIf<IsCustomType<Type>> * = nullptr>
|
||||||
|
void writeCustomType(BinarySerializer &serializer, const Type &customType, BinaryVersion version = 0);
|
||||||
|
|
||||||
class BinaryDeserializer : public CppUtilities::BinaryReader {
|
class BinaryDeserializer : public CppUtilities::BinaryReader {
|
||||||
friend class ::BinaryReflectorTests;
|
friend class ::BinaryReflectorTests;
|
||||||
|
@ -92,6 +93,7 @@ public:
|
||||||
template <typename Type, Traits::EnableIf<IsIteratableExceptString<Type>, Traits::HasSize<Type>> * = nullptr> void write(const Type &iteratable);
|
template <typename Type, Traits::EnableIf<IsIteratableExceptString<Type>, Traits::HasSize<Type>> * = nullptr> void write(const Type &iteratable);
|
||||||
template <typename Type, Traits::EnableIf<std::is_enum<Type>> * = nullptr> void write(const Type &enumValue);
|
template <typename Type, Traits::EnableIf<std::is_enum<Type>> * = nullptr> void write(const Type &enumValue);
|
||||||
template <typename Type, Traits::EnableIf<IsVariant<Type>> * = nullptr> void write(const Type &variant);
|
template <typename Type, Traits::EnableIf<IsVariant<Type>> * = nullptr> void write(const Type &variant);
|
||||||
|
template <typename Type, Traits::EnableIf<IsBuiltInType<Type>> * = nullptr> void write(const Type &builtInType, BinaryVersion version);
|
||||||
template <typename Type, Traits::EnableIf<IsCustomType<Type>> * = nullptr> void write(const Type &customType, BinaryVersion version = 0);
|
template <typename Type, Traits::EnableIf<IsCustomType<Type>> * = nullptr> void write(const Type &customType, BinaryVersion version = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -288,6 +290,12 @@ template <typename Type, Traits::EnableIf<IsVariant<Type>> *> void BinarySeriali
|
||||||
variant);
|
variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Type, Traits::EnableIf<IsBuiltInType<Type>> *> void BinarySerializer::write(const Type &builtInType, BinaryVersion version)
|
||||||
|
{
|
||||||
|
CPP_UTILITIES_UNUSED(version)
|
||||||
|
write(builtInType);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Type, Traits::EnableIf<IsCustomType<Type>> *> void BinarySerializer::write(const Type &customType, BinaryVersion version)
|
template <typename Type, Traits::EnableIf<IsCustomType<Type>> *> void BinarySerializer::write(const Type &customType, BinaryVersion version)
|
||||||
{
|
{
|
||||||
writeCustomType(*this, customType, version);
|
writeCustomType(*this, customType, version);
|
||||||
|
|
|
@ -26,12 +26,14 @@ template <typename Type, BinaryVersion defaultVersion> struct BinarySerializable
|
||||||
static constexpr auto defaultSerializeVersion = defaultVersion;
|
static constexpr auto defaultSerializeVersion = defaultVersion;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Type, BinaryVersion defaultVersion> inline void BinarySerializable<Type, defaultVersion>::toBinary(std::ostream &outputStream) const
|
template <typename Type, BinaryVersion defaultVersion>
|
||||||
|
inline void BinarySerializable<Type, defaultVersion>::toBinary(std::ostream &outputStream) const
|
||||||
{
|
{
|
||||||
BinaryReflector::BinarySerializer(&outputStream).write(static_cast<const Type &>(*this), defaultVersion);
|
BinaryReflector::BinarySerializer(&outputStream).write(static_cast<const Type &>(*this), defaultVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type, BinaryVersion defaultVersion> inline void BinarySerializable<Type, defaultVersion>::restoreFromBinary(std::istream &inputStream)
|
template <typename Type, BinaryVersion defaultVersion>
|
||||||
|
inline void BinarySerializable<Type, defaultVersion>::restoreFromBinary(std::istream &inputStream)
|
||||||
{
|
{
|
||||||
BinaryReflector::BinaryDeserializer(&inputStream).read(static_cast<Type &>(*this));
|
BinaryReflector::BinaryDeserializer(&inputStream).read(static_cast<Type &>(*this));
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ template <> void readCustomType<TestObjectBinary>(BinaryDeserializer &deserializ
|
||||||
deserializer.read(customType.dateTime);
|
deserializer.read(customType.dateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> void writeCustomType<TestObjectBinary>(BinarySerializer &serializer, const TestObjectBinary &customType)
|
template <> void writeCustomType<TestObjectBinary>(BinarySerializer &serializer, const TestObjectBinary &customType, BinaryVersion version)
|
||||||
{
|
{
|
||||||
serializer.write(customType.number);
|
serializer.write(customType.number);
|
||||||
serializer.write(customType.number2);
|
serializer.write(customType.number2);
|
||||||
|
@ -119,7 +119,7 @@ template <> void readCustomType<NestingArrayBinary>(BinaryDeserializer &deserial
|
||||||
deserializer.read(customType.testObjects);
|
deserializer.read(customType.testObjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> void writeCustomType<NestingArrayBinary>(BinarySerializer &serializer, const NestingArrayBinary &customType)
|
template <> void writeCustomType<NestingArrayBinary>(BinarySerializer &serializer, const NestingArrayBinary &customType, BinaryVersion version)
|
||||||
{
|
{
|
||||||
serializer.write(customType.name);
|
serializer.write(customType.name);
|
||||||
serializer.write(customType.testObjects);
|
serializer.write(customType.testObjects);
|
||||||
|
@ -132,7 +132,8 @@ template <> void readCustomType<ObjectWithVariantsBinary>(BinaryDeserializer &de
|
||||||
deserializer.read(customType.yetAnotherVariant);
|
deserializer.read(customType.yetAnotherVariant);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> void writeCustomType<ObjectWithVariantsBinary>(BinarySerializer &serializer, const ObjectWithVariantsBinary &customType)
|
template <>
|
||||||
|
void writeCustomType<ObjectWithVariantsBinary>(BinarySerializer &serializer, const ObjectWithVariantsBinary &customType, BinaryVersion version)
|
||||||
{
|
{
|
||||||
serializer.write(customType.someVariant);
|
serializer.write(customType.someVariant);
|
||||||
serializer.write(customType.anotherVariant);
|
serializer.write(customType.anotherVariant);
|
||||||
|
|
|
@ -7,11 +7,11 @@ namespace ReflectiveRapidJSON {
|
||||||
#define REFLECTIVE_RAPIDJSON_CAT_1(a, b) a##b
|
#define REFLECTIVE_RAPIDJSON_CAT_1(a, b) a##b
|
||||||
#define REFLECTIVE_RAPIDJSON_CAT_2(a, b) REFLECTIVE_RAPIDJSON_CAT_1(a, b)
|
#define REFLECTIVE_RAPIDJSON_CAT_2(a, b) REFLECTIVE_RAPIDJSON_CAT_1(a, b)
|
||||||
#define REFLECTIVE_RAPIDJSON_AS_OF_VERSION(version) \
|
#define REFLECTIVE_RAPIDJSON_AS_OF_VERSION(version) \
|
||||||
constexpr std::size_t REFLECTIVE_RAPIDJSON_CAT_2(rrjAsOfVersion, __COUNTER__) = version; \
|
static constexpr std::size_t REFLECTIVE_RAPIDJSON_CAT_2(rrjAsOfVersion, __COUNTER__) = version; \
|
||||||
public
|
public
|
||||||
#define REFLECTIVE_RAPIDJSON_UNTIL_VERSION(version) \
|
#define REFLECTIVE_RAPIDJSON_UNTIL_VERSION(version) \
|
||||||
constexpr std::size_t REFLECTIVE_RAPIDJSON_CAT_2(rrjUntilVersion, __COUNTER__) = version; \
|
static constexpr std::size_t REFLECTIVE_RAPIDJSON_CAT_2(rrjUntilVersion, __COUNTER__) = version; \
|
||||||
public
|
public
|
||||||
#else
|
#else
|
||||||
#define REFLECTIVE_RAPIDJSON_AS_OF_VERSION(version) public
|
#define REFLECTIVE_RAPIDJSON_AS_OF_VERSION(version) public
|
||||||
#define REFLECTIVE_RAPIDJSON_UNTIL_VERSION(version) public
|
#define REFLECTIVE_RAPIDJSON_UNTIL_VERSION(version) public
|
||||||
|
|
Loading…
Reference in New Issue