Throw exception during binary deserialization when version is not supported
This commit is contained in:
parent
13428667f8
commit
44c6b8c609
|
@ -379,7 +379,7 @@ as_of_version(3):
|
||||||
std::uint32_t bar; // will be read/written if outer scope version is >= 3
|
std::uint32_t bar; // will be read/written if outer scope version is >= 3
|
||||||
};
|
};
|
||||||
|
|
||||||
// example struct where version is serialized/deserialized; defaults to version when writing
|
// example struct where version is serialized/deserialized; defaults to version 3 when writing
|
||||||
struct Example : public BinarySerializable<Example, 3> {
|
struct Example : public BinarySerializable<Example, 3> {
|
||||||
Nested nested; // will be read/written in any case, version is "propagated down"
|
Nested nested; // will be read/written in any case, version is "propagated down"
|
||||||
std::uint32_t a, b; // will be read/written in any case
|
std::uint32_t a, b; // will be read/written in any case
|
||||||
|
@ -395,8 +395,11 @@ as_of_version(4):
|
||||||
};
|
};
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
A mechanism to catch unsupported versions during deserialization is yet to be implemented.
|
The version specified as template argument is also assumed to be the highest supported version.
|
||||||
Additionally, the versioning is completely untested at this point.
|
If a higher version is encountered during deserialization, `BinaryVersionNotSupported` is thrown
|
||||||
|
and the deserialization aborted.
|
||||||
|
|
||||||
|
Note that the versioning is mostly untested at this point.
|
||||||
|
|
||||||
### Remarks
|
### Remarks
|
||||||
* Static member variables and member functions are currently ignored by the generator.
|
* Static member variables and member functions are currently ignored by the generator.
|
||||||
|
|
|
@ -308,10 +308,13 @@ void BinarySerializationCodeGenerator::generate(std::ostream &os) const
|
||||||
<< ">(BinaryDeserializer &deserializer, ::" << relevantClass.qualifiedName << " &customObject, BinaryVersion version)\n{\n";
|
<< ">(BinaryDeserializer &deserializer, ::" << relevantClass.qualifiedName << " &customObject, BinaryVersion version)\n{\n";
|
||||||
if (!relevantClass.relevantBase.empty()) {
|
if (!relevantClass.relevantBase.empty()) {
|
||||||
os << " // read version\n"
|
os << " // read version\n"
|
||||||
" if constexpr (Versioning<"
|
" using V = Versioning<"
|
||||||
<< relevantClass.relevantBase
|
<< relevantClass.relevantBase
|
||||||
<< ">::enabled) {\n"
|
<< ">;\n"
|
||||||
" version = deserializer.readVariableLengthUIntBE();\n"
|
" if constexpr (V::enabled) {\n"
|
||||||
|
" V::assertVersion(version = deserializer.readVariableLengthUIntBE(), \""
|
||||||
|
<< relevantClass.qualifiedName
|
||||||
|
<< "\");\n"
|
||||||
" }\n";
|
" }\n";
|
||||||
}
|
}
|
||||||
os << " // read base classes\n";
|
os << " // read base classes\n";
|
||||||
|
|
|
@ -14,10 +14,13 @@
|
||||||
|
|
||||||
namespace ReflectiveRapidJSON {
|
namespace ReflectiveRapidJSON {
|
||||||
|
|
||||||
|
using BinaryVersionNotSupported = VersionNotSupported<BinaryVersion>;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief The BinarySerializable class provides the CRTP-base for (de)serializable objects.
|
* \brief The BinarySerializable class provides the CRTP-base for (de)serializable objects.
|
||||||
*/
|
*/
|
||||||
template <typename Type, BinaryVersion v> struct BinarySerializable {
|
template <typename Type, BinaryVersion v> struct BinarySerializable {
|
||||||
|
using VersionNotSupported = BinaryVersionNotSupported;
|
||||||
void toBinary(std::ostream &outputStream, BinaryVersion version = 0) const;
|
void toBinary(std::ostream &outputStream, BinaryVersion version = 0) const;
|
||||||
BinaryVersion restoreFromBinary(std::istream &inputStream);
|
BinaryVersion restoreFromBinary(std::istream &inputStream);
|
||||||
static Type fromBinary(std::istream &inputStream);
|
static Type fromBinary(std::istream &inputStream);
|
||||||
|
|
|
@ -26,6 +26,11 @@ public
|
||||||
|
|
||||||
CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(IsVersioned, T::version);
|
CPP_UTILITIES_TRAITS_DEFINE_TYPE_CHECK(IsVersioned, T::version);
|
||||||
|
|
||||||
|
template <typename VersionType> struct VersionNotSupported {
|
||||||
|
VersionType presentVersion = 0, maxVersion = 0;
|
||||||
|
const char *record = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Type, bool Condition = IsVersioned<Type>::value> struct Versioning {
|
template <typename Type, bool Condition = IsVersioned<Type>::value> struct Versioning {
|
||||||
static constexpr auto enabled = false;
|
static constexpr auto enabled = false;
|
||||||
};
|
};
|
||||||
|
@ -33,10 +38,21 @@ template <typename Type, bool Condition = IsVersioned<Type>::value> struct Versi
|
||||||
template <typename Type> struct Versioning<Type, true> {
|
template <typename Type> struct Versioning<Type, true> {
|
||||||
static constexpr auto enabled = Type::version != 0;
|
static constexpr auto enabled = Type::version != 0;
|
||||||
static constexpr auto serializationDefault = Type::version;
|
static constexpr auto serializationDefault = Type::version;
|
||||||
|
static constexpr auto maxSupported = Type::version;
|
||||||
static constexpr auto applyDefault(decltype(serializationDefault) version)
|
static constexpr auto applyDefault(decltype(serializationDefault) version)
|
||||||
{
|
{
|
||||||
return version ? version : serializationDefault;
|
return version ? version : serializationDefault;
|
||||||
}
|
}
|
||||||
|
static constexpr auto isSupported(decltype(maxSupported) version)
|
||||||
|
{
|
||||||
|
return version <= maxSupported;
|
||||||
|
}
|
||||||
|
static constexpr auto assertVersion(decltype(maxSupported) version, const char *record = nullptr)
|
||||||
|
{
|
||||||
|
if (!isSupported(version)) {
|
||||||
|
throw typename Type::VersionNotSupported({ .presentVersion = version, .maxVersion = maxSupported, .record = record });
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ReflectiveRapidJSON
|
} // namespace ReflectiveRapidJSON
|
||||||
|
|
Loading…
Reference in New Issue