msgpack / msgpack-d

MessagePack for D / msgpack.org[D]
http://msgpack.org/
Boost Software License 1.0
118 stars 41 forks source link

One Common Interface Member for Specifying Packing and Unpacking of Classes and Structs #20

Open nordlow opened 11 years ago

nordlow commented 11 years ago

Is there a reason for why msgpack-d doesn't provide packing and unpacking through one common class/struct member? Boost.Units and cerealed does just that.

repeatedly commented 11 years ago

Sorry, I don't understand your comment. Could you write the actual example?

nordlow commented 11 years ago

Carefully read this page https://github.com/atilaneves/cerealed.

Cerealed is yet another serialization package for D. Cerealed provides more compact ways of specifying serialization (pack) and deserialization (unpack) in D than msgpack-d does. Examples are

Could msgpack-d be enhanced to provide these features aswell?

I really like msgpack's more stable backend format compared to Cerealed and would love to get these features in msgpack-d aswell.

repeatedly commented 11 years ago

clever use of User Defined Attributes (UDA).

https://github.com/msgpack/msgpack-d/blob/23252c5fad1b3274e26375fe3daa91ee2c3a56ef/example/attribute.d#L12 msgpack-d has @nonPacked attribute. Isn't it enough?

msgpack-d can't provide @Bits and @RawArray because it causes invalid msgpack format.

nordlow commented 11 years ago

Ahh. Nice. I'd missed that. What about specifying a common serializer (accept) for both packing and unpacking like cerealed does in this example

struct CustomStruct {
    ubyte mybyte;
    ushort myshort;
    void accept(Cereal cereal) {
         //do NOT call cereal.grain(this), that would cause an infinite loop
         cereal.grainAllMembers(this);
         ubyte otherbyte = 4; //make it an lvalue
         cereal.grain(otherbyte);
    }
}

auto cerealiser = new Cerealiser();
cerealiser ~= CustomStruct(1, 2);
assert(cerealiser.bytes == [ 1, 0, 2, 4]);

//because of the custom serialisation, passing in just [1, 0, 2] would throw
auto decerealiser = new Decerealiser([1, 0, 2, 4]);
assert(decerealiser.value!CustomStruct == CustomStruct(1, 2));

This may have to be implemented in a templated member function, right?

repeatedly commented 11 years ago

I think this approach causes performance degression so I can't implement only this approach. But maybe, we can implement Cereal like class based (se)deserializer on top of current Packer / Unpacker.

nordlow commented 11 years ago

Couldn't the behaviour of such a unified pack-unpack function, say doMsgpack(P), be determined through some predicate/trait on the template parameter P, with zero-runtime cost? I believe this is how Boost.Units solves it. I'm gonna check how Cereal does this and get back to you.

Suitable alternative names could be codeMsgpack or acceptMsgpack (in analogy with Cereal's namings).

repeatedly commented 11 years ago

@nordlow My 'performance degression' means vtbl call, ref for lvalue and etc. So template parameter doesn't resolve the problem. But these degressions are not problem in some cases. I think class based implementation seems acceptable like below.

class MessagePacker
{
    /* ... */
}

class MessagePackSerializer : MessagePacker
{
    Packer packer;

    /* do packing */
}

class MessagePackDeserializer : MessagePacker
{
    Unpacker unpacker;

    /* do unpacking */
}
nordlow commented 11 years ago

I don't understand. Could you give please be more specific about what code the classes should contain.

repeatedly commented 10 years ago

Could you give please be more specific about what code the classes should contain.

I don't have a detail implementation because above class is just an idea. But it should be similar to Cerealed.

repeatedly commented 10 years ago

If I have a time, I will impelemet this class as a prototype.