File msgpack-erlang-0.7.0-git.patch of Package msgpack-erlang
diff --git a/.travis.yml b/.travis.yml
index ee581a5..cd4bd3a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,6 +5,13 @@ script: PATH=.:$PATH make check-all
notifications:
email: false
otp_release:
+ - 20.3
+ - 20.2
+ - 20.1
+ - 20.0
+ - 19.3
+ - 19.2
+ - 19.1
- 19.0
- 18.3
- 18.2
diff --git a/README.md b/README.md
index 1115e46..bf320df 100644
--- a/README.md
+++ b/README.md
@@ -121,8 +121,9 @@ Both at packing and unpacking. Default value is `map`.
```erlang
msgpack:pack(#{ <<"key">> => <<"value">> }, []).
-msgpack:pack({[{<<"key">>, <<"value">>}]}, [{format, jiffy}]),
-msgpack:pack([{<<"key">>, <<"value">>}], [{format, jsx}]).
+msgpack:pack(#{ <<"key">> => <<"value">> }, [{map_format, map}]).
+msgpack:pack({[{<<"key">>, <<"value">>}]}, [{map_format, jiffy}]),
+msgpack:pack([{<<"key">>, <<"value">>}], [{map_format, jsx}]).
```
diff --git a/rebar.config b/rebar.config
index 8ff2e37..87ec726 100644
--- a/rebar.config
+++ b/rebar.config
@@ -1,4 +1,7 @@
-{require_otp_vsn, "17|18|19"}.
+%-*-Mode:erlang;coding:utf-8;tab-width:4;c-basic-offset:4;indent-tabs-mode:()-*-
+% ex: set ft=erlang fenc=utf-8 sts=4 ts=4 sw=4 et nomod:
+
+{require_otp_vsn, "17|18|19|20|21"}.
{erl_opts, [fail_on_warning, debug_info, warn_untyped_record]}.
%%, {parse_transform, eqc_cover}]}.
diff --git a/src/msgpack.erl b/src/msgpack.erl
index b86ef2a..01a08cc 100644
--- a/src/msgpack.erl
+++ b/src/msgpack.erl
@@ -48,13 +48,13 @@
-export_type([object/0, msgpack_map/0, options/0, ext_packer/0, ext_unpacker/0]).
-type object() :: msgpack_term().
--type options() ::
+-type options() ::
[{spec, new|old} |
{allow_atom, none|pack} |
{known_atoms, [atom()]} |
- {unpack_str, as_binary|as_list} |
+ {unpack_str, as_binary|as_list|as_tagged_list} |
{validate_string, boolean()} |
- {pack_str, from_binary|from_list|none} |
+ {pack_str, from_binary|from_list|from_tagged_list|none} |
{map_format, map|jiffy|jsx} |
{ext, {msgpack:ext_packer(), msgpack:ext_unpacker()} | module()}].
@@ -86,10 +86,10 @@ binary_to_term(Bin, Opt) ->
%% @doc Encode an erlang term into an msgpack binary.
%% Returns {error, {badarg, term()}} if the input is illegal.
--spec pack(msgpack:object()) -> binary() | {error, {badarg, term()}}.
+-spec pack(msgpack:object()) -> binary() | {error, _}.
pack(Term) -> msgpack:pack(Term, []).
--spec pack(msgpack:object(), msgpack:options()) -> binary().
+-spec pack(msgpack:object(), msgpack:options()) -> binary() | {error, _}.
pack(Term, Opts) ->
Option = parse_options(Opts),
try
@@ -129,7 +129,15 @@ unpack_stream(Bin) -> unpack_stream(Bin, []).
unpack_stream(Bin, Opts0) when is_binary(Bin) ->
Opts = parse_options(Opts0),
try
- msgpack_unpacker:unpack_stream(Bin, Opts)
+ Opts1=Opts?OPTION{
+ known_atoms=lists:map(
+ fun(X) ->
+ erlang:atom_to_binary(X, utf8)
+ end,
+ Opts?OPTION.known_atoms
+ )
+ },
+ msgpack_unpacker:unpack_stream(Bin, Opts1)
catch
throw:Exception -> {error, Exception}
end;
@@ -158,14 +166,14 @@ parse_options([{allow_atom,Type}|T], Opt0) ->
parse_options([{known_atoms, Atoms}|T], Opt0) when is_list(Atoms) ->
parse_options(T, Opt0?OPTION{known_atoms=Atoms});
-parse_options([{unpack_str, As}|T], Opt0) when As =:= as_binary orelse As =:= as_list ->
+parse_options([{unpack_str, As}|T], Opt0) when As =:= as_binary orelse As =:= as_list orelse As =:= as_tagged_list ->
parse_options(T, Opt0?OPTION{unpack_str=As});
parse_options([{validate_string, Bool}|T], Opt) when is_boolean(Bool) ->
parse_options(T, Opt?OPTION{validate_string=Bool});
parse_options([{pack_str, From}|T], Opt)
- when From =:= from_binary orelse From =:= from_list orelse From =:= none ->
+ when From =:= from_binary orelse From =:= from_list orelse From =:= from_tagged_list orelse From =:= none ->
parse_options(T, Opt?OPTION{pack_str=From});
parse_options([{map_format,Type}|T], Opt0)
diff --git a/src/msgpack.hrl b/src/msgpack.hrl
index d452dbd..0f47e73 100644
--- a/src/msgpack.hrl
+++ b/src/msgpack.hrl
@@ -26,7 +26,7 @@
%% Erlang representation of msgpack data.
-type msgpack_term() :: [msgpack_term()] | msgpack_map() |
- integer() | float() | boolean() | binary().
+ integer() | float() | boolean() | binary() | string() | {string, string()}.
-type format_type() :: jsx|jiffy|map.
@@ -36,10 +36,10 @@
-record(options_v4, {
spec = new :: new | old,
allow_atom = pack :: none | pack, %% allows atom when packing
- known_atoms = [] :: [atom()],
- unpack_str = as_list :: as_binary | as_list,
+ known_atoms = [] :: [atom()|binary()],
+ unpack_str = as_list :: as_binary | as_list | as_tagged_list,
validate_string = false :: boolean(),
- pack_str = from_list :: from_binary | from_list | none,
+ pack_str = from_list :: from_binary | from_list | from_tagged_list | none,
map_format = ?DEFAULT_MAP_FORMAT :: format_type(),
map_unpack_fun = ?DEFAULT_MAP_UNPACKER_FUN :: msgpack_map_unpacker(),
ext_packer = undefined :: msgpack:ext_packer() | undefined,
diff --git a/src/msgpack_packer.erl b/src/msgpack_packer.erl
index eeb6b1e..861f3ff 100644
--- a/src/msgpack_packer.erl
+++ b/src/msgpack_packer.erl
@@ -61,6 +61,11 @@ pack(Map, Opt = ?OPTION{map_format=jsx}) when Map =:= [{}]->
pack([{_,_}|_] = Map, Opt = ?OPTION{map_format=jsx}) ->
pack_map(Map, Opt);
+pack({string, String}, ?OPTION{spec=new, pack_str=from_tagged_list}=Opt) ->
+ case pack_string(String, Opt) of
+ {error, _} -> throw({badarg, String});
+ Bin when is_binary(Bin) -> Bin
+ end;
pack(List, ?OPTION{spec=new, pack_str=from_list}=Opt) when is_list(List) ->
try
case lists:all(fun is_integer/1, List) of
diff --git a/src/msgpack_unpacker.erl b/src/msgpack_unpacker.erl
index bf85b45..3484466 100644
--- a/src/msgpack_unpacker.erl
+++ b/src/msgpack_unpacker.erl
@@ -233,9 +233,18 @@ unpack_str_or_raw(V, ?OPTION{spec=new,
{case UnpackStr of
as_binary when ValidateString -> unpack_str(V), maybe_bin(V, Opt);
as_binary -> maybe_bin(V, Opt);
- as_list -> unpack_str(V)
+ as_list -> unpack_str(V);
+ as_tagged_list -> {string, unpack_str(V)}
end, Rest}.
+maybe_bin(Bin, ?OPTION{known_atoms=Known}) when Known=/=[] ->
+ case lists:member(Bin,Known) of
+ true ->
+ erlang:binary_to_existing_atom(Bin,utf8);
+ false ->
+ Bin
+ end;
+
maybe_bin(Bin, _) ->
Bin.
diff --git a/test/msgpack_tests.erl b/test/msgpack_tests.erl
index 2f977f1..7b3c5b5 100644
--- a/test/msgpack_tests.erl
+++ b/test/msgpack_tests.erl
@@ -379,6 +379,13 @@ binary_test_() ->
end}
].
+atom_test_() ->
+ Map1=#{atom1=>atom1,atom2=><<"binary2">>},
+ Bin=msgpack:pack(Map1),
+ ?_assertEqual({ok,#{<<"atom1">>=><<"atom1">>,
+ <<"atom2">>=><<"binary2">>}}, msgpack:unpack(Bin)),
+ ?_assertEqual({ok,Map1}, msgpack:unpack(Bin,[{known_atoms,[atom1,atom2]}])).
+
-define(PCNT, 5).
-define(CNT, 10000).
@@ -568,6 +575,17 @@ new_spec_pack_test_() ->
?_assertMatch(<<16#DD, 0, 1, 0, 0, _:65536/binary>>, %% 0xDD, four bytes, N objects
msgpack:pack(list_minus_one(65536), [{spec,new},{pack_str,PackStr}]))]
|| PackStr <- [from_list, from_binary, none]]
+ },
+ {"pack_str from_tagged_list",
+ [?_assertEqual(<<2#101:3, 3:5, 97,97,97>>,
+ msgpack:pack({string, "aaa"}, [{spec,new},{pack_str,from_tagged_list}])),
+ ?_assertMatch(<<16#D9, 32, _:32/binary>>,
+ msgpack:pack({string, list_a(32)}, [{spec,new},{pack_str,from_tagged_list}])),
+ ?_assertMatch(<<16#DA, 1, 0, _:256/binary>>,
+ msgpack:pack({string, list_a(256)}, [{spec,new},{pack_str,from_tagged_list}])),
+ ?_assertMatch(<<16#DB, 0, 1, 0, 0, _:65536/binary>>,
+ msgpack:pack({string, list_a(65536)}, [{spec,new},{pack_str,from_tagged_list}]))
+ ]
}].
new_spec_unpack_test_() ->
@@ -603,7 +621,9 @@ new_spec_unpack_test_() ->
?_assertEqual({ok, list_a(256)},
msgpack:unpack(<<16#DA, 1,0, (binary_a(256))/binary>>, [{spec,new},{unpack_str,as_list}])),
?_assertEqual({ok, list_a(65536)},
- msgpack:unpack(<<16#DB, 0,1,0,0, (binary_a(65536))/binary>>, [{spec,new},{unpack_str,as_list}]))
+ msgpack:unpack(<<16#DB, 0,1,0,0, (binary_a(65536))/binary>>, [{spec,new},{unpack_str,as_list}])),
+ ?_assertEqual({ok, {string, "aaa"}},
+ msgpack:unpack(<<2#101:3, 3:5, 97,97,97>>, [{spec,new},{unpack_str,as_tagged_list}]))
]}].
unpack_str_validation_test_() ->