Review: std.msgpack
Robert Jacques
sandford at jhu.edu
Mon Jun 21 21:47:19 PDT 2010
On Mon, 21 Jun 2010 01:22:40 -0400, Masahiro Nakagawa
<repeatedly at gmail.com> wrote:
> On Sun, 20 Jun 2010 02:08:07 +0900, Robert Jacques <sandford at jhu.edu>
> wrote:
>
>> On Sat, 19 Jun 2010 00:02:28 -0400, Masahiro Nakagawa
>> <repeatedly at gmail.com> wrote:
>>
>>> mp_Object is based on std.json.JSONValue.
>>> Variant can't have mp_pack method.
>>> Hmm..., I check Variant again.
>>
>> Well, std.json is an incomplete, alpha library that's buggy and
>> unreviewed. For example, the design is currently very C-ish with
>> structs, enums, functions and exceptions all being independent top
>> level constructs.
>
> I checked Variant, but Variant[Variant] doesn't work... :(
I know. But then again, how would you define a total ordering for Variant?
The sadder aspect is that Variant[string] doesn't work either. Anyways, I
primarily trying to recommend the API, although fixing Variant is the
better long term solution.
For what it's worth, this works:
Variant[Variant] bar = [ Variant("foo"): Variant(5),
Variant(5.5):Variant(6) ];
But this doesn't
Variant a = "bar";
Variant b = 5;
bar[a] = b;
>>> If Phobos has std.serializer like Orange(or Doost.Serialization?),
>>> I will implement MsgPackArchive.
>>> But general serializer usually is low-performance and lacks some
>>> features.
>>> So when user wants performance, user will use Packer and Unpacker
>>> directly.
>>
>> I'd disagree, with regard to performance: there's no reason why a
>> general (cycle free) serializer would be slower than your direct
>> routines. A serializer's only job is to pack/unpack complex objects
>> correctly: the key advantage is that polymorphic objects/struct only
>> have to support one custom serialization routine/mixin. Also,
>> separating physical-encoding from logical-encoding allows for some
>> very powerful idioms. You could, for example, add cycle
>> detection/support to msgpack by having the serializer write in a
>> micro-format on-top of msgpack. Another, more important example is
>> letting the user decide between an array and a map representation for
>> structs/objects. Using arrays for objects is extremely brittle. If say,
>> a new hire refactors a class from A{ int x; int y;} to A{ int y; int x;
>> } you now have an extremely hard to find and track down logic bug in
>> your program. To say nothing about trying to upgrade an implementation.
>> On the other hand, using maps for objects adds a decent amount of
>> overhead to the total serialized length.
>
> Yeah, It's a implementation-dependent problem. So I wrote "usually".
> If Phobos supports good serializer, I will remove Packer and
> direct-conversion Unpacker.
>
>>>> Other little things,
>>>> -Why isn't nil mapped to null?
>>>
>>> Where?
>>
>> MsgPack has a nil type which I assume is equivalent to null. So why
>> isn't it simply included in the object serializer (and arguably also in
>> the array and map serializer as well)?
>
> Sorry, I can't understand this statement. Nullable types(class, array
> and associative-array)
> is serialized to nil if null.
Sorry. The comment was about redundancy. i.e. packNil <=> pack(null).
>> For that matter, packNil, packTrue, packFalse, etc are all redundant
>> with pack(T).
>
> I removed packTrue, packFalse.
>
>> Furthermore, stream, packArray, packMap and packRaw all should be
>> internal routines. (Though, a rawPack(T)(T value) routine might not go
>> amiss)
>
> I moved packRaw to internal method, but packArray and packMap should be
> public.
> MessagePack's array and map can contain any type.
I can see the usefulness of the functionality, but for an end-user API, it
is brittle and error-prone. For example:
p.packArray(3).pack(5).pack("six"); produces an incorrect msgPack stream.
A better syntax would be: p.pack(5,"six"); or p.packArray(5,"six"); I know
you're using pack(Types...) to mean pack(Types[0]).pack(Types[1])... but
using it for variable type arrays is worth considering. For packMap, pack(
["key": "value"], [5:"six"] ) could work, but packMap( ["key": "value"],
[5:"six"] ) or packMap("key","value",5,"six") would avoid confusion with
pack(Types...).
>> (Returns: this to method chain. => Returns: self. i.e. for method
>> chaining )
>
> Changed.
>
>> Oh, as for packing real you'll need to use CustomFloat!(80) for cross
>> platform inter-op. Also, it shouldn't be @system: there's nothing
>> memory-unsafe about writing or reading them. Please don't abuse
>> @system, etc for meanings other their intended meanings.
>
> I forgot this. CutstomFloat was already fixed by you and David in trunk.
> I added 80bit floating point support for non-x86 environment.
Don't forget that some x86 platform store 80-bit floats in more than
80-bits. So you do need to check the size of real on x86 platforms as well.
>
> Masahiro
P.S. Don't forget to apply changes to packer's API to unpacker.
More information about the Digitalmars-d
mailing list