Serialization: Correctly encode structs with no fields

Empty structs were being serialized as `null`, when they should have been serialized as `{}`.

This was due to the type inference on the serializer - where no calls to `field()` would result in the default `null` type.

To solve this, the `serialize(const void* object, const std::initializer_list<Field>&)` inline helper has been promoted to a virtual function (and renamed to `fields()`).
The JSON serializer implementation of this now first sets the object type to `object`, even if there are no fields to serialize.

Added test for this.

Fixes: #10
This commit is contained in:
Ben Clayton
2020-01-05 09:25:43 +00:00
parent 3a10d4cabd
commit cdc19ac4d9
5 changed files with 30 additions and 22 deletions

View File

@@ -166,6 +166,10 @@ class Serializer {
// Serializer that should be used to encode the n'th array element's data.
virtual bool array(size_t count, const std::function<bool(Serializer*)>&) = 0;
// fields() encodes all the provided fields of the given object.
virtual bool fields(const void* object,
const std::initializer_list<Field>&) = 0;
// field() encodes a field to the struct object referenced by this Serializer.
// The FieldSerializer will be called with a Serializer used to encode the
// field's data.
@@ -192,10 +196,6 @@ class Serializer {
template <typename T0, typename... Types>
inline bool serialize(const dap::variant<T0, Types...>&);
// serialize() encodes all the provided fields of the given object.
inline bool serialize(const void* object,
const std::initializer_list<Field>&);
// deserialize() encodes the given string.
inline bool serialize(const char* v);
@@ -231,18 +231,6 @@ bool Serializer::serialize(const dap::variant<T0, Types...>& var) {
return serialize(var.value);
}
bool Serializer::serialize(const void* object,
const std::initializer_list<Field>& fields) {
for (auto const& f : fields) {
if (!field(f.name, [&](Serializer* d) {
auto ptr = reinterpret_cast<const uint8_t*>(object) + f.offset;
return f.type->serialize(d, ptr);
}))
return false;
}
return true;
}
bool Serializer::serialize(const char* v) {
return serialize(std::string(v));
}

View File

@@ -164,7 +164,7 @@ M member_type(M T::*);
return d->deserialize(ptr, {__VA_ARGS__}); \
} \
bool serialize(Serializer* s, const void* ptr) const override { \
return s->serialize(ptr, {__VA_ARGS__}); \
return s->fields(ptr, {__VA_ARGS__}); \
} \
}; \
static TI typeinfo; \