The library msgpack is not meant to decode raw binaries, but binaries which was previously encoded with msgpack:pack.
The reason is that a binary has no structure by itself, so you must include some information in it to allow the decoding. It is what a function like term_to_binary does, using the erlang external format:
1> B = term_to_binary({12,atom,[$a,$l,$i,$s,$t]}).
<<131,104,3,97,12,100,0,4,97,116,111,109,107,0,5,97,108,
105,115,116>>
2> binary_to_term(B).
{12,atom,"alist"}
The library msgpack allows to use other encoding method.
Coming to your issue. The difference between unpack and unpack_stream is that the first expect one single encoded term in the binary while the second suppose that the trailing binary contains other encoded terms.
when you call msgpack:unpack(<<10>>)
, it falls in the case where the first element is smaller than 128: in this case the coded value is the value itself. If you had tried with something greater than 127, you had got an error:
4> msgpack:unpack(<<10>>).
{ok,10}
5> msgpack:unpack(<<200>>).
{error,incomplete}
6>
when you call msgpack:unpack_stream(<<10>>)
, it does exactly the same, so the first element is decoded, with the result 10, and the rest of the binary is provided fro further decoding:
8> {A,Rest} = msgpack:unpack_stream(<<10,0>>).
{10,<<0>>}
9> msgpack:unpack_stream(Rest).
{0,<<>>}
10> msgpack:unpack_stream(<<200,0>>).
{error,incomplete}
11> msgpack:unpack_stream(<<200,0,0>>).
{error,incomplete}
12> msgpack:unpack_stream(<<200,0,0,0>>).
{error,{badarg,{bad_ext,200}}}
13>
The right way to use the library is to encode first your message:
13> Msg = msgpack:pack(<<10,0,0>>).
<<163,10,0,0>>
14> msgpack:unpack(Msg).
{ok,<<10,0,0>>}
or with the first example:
24> Msg1 = msgpack:pack(msgpack:term_to_binary({12,atom,[$a,$l,$i,$s,$t]})).
<<183,199,20,131,131,104,3,97,12,100,0,4,97,116,111,109,
107,0,5,97,108,105,115,116>>
25> {ok,Rep1} = msgpack:unpack(Msg1).
{ok,<<199,20,131,131,104,3,97,12,100,0,4,97,116,111,109,
107,0,5,97,108,105,115,116>>}
26> msgpack:binary_to_term(Rep1).
{12,atom,"alist"}
27>
[edit]
here is a proposal to add padding and an unpacker that detect it. It uses the unpack_stream, because it is not possible to modify the way an integer is coded.
Packer = fun(X, Opt) -> {ok, {12,<<>>}} end,
Unpacker = fun(12, _) -> {ok, padding} end,
Opt = [{ext,{Packer,Unpacker}}],
Pad = fun(B) -> Size = 10 - size(B), SB = Size*8,<<B/binary,16#C7,Size,12,0:SB>> end,
R = msgpack:pack(256897),
Var = Pad(R),
{I,Rest} = msgpack:unpack_stream(Var,Opt),
{padding,<<>>} = msgpack:unpack_stream(Rest,Opt).