Serialization rework #2503
There was a problem hiding this comment.
Now follows the same structure as the other new stream APIs.
- Adds a documentation comment and an example to resultSerializer - Both, serialize() and deserialize(), work on ranges of ubyte now Note that this might later be extended to allow ranges of char, but for now this is the more generic baseline implementation.
- Renamed isSerializerSupportSinkType to doesSerializerSupportStringSink and made it independent of the serialized type - Adds support for output range based string sink serialization in addition to delegate based - Sink serialization takes precedence independently of the used serializer to enforce consistent semantics - Fixes JsonStringSerializer to escape strings written with the sink approach - Fixes the documentation order of string serialization vs. sink serialization
Allows to use overload sets and template functions for generic deserialization.
I don't think the
All of these would only work under the assumption that the serializer performs a recursive construction of the result value using constructor calls. I don't think that this is realistic for a generic serializer for multiple reasons.
Also, the init state is practically mandated by the language to be valid anyway. Returning large structs by value, where performing an extra copy is a performance issue (in the same order of magnitude as the serialization and the network transfer), doesn't sound like a good idea, too, at least I wouldn't count on the library handling it with NRVO throughout if I were a user.
So while I do understand that these are issues in theory, I'm not really convinced that they are in practice. The counter argument is pretty simple, but maybe you have a better idea how to solve it:
Having it as a return value means that
Well, constructor is one thing, but the serializer an also define a hook (a la
It's mandated to exist. But some types need to be constructed to be valid, which is a common complain in D.
Well, those are drawn from experience writing a deserializer. Namely, this.
The reason for doing so was that we needed to have, in our REST API, types that are not under our control. Those types are
The TL;DR from my experience was: If you want a generic serializer, it needs to handle const/immutable/shared.
I'm not sure I follow. If you can provide an instance of the type to be filled, you can provide the
If the copy constructor is the issue, then why not just move the value instead of copying?
How to invoke
It breaks internal pointers. Which are invalid in D, but not in C++. And even in D, I know Weka is using them for example.
Not only. Any type is able to explicitly support the serialization by specifying the static
I would really have to have a way to provide a pattern matcher to the function, but I haven't found quite the right approach yet.
The API I went with requires you to provide the type you want as template parameter. E.g.
Serialization of possibly immutable C++ structs with internal pointers, set up in D, which may choose to move the struct implicitly, still sounds like a rather esoteric and dangerous combination to me (although I see how this could come up in custom IPC scenarios), and nothing to endorse. But since you have practical evidence I obviously can't really dismiss it.
So then that means it's template-only serialization, which, since it matches the general serialization API, is really not a big deal. Being able to work with concrete types and overload sets would have been nice, though.
Allows to construct types with assignment restrictions with the trade-off of requiring generic serializer definitions instead of overload sets.