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_() ->
openSUSE Build Service is sponsored by