/run Torrent client/parser.erl
Erlang | 73 lines | 52 code | 9 blank | 12 comment | 1 complexity | 052e0cab887b57fdd2868309cf9f1d87 MD5 | raw file
1-module(parser). 2 3-export([decode/1, encode/1]). 4-define(DICT, dict). 5 6decode(Data) -> 7 dec(Data). 8 % case catch dec(Data) of 9 % {'EXIT', _} -> 10 % {error, unparsed}; 11 % {Res, _} -> 12 % {ok, Res} 13 % end. 14 15encode(Struct) -> 16 iolist_to_binary(enc(Struct)). 17 18%%-------------------------------------------------------------------- 19%% Decoding 20%%-------------------------------------------------------------------- 21dec(<<$l, Tail/binary>>) -> 22 dec_list(Tail, []); 23dec(<<$d, Tail/binary>>) -> 24 dec_dict(Tail, ?DICT:new()); 25dec(<<$i, Tail/binary>>) -> 26 dec_int(Tail, []); 27dec(Data) -> 28 dec_string(Data, []). 29 30dec_int(<<$e, Tail/binary>>, Acc) -> 31 {list_to_integer(lists:reverse(Acc)), Tail}; 32dec_int(<<X, Tail/binary>>, Acc) -> 33 dec_int(Tail, [X|Acc]). 34 35dec_string(<<$:, Tail/binary>>, Acc) -> 36 Int = list_to_integer(lists:reverse(Acc)), 37 <<Str:Int/binary, Rest/binary>> = Tail, 38 {Str, Rest}; 39dec_string(<<X, Tail/binary>>, Acc) -> 40 dec_string(Tail, [X|Acc]). 41 42dec_list(<<$e, Tail/binary>>, Acc) -> 43 {{list, lists:reverse(Acc)}, Tail}; 44dec_list(Data, Acc) -> 45 {Res, Tail} = dec(Data), 46 dec_list(Tail, [Res|Acc]). 47 48dec_dict(<<$e, Tail/binary>>, Acc) -> 49 {{dict, Acc}, Tail}; 50dec_dict(Data, Acc) -> 51 {Key, Tail1} = dec(Data), 52 {Val, Tail2} = dec(Tail1), 53 dec_dict(Tail2, ?DICT:store(Key, Val, Acc)). 54 55%%-------------------------------------------------------------------- 56%% Encoding 57%%-------------------------------------------------------------------- 58enc(Int) when is_integer(Int) -> 59 IntBin = list_to_binary(integer_to_list(Int)), 60 [$i, IntBin, $e]; 61enc(Str) when is_list(Str) -> 62 enc(list_to_binary(Str)); 63enc(Str) when is_binary(Str) -> 64 IntBin = list_to_binary(integer_to_list(size(Str))), 65 [IntBin, $:, Str]; 66enc({list, List}) when is_list(List) -> 67 [$l, [enc(Elem) || Elem <- List], $e]; 68enc({dict, Dict}) -> 69 Data = lists:map( 70 fun({Key, Val}) when is_list(Key) or is_binary(Key) -> 71 [enc(Key), enc(Val)] 72 end, lists:keysort(1, ?DICT:to_list(Dict))), 73 [$d, Data, $e].