%% @doc Backend source for the encoding of erl_bencode -module(encode). -export([encode/1]). -import(string, [concat/2]). -spec start_encode(Encode, List) -> RetList | {error, Reason} when Encode :: term(), List :: list(), RetList :: list(), Reason :: atom(). start_encode(Encode, List) when is_map(Encode) -> encode_map(Encode, List); start_encode(Encode, List) when is_list(Encode) -> determ_list_or_string(Encode, List); start_encode(Encode, List) when is_number(Encode) -> encode_int(Encode, List); start_encode(_,_) -> {error, badform}. -spec determ_list_or_string(Encode, List) -> RetList when Encode :: term(), List :: list(), RetList :: list(). determ_list_or_string(Encode, List) -> Bool = io_lib:char_list(Encode), if Bool -> encode_string(Encode, List); true -> encode_list(Encode, List) end. -spec encode_list(Encode, List) -> {ok, RetList} when Encode :: term(), List :: list(), RetList :: list(). encode_list(Encode, List) -> {ok, TempHead} = iter_list(Encode, concat(List, "l")), {ok, concat(TempHead, "e")}. -spec iter_list(Encode, List) -> {ok, RetList} when Encode :: term(), List :: list(), RetList :: list(). iter_list([], List) -> {ok, List}; iter_list([H | T], List) -> {ok, NewHead} = start_encode(H, List), iter_list(T, NewHead). -spec encode_map(Encode, List) -> {ok, RetList} when Encode :: term(), List :: list(), RetList :: list(). encode_map(Encode, List) -> ListOfKeys = maps:keys(Encode), {ok, TempHead} = iter_map(Encode, concat(List, "d"), ListOfKeys), {ok, concat(TempHead, "e")}. -spec iter_map(Encode, List, Keys) -> {ok, RetList} when Encode :: term(), List :: list(), Keys :: list(), RetList :: list(). iter_map(_, List, []) -> {ok, List}; iter_map(Encode, List, [Key | Tail]) -> {ok, TempHead} = start_encode(Key, List), {ok, NewHead} = start_encode(maps:get(Key, Encode), TempHead), iter_map(Encode, NewHead, Tail). -spec encode_int(Encode, List) -> {ok, RetList} when Encode :: term(), List :: list(), RetList :: list. encode_int(Encode, List) -> IntList = integer_to_list(Encode), {ok, concat(List, concat(concat("i", IntList), "e"))}. -spec encode_string(Encode, List) -> {ok, RetList} when Encode :: term(), List :: list(), RetList :: list(). encode_string(Encode, List) -> Len = string:length(Encode), {ok, concat(List, concat(concat(integer_to_list(Len), ":"), Encode))}. -spec encode(Encode) -> {ok, Value} | {error, Reason} when Encode :: term(), Value :: list(), Reason :: atom(). encode(Encode) -> Value = start_encode(Encode, []), case Value of {error, _Reason} -> Value; Value -> Value end.