MessagePack C API
Asked Answered
S

1

3

In looking at the C API for MessagePack, there are a number of functions to appropriately serialize (pack) the data according to type: msgpack_pack_uint8, msgpack_pack_int32, ...

There doesn't seem to be the equivalent call in the API to unpack the data. msgpack_unpack_next returns a msgpack_object. These objects only have coarse granularity of types (the largest of the type: int64, double, ...), based on the enums included.

Am I missing something here? Is the expectation that the coarse object be used and then cast?

How should unpacking be done properly?

Furthermore, is there any good documentation or usage examples? The ones on the website are trivial.

Sevastopol answered 14/9, 2012 at 20:19 Comment(4)
And where is the C API for MessagePack?Lafayette
@Lafayette github.com/msgpack/msgpack-c or msgpack.orgSevastopol
thanks. I hoped there was more more analytical documentation.Lafayette
The best documentation I can find is here: github.com/msgpack/msgpack-c/wiki/v2_0_c_overviewBonefish
S
11

At unpack time, any integer value is always stored within a msgpack_object as a fixed-width 64-bit integer (int64_t if negative, uint64_t otherwise).

See cpp/src/msgpack/object.h for more details on msgpack_object et al., and cpp/src/msgpack/unpack.c to see how msgpack handles the unpacking logic, e.g.:

static inline int template_callback_int8(unpack_user* u,
                                         int8_t d,
                                         msgpack_object* o) {
    if(d >= 0) {
        o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d;
        return 0;
    }
    else {
        o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o->via.i64 = d;
        return 0;
    }
}

This is because at pack time, msgpack chooses dynamically the most optimal way to encode an integer according to its value, e.g. if you use msgpack_pack_uint16 to pack your integer then:

  • it will be saved in 1 byte if the value is in [0, 127],
  • 2 bytes with 0xcc as first byte if the value is in [128, 255],
  • 3 bytes with 0xcd as first byte otherwise.

See msgpack_pack_real_uint16 from cpp/src/msgpack/pack_template.h for more details.


In other words at unpack time, msgpack uses a large enough positive or negative (test if obj.type is MSGPACK_OBJECT_POSITIVE_INTEGER or MSGPACK_OBJECT_NEGATIVE_INTEGER) to hold any integer value. So it's up to you to:

  • cast if you can always assume that values will never overflow your cast type,
  • or, check dynamically (with a mask) if the value is not large enough for your receiver type,
  • or, always use an int64_t or uint64_t.

At last, the C test suite (msgpack/cpp/test/msgpackc_test.cpp) might be helpful to browse code samples.

Significance answered 25/9, 2012 at 10:27 Comment(1)
Thanks! I came to the same conclusion. msgpack is efficient on the wire and it's up to you to know the protocol for appropriate conversions. The cost of that efficiency is it can't automatically deduce the original type on unpacking.Sevastopol

© 2022 - 2024 — McMap. All rights reserved.