[erlang-questions] Protocol Mapping
Ulf Wiger
ulf@REDACTED
Wed Dec 19 17:36:27 CET 2012
For fun, I made a version with parse_trans which generates a module:
-module(mapping).
-compile(export_all).
-include_lib("parse_trans/include/codegen.hrl").
-define(MAP, [
{hello, 100},
{help, 101},
{done, 102}
]).
codegen(Mod) ->
codegen:gen_module(
{'$var',Mod}, [{encode,1},
{decode,1}],
[{encode, [fun({'$var',X}) ->
{'$var', Y}
end || {X, Y} <- ?MAP]},
{decode, [fun({'$var', Y}) ->
{'$var', X}
end || {X, Y} <- ?MAP]}]).
Eshell V5.9.2 (abort with ^G)
1> c(mapping).
{ok,mapping}
2> mapping:codegen(x).
[{attribute,1,module,x},
{attribute,37,export,[{encode,1},{decode,1}]},
{function,39,encode,1,
[{clause,39,[{atom,39,hello}],[],[{integer,40,100}]},
{clause,39,[{atom,39,help}],[],[{integer,40,101}]},
{clause,39,[{atom,39,done}],[],[{integer,40,102}]}]},
{function,42,decode,1,
[{clause,42,[{integer,42,100}],[],[{atom,43,hello}]},
{clause,42,[{integer,42,101}],[],[{atom,43,help}]},
{clause,42,[{integer,42,102}],[],[{atom,43,done}]}]}]
3> compile:forms(v(2),[]).
{ok,x,
<<70,79,82,49,0,0,2,48,66,69,65,77,65,116,111,109,0,0,0,
71,0,0,0,9,1,120,...>>}
4> code:load_binary(x,"/tmp/x.beam",element(3,v(3))).
{module,x}
5> x:encode(hello).
100
6> x:decode(100).
hello
The codegen:gen_module/3 pseudo-function is documented here:
https://github.com/esl/parse_trans/blob/master/doc/parse_trans_codegen.md#gen_module3
BR,
Ulf W
On 19 Dec 2012, at 14:05, Attila Rajmund Nohl wrote:
> Hello!
>
> You could try to generate the code that implements the first pattern.
>
> 2012/12/19 Steve Davis <steven.charles.davis@REDACTED>:
>> Hi,
>>
>> I'm frequently facing situations with binary protocol
>> translations/transforms where I need to map binary codes to e.g. atoms and
>> back.
>>
>> This is of course "easy" in Erlang, but suffers some inconveniences. I've
>> attached a code snippet distilled down to the simplest case to explain my
>> issue.
>>
>> I'm sure the first codec pattern below is familiar, and for sure is
>> efficient.
>> However, there are multiple places where updating is required to add new
>> message types.
>>
>> The second pattern is much less usual, but handy as one line achieves the
>> addition of a new message type.
>> It helps particularly when there is more than one pairing involved (e.g.
>> {atom, code, status_message}).
>>
>> For sure this cannot be something nobody has seen/thought about. I'm
>> wondering if anyone has comment on this, and maybe suggestions for
>> approaches that I haven't thought of.
>>
>> /s
>> -------
>> -module(mapping).
>>
>> -compile(export_all).
>>
>> %% traditional
>>
>> -define(HELLO, 100).
>> -define(HELP, 101).
>> -define(DONE, 102).
>>
>> encode(hello) -> ?HELLO;
>> encode(help) -> ?HELP;
>> encode(done) -> ?DONE.
>>
>> decode(?HELLO) -> hello;
>> decode(?HELP) -> help;
>> decode(?DONE) -> done.
>>
>> %% alternative
>>
>> -define(MAP, [
>> {hello, 100},
>> {help, 101},
>> {done, 102}
>> ]).
>>
>> encode0(X) ->
>> {X, Y} = lists:keyfind(X, 1, ?MAP),
>> Y.
>>
>> decode0(X) ->
>> {Y, X} = lists:keyfind(X, 2, ?MAP),
>> Y.
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
Ulf Wiger, Co-founder & Developer Advocate, Feuerlabs Inc.
http://feuerlabs.com
More information about the erlang-questions
mailing list