/run Torrent client/parser.erl

http://github.com/anonymous-admin/anonymous · Erlang · 73 lines · 52 code · 9 blank · 12 comment · 1 complexity · 052e0cab887b57fdd2868309cf9f1d87 MD5 · raw file

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