Add #{items := list()} type for encode/decode #32

Merged
uwiger merged 3 commits from uw-encode-maps into master 2023-08-18 21:40:50 +09:00
uwiger commented 2023-08-17 20:17:49 +09:00 (Migrated from gitlab.com)

Add support for decoding sub-structures.

Example:

serialization_template(ping, ?PING_VSN) ->
    [ {versions, [#{items => [ {protocol, binary}
                             , {vsns, [int]}]
                   }]
      }
    , {port, int}
...

Previously, the template supported only [type()], denoting a list where all elements are of the same type. This made it tricky to extend the list pattern. Also, complex subtypes aren't necessarily that descriptive:

capabilities_template(<<"chain_poi">>, ?PING_VSN) ->
    [{chain_poi, #{ items => [ {height, int}
                             , {root_hash, binary}
                             , {genesis, binary}
                             , {top, binary}
                             , {poi, binary} ]}
     }].

The serialization would look like this:

(aeternity@localhost)1> Cs = [{chain_poi,[#{height => 1000, root_hash => <<"rx">>, genesis => <<"gx">>, top => <<"tx">>, poi => <<"px">>}]}].
[{chain_poi,[#{genesis => <<"gx">>,height => 1000,poi => <<"px">>,
               root_hash => <<"rx">>,top => <<"tx">>}]}]
(aeternity@localhost)2> aec_peer_messages:serialize_capabilities(2,Cs).
<<221,220,137,99,104,97,105,110,95,112,111,105,145,208,
  207,130,3,232,130,114,120,130,103,120,130,116,120,130,
  112,...>>
(aeternity@localhost)3> aeser_rlp:decode(v(2)).
[[<<"chain_poi">>,
  <<208,207,130,3,232,130,114,120,130,103,120,130,116,120,
    130,112,120>>]]
(aeternity@localhost)4> [[_,Sub]] = v(3).
[[<<"chain_poi">>,
  <<208,207,130,3,232,130,114,120,130,103,120,130,116,120,
    130,112,120>>]]
(aeternity@localhost)5> aeser_rlp:decode(Sub).
[[<<3,232>>,<<"rx">>,<<"gx">>,<<"tx">>,<<"px">>]]
Add support for decoding sub-structures. Example: ```erlang serialization_template(ping, ?PING_VSN) -> [ {versions, [#{items => [ {protocol, binary} , {vsns, [int]}] }] } , {port, int} ... ``` Previously, the template supported only `[type()]`, denoting a list where all elements are of the same type. This made it tricky to extend the list pattern. Also, complex subtypes aren't necessarily that descriptive: ```erlang capabilities_template(<<"chain_poi">>, ?PING_VSN) -> [{chain_poi, #{ items => [ {height, int} , {root_hash, binary} , {genesis, binary} , {top, binary} , {poi, binary} ]} }]. ``` The serialization would look like this: ```erlang (aeternity@localhost)1> Cs = [{chain_poi,[#{height => 1000, root_hash => <<"rx">>, genesis => <<"gx">>, top => <<"tx">>, poi => <<"px">>}]}]. [{chain_poi,[#{genesis => <<"gx">>,height => 1000,poi => <<"px">>, root_hash => <<"rx">>,top => <<"tx">>}]}] (aeternity@localhost)2> aec_peer_messages:serialize_capabilities(2,Cs). <<221,220,137,99,104,97,105,110,95,112,111,105,145,208, 207,130,3,232,130,114,120,130,103,120,130,116,120,130, 112,...>> (aeternity@localhost)3> aeser_rlp:decode(v(2)). [[<<"chain_poi">>, <<208,207,130,3,232,130,114,120,130,103,120,130,116,120, 130,112,120>>]] (aeternity@localhost)4> [[_,Sub]] = v(3). [[<<"chain_poi">>, <<208,207,130,3,232,130,114,120,130,103,120,130,116,120, 130,112,120>>]] (aeternity@localhost)5> aeser_rlp:decode(Sub). [[<<3,232>>,<<"rx">>,<<"gx">>,<<"tx">>,<<"px">>]] ```
ghallak (Migrated from gitlab.com) approved these changes 2023-08-17 20:17:49 +09:00
zxq9 commented 2023-08-17 23:36:52 +09:00 (Migrated from gitlab.com)

Created by: radrow

Comment please

              | #{items := [{field_name(), type()}]} %% Record with named fields represented as a map. Encoded as a list in the given order.
*Created by: radrow* Comment please ```suggestion:-0+0 | #{items := [{field_name(), type()}]} %% Record with named fields represented as a map. Encoded as a list in the given order. ```
zxq9 commented 2023-08-18 00:04:29 +09:00 (Migrated from gitlab.com)

Created by: radrow

Check for duplicates in Items?

decode_field(#{items := Items}, List) when length(List) =:= length(Items) ->
    Zipped = lists:zip(Items, List),
    lists:foldl(
      fun({{K, Type}, V}, Map) ->
              maps:is_key(K, Map) andalso error(badarg, duplicate_field),
              Map#{ K => decode_field(Type, V) }
      end, #{}, Zipped);
*Created by: radrow* Check for duplicates in `Items`? ```suggestion:-0+0 decode_field(#{items := Items}, List) when length(List) =:= length(Items) -> Zipped = lists:zip(Items, List), lists:foldl( fun({{K, Type}, V}, Map) -> maps:is_key(K, Map) andalso error(badarg, duplicate_field), Map#{ K => decode_field(Type, V) } end, #{}, Zipped); ```
uwiger commented 2023-08-18 03:41:40 +09:00 (Migrated from gitlab.com)

Check for duplicates in Items?

I guess we could, but there will be runtime overhead to catch what would be a compile-time error.

> Check for duplicates in `Items`? I guess we could, but there will be runtime overhead to catch what would be a compile-time error.
zxq9 commented 2023-08-18 04:08:18 +09:00 (Migrated from gitlab.com)

Created by: radrow

Review: Approved

*Created by: radrow* **Review:** Approved
ghallak commented 2023-08-18 16:01:47 +09:00 (Migrated from gitlab.com)

approved this merge request

approved this merge request
zxq9 commented 2023-08-18 21:40:50 +09:00 (Migrated from gitlab.com)

Merged by: uwiger at 2023-08-18 12:40:50 UTC

*Merged by: uwiger at 2023-08-18 12:40:50 UTC*
Sign in to join this conversation.
No description provided.