Skip to content

Commit 3a20095

Browse files
committed
added 17.0 map. next: compatibility code with rebar.config.script
1 parent 66d8149 commit 3a20095

6 files changed

Lines changed: 111 additions & 50 deletions

File tree

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,21 @@ Opt = [{enable_str, true}]
4646
There are several options for `msgpack:pack/2` and `msgpack:unpack/2` .
4747
See `msgpack:options()` in `msgpack.hrl`.
4848

49+
## Map Style
50+
51+
Since Erlang/OTP 17.0
52+
53+
```erlang
54+
msgpack:pack(#{ <<"key">> => <<"value">> }, [{format, map}]).
55+
```
56+
57+
Or use old jiffy/jsx style
58+
59+
```erlang
60+
msgpack:pack({[{<<"key">>, <<"value">>}]}, [{format, jiffy}]),
61+
msgpack:pack([{<<"key">>, <<"value">>}], [{format, jsx}]).
62+
```
63+
4964
## Ext type
5065

5166
Now msgpack-erlang supports ext type. Now you can serialize everything

include/msgpack.hrl

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121

2222
-type msgpack_map_jiffy() :: {[{msgpack_term(), msgpack_term()}]}.
2323

24-
-type msgpack_map() :: msgpack_map_jsx() | msgpack_map_jiffy().
24+
-type msgpack_map() :: msgpack_map_jsx() | msgpack_map_jiffy()
25+
| map().
2526

2627
-type msgpack_map_unpacker() ::
2728
fun((binary(), non_neg_integer(), msgpack_map(), msgpack_option()) ->
@@ -41,8 +42,10 @@
4142
| fun((byte(), binary()) ->
4243
{ok, msgpack_term()} | {error, any()}).
4344

45+
-type format_type() :: jsx|jiffy|map.
46+
4447
-type msgpack_list_options() :: [
45-
{format, jsx|jiffy} |
48+
{format, format_type()} |
4649
jsx | jiffy |
4750
{allow_atom, none|pack} |
4851
{enable_str, boolean()} |
@@ -51,14 +54,26 @@
5154

5255
-record(options_v1, {
5356
interface = jiffy :: jiffy | jsx,
54-
map_unpack_fun = fun msgpack_unpacker:unpack_map_jiffy/4 ::
57+
map_unpack_fun = fun msgpack_unpacker:unpack_map_jiffy/3 ::
5558
msgpack_map_unpacker(),
5659
impl = erlang :: erlang | nif
5760
}).
5861

5962
-record(options_v2, {
6063
interface = jiffy :: jiffy | jsx,
61-
map_unpack_fun = fun msgpack_unpacker:unpack_map_jiffy/4 ::
64+
map_unpack_fun = fun msgpack_unpacker:unpack_map_jiffy/3 ::
65+
msgpack_map_unpacker(),
66+
impl = erlang :: erlang | nif,
67+
allow_atom = none :: none | pack, %% allows atom when packing
68+
enable_str = false :: boolean(), %% true for new spec
69+
ext_packer = undefined :: msgpack_ext_packer() | undefined,
70+
ext_unpacker = undefined :: msgpack_ext_unpacker() | undefined,
71+
original_list = [] :: msgpack_list_options()
72+
}).
73+
74+
-record(options_v3, {
75+
interface = map :: format_type(),
76+
map_unpack_fun = fun msgpack_unpacker:unpack_map/3 ::
6277
msgpack_map_unpacker(),
6378
impl = erlang :: erlang | nif,
6479
allow_atom = none :: none | pack, %% allows atom when packing
@@ -68,5 +83,5 @@
6883
original_list = [] :: msgpack_list_options()
6984
}).
7085

71-
-define(OPTION, #options_v2).
72-
-type msgpack_option() :: #options_v2{}.
86+
-define(OPTION, #options_v3).
87+
-type msgpack_option() :: #options_v3{}.

src/msgpack.erl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
%% <tr><td> binary() </td><td> fix_raw/raw16/raw32 </td></tr>
3232
%% <tr><td> list() </td><td> fix_array/array16/array32 </td></tr>
3333
%% <tr><td> {proplist()} </td><td> fix_map/map16/map32 </td></tr>
34+
%% <tr><td> [{term(),term{}]|[{}] </td><td> fix_map/map16/map32 </td></tr>
35+
%% <tr><td> map() </td><td> fix_map/map16/map32 </td></tr>
3436
%% </table>
3537
%% @end
3638

@@ -113,11 +115,14 @@ unpack_stream(Other, _) -> {error, {badarg, Other}}.
113115

114116
%% @private
115117
-spec parse_options(msgpack:options()) -> msgpack_option().
116-
parse_options(Opt) -> parse_options(Opt, ?OPTION{original_list=Opt}).
118+
119+
parse_options(Opt) ->
120+
parse_options(Opt, ?OPTION{original_list=Opt}).
117121

118122
%% @private
119123
-spec parse_options(msgpack:options(), msgpack_option()) -> msgpack_option().
120124
parse_options([], Opt) -> Opt;
125+
121126
parse_options([jsx|TL], Opt0) ->
122127
Opt = Opt0?OPTION{interface=jsx,
123128
map_unpack_fun=msgpack_unpacker:map_unpacker(jsx)},
@@ -126,19 +131,23 @@ parse_options([jiffy|TL], Opt0) ->
126131
Opt = Opt0?OPTION{interface=jiffy,
127132
map_unpack_fun=msgpack_unpacker:map_unpacker(jiffy)},
128133
parse_options(TL, Opt);
129-
parse_options([{format,Type}|TL], Opt0) when Type =:= jsx; Type =:= jiffy ->
134+
parse_options([{format,Type}|TL], Opt0)
135+
when Type =:= jsx; Type =:= jiffy; Type =:= map->
130136
Opt = Opt0?OPTION{interface=Type,
131137
map_unpack_fun=msgpack_unpacker:map_unpacker(Type)},
132138
parse_options(TL, Opt);
139+
133140
parse_options([{allow_atom,Type}|TL], Opt0) ->
134141
Opt = case Type of
135142
none -> Opt0?OPTION{allow_atom=none};
136143
pack -> Opt0?OPTION{allow_atom=pack}
137144
end,
138145
parse_options(TL, Opt);
146+
139147
parse_options([{enable_str,Bool}|TL], Opt0) ->
140148
Opt = Opt0?OPTION{enable_str=Bool},
141149
parse_options(TL, Opt);
150+
142151
parse_options([{ext, Module}|TL], Opt0) when is_atom(Module) ->
143152
Opt = Opt0?OPTION{ext_packer=fun Module:pack_ext/2,
144153
ext_unpacker=fun Module:unpack_ext/3},
@@ -149,6 +158,7 @@ parse_options([{ext, {Packer,Unpacker}}|TL], Opt0) when
149158
Opt = Opt0?OPTION{ext_packer=Packer, ext_unpacker=Unpacker},
150159
parse_options(TL, Opt).
151160

161+
152162
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
153163
%% unit tests
154164
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

src/msgpack_packer.erl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ pack(true, _) ->
4141

4242
pack(Bin, Opt) when is_binary(Bin) ->
4343
case Opt of
44+
#options_v3{enable_str=true} = Opt -> pack_raw2(Bin);
45+
#options_v3{enable_str=false} = Opt -> pack_raw(Bin);
4446
#options_v2{enable_str=true} = Opt -> pack_raw2(Bin);
4547
#options_v2{enable_str=false} = Opt -> pack_raw(Bin);
4648
#options_v1{} = Opt -> pack_raw(Bin)
@@ -49,6 +51,10 @@ pack(Bin, Opt) when is_binary(Bin) ->
4951
pack(Atom, #options_v2{allow_atom=pack} = Opt) when is_atom(Atom) ->
5052
pack(erlang:atom_to_binary(Atom, unicode), Opt);
5153

54+
%% map interface
55+
pack(Map, Opt = ?OPTION{interface=map}) when is_map(Map) ->
56+
pack_map(maps:to_list(Map), Opt);
57+
5258
%% jiffy interface
5359
pack({Map}, Opt = ?OPTION{interface=jiffy}) when is_list(Map) ->
5460
pack_map(Map, Opt);
@@ -59,7 +65,7 @@ pack(Map, Opt = ?OPTION{interface=jsx}) when Map =:= [{}]->
5965
pack([{_,_}|_] = Map, Opt = ?OPTION{interface=jsx}) ->
6066
pack_map(Map, Opt);
6167

62-
pack(List, #options_v2{enable_str=true}=Opt) when is_list(List) ->
68+
pack(List, ?OPTION{enable_str=true}=Opt) when is_list(List) ->
6369
try
6470
case lists:all(fun is_integer/1, List) of
6571
true ->

src/msgpack_unpacker.erl

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
-include("msgpack.hrl").
2424
-include_lib("eunit/include/eunit.hrl").
2525

26-
-export([unpack_map_jiffy/4, unpack_map_jsx/4]).
26+
-export([unpack_map/3, unpack_map_jiffy/3, unpack_map_jsx/3]).
2727

2828
%% unpack them all
2929
-spec unpack_stream(Bin::binary(), msgpack_option()) -> {msgpack:object(), binary()} | no_return().
@@ -94,14 +94,14 @@ unpack_stream(<<16#DD, L:32/big-unsigned-integer-unit:1, Rest/binary>>, Opt) ->
9494
%% Maps
9595
unpack_stream(<<2#1000:4, L:4, Rest/binary>>, Opt) ->
9696
Unpacker = Opt?OPTION.map_unpack_fun,
97-
Unpacker(Rest, L, [], Opt);
97+
Unpacker(Rest, L, Opt);
9898
unpack_stream(<<16#DE, L:16/big-unsigned-integer-unit:1, Rest/binary>>, Opt) ->
9999
Unpacker = Opt?OPTION.map_unpack_fun,
100-
Unpacker(Rest, L, [], Opt);
100+
Unpacker(Rest, L, Opt);
101101

102102
unpack_stream(<<16#DF, L:32/big-unsigned-integer-unit:1, Rest/binary>>, Opt) ->
103103
Unpacker = Opt?OPTION.map_unpack_fun,
104-
Unpacker(Rest, L, [], Opt);
104+
Unpacker(Rest, L, Opt);
105105

106106
%% Tag-encoded lengths (kept last, for speed)
107107
%% positive int
@@ -166,34 +166,50 @@ unpack_array(Bin, Len, Acc, Opt) ->
166166
{Term, Rest} = unpack_stream(Bin, Opt),
167167
unpack_array(Rest, Len-1, [Term|Acc], Opt).
168168

169+
map_unpacker(map) ->
170+
fun ?MODULE:unpack_map/3;
169171
map_unpacker(jiffy) ->
170-
fun ?MODULE:unpack_map_jiffy/4;
172+
fun ?MODULE:unpack_map_jiffy/3;
171173
map_unpacker(jsx) ->
172-
fun ?MODULE:unpack_map_jsx/4.
174+
fun ?MODULE:unpack_map_jsx/3.
173175

174176

177+
-spec unpack_map(binary(), non_neg_integer(), msgpack_option()) ->
178+
{map(), binary()} | no_return().
179+
unpack_map(Bin, Len, Opt) ->
180+
{Map, Rest} = unpack_map_as_proplist(Bin, Len, [], Opt),
181+
{maps:from_list(Map), Rest}.
182+
%% unpack_map(Bin, Len, #{}, Opt).
183+
184+
%% unpack_map(Bin, Len, Acc, _) -> {Acc, Bin};
185+
%% unpack_map(Bin, Len, Acc, Opt) ->
186+
%% {Key, Rest} = unpack_stream(Bin, Opt),
187+
%% {Value, Rest2} = unpack_stream(Rest, Opt),
188+
%% unpack_map(Rest2, Len-1, maps:put(Key, Value, Acc), Opt).
189+
175190
%% Users SHOULD NOT send too long list: this uses lists:reverse/1
176-
-spec unpack_map_jiffy(binary(), non_neg_integer(),
177-
msgpack:msgpack_map(), msgpack_option()) ->
178-
{msgpack:msgpack_map(), binary()} | no_return().
179-
unpack_map_jiffy(Bin, 0, Acc, _) ->
180-
{{lists:reverse(Acc)}, Bin};
181-
unpack_map_jiffy(Bin, Len, Acc, Opt) ->
182-
{Key, Rest} = unpack_stream(Bin, Opt),
183-
{Value, Rest2} = unpack_stream(Rest, Opt),
184-
unpack_map_jiffy(Rest2, Len-1, [{Key,Value}|Acc], Opt).
185-
186-
-spec unpack_map_jsx(binary(), non_neg_integer(),
187-
msgpack:msgpack_map(), msgpack_option()) ->
188-
{msgpack:msgpack_map(), binary()} | no_return().
189-
unpack_map_jsx(Bin, 0, [], _) ->
190-
{[{}], Bin};
191-
unpack_map_jsx(Bin, 0, Acc, _) ->
191+
-spec unpack_map_jiffy(binary(), non_neg_integer(), msgpack_option()) ->
192+
{msgpack:msgpack_map_jiffy(), binary()} | no_return().
193+
unpack_map_jiffy(Bin, Len, Opt) ->
194+
{Map, Rest} = unpack_map_as_proplist(Bin, Len, [], Opt),
195+
{{Map}, Rest}.
196+
197+
-spec unpack_map_jsx(binary(), non_neg_integer(), msgpack_option()) ->
198+
{msgpack:msgpack_map_jsx(), binary()} | no_return().
199+
unpack_map_jsx(Bin, Len, Opt) ->
200+
case unpack_map_as_proplist(Bin, Len, [], Opt) of
201+
{[], Rest} -> {[{}], Rest};
202+
{Map, Rest} -> {Map, Rest}
203+
end.
204+
205+
-spec unpack_map_as_proplist(binary(), non_neg_integer(), proplists:proplist(), msgpack_option()) ->
206+
{proplists:proplist(), binary()} | no_return().
207+
unpack_map_as_proplist(Bin, 0, Acc, _) ->
192208
{lists:reverse(Acc), Bin};
193-
unpack_map_jsx(Bin, Len, Acc, Opt) ->
209+
unpack_map_as_proplist(Bin, Len, Acc, Opt) ->
194210
{Key, Rest} = unpack_stream(Bin, Opt),
195211
{Value, Rest2} = unpack_stream(Rest, Opt),
196-
unpack_map_jsx(Rest2, Len-1, [{Key,Value}|Acc], Opt).
212+
unpack_map_as_proplist(Rest2, Len-1, [{Key,Value}|Acc], Opt).
197213

198214
unpack_string_or_raw(V, ?OPTION{enable_str=true} = _Opt, Rest) ->
199215
{unpack_string(V), Rest};

test/msgpack_test.erl

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
-ifdef(DO_MSGPACK_CROSSLANG_TEST).
2727

28-
test_data_jsx()->
28+
test_data() ->
2929
[true, false, nil,
3030
0, 1, 2, 123, 512, 1230, 678908, 16#FFFFFFFFFF,
3131
-1, -23, -512, -1230, -567898, -16#FFFFFFFFFF,
@@ -35,23 +35,16 @@ test_data_jsx()->
3535
<<"hoasfdafdas][">>,
3636
[0,42, <<"sum">>, [1,2]], [1,42, nil, [3]],
3737
-234, -40000, -16#10000000, -16#100000000,
38-
42,
39-
[{}], {hoge}
40-
].
38+
42].
39+
40+
test_data_jsx()->
41+
test_data() ++ [[{}], {hoge}].
4142

4243
test_data_jiffy()->
43-
[true, false, nil,
44-
0, 1, 2, 123, 512, 1230, 678908, 16#FFFFFFFFFF,
45-
-1, -23, -512, -1230, -567898, -16#FFFFFFFFFF,
46-
123.123, -234.4355, 1.0e-34, 1.0e64,
47-
[23, 234, 0.23],
48-
<<"hogehoge">>, <<"243546rf7g68h798j", 0, 23, 255>>,
49-
<<"hoasfdafdas][">>,
50-
[0,42, <<"sum">>, [1,2]], [1,42, nil, [3]],
51-
-234, -40000, -16#10000000, -16#100000000,
52-
42,
53-
{[]}, {hoge}
54-
].
44+
test_data() ++ [ {[]}, {hoge} ].
45+
46+
test_data_map()->
47+
test_data() ++ [ #{}, {hoge} ].
5548

5649
compare_all([], [])-> ok;
5750
compare_all([], R)-> {toomuchrhs, R};
@@ -69,6 +62,10 @@ port_receive(Port, Acc) ->
6962
after 1000 -> Acc
7063
end.
7164

65+
port_map_test()->
66+
Tests = test_data_map(),
67+
?assertEqual({[Tests],<<>>}, msgpack:unpack(msgpack:pack([Tests], [{format,map}]), [{format,map}])),
68+
7269
port_jiffy_test()->
7370
Tests = test_data_jiffy(),
7471
?assertEqual({[Tests],<<>>}, msgpack:unpack(msgpack:pack([Tests], [{format,jiffy}]), [{format,jiffy}])),
@@ -77,7 +74,7 @@ port_jiffy_test()->
7774
% true = port_command(Port, msgpack:pack(Tests)),
7875
% ?assertEqual({Tests, <<>>}, msgpack:unpack(port_receive(Port))),
7976
% port_close(Port).
80-
ok.
77+
ok.
8178

8279

8380
port_jsx_test()->
@@ -121,6 +118,8 @@ issue_jsx_5_test() ->
121118
Bin0 = <<130,196,4,116,121,112,101,196,7,119,111,114,107,101,114,115,
122119
196,4,100,97,116,97,145,130,196,8,119,111,114,107,101,114,105,100,
123120
196,5,115,116,100,46,49,196,5,115,108,111,116,115,160>>,
121+
?debugFmt("~w", [binary_to_list(Bin0)]),
122+
?debugFmt("~w", [binary_to_list(Encoded)]),
124123
?assertEqual(Bin0, Encoded),
125124

126125
{ok, Decoded} = msgpack:unpack(Bin0, [{format,jsx}, {enable_str,true}]),

0 commit comments

Comments
 (0)