Current section
Files
Jump to
Current section
Files
lib/denlixir/decoder.ex
defmodule Benlixir.Decoder do
require IEx
def decode(input) when is_binary(input) do
"d"<>rest = input
[ master,_ ] = decode_map(%{}, %{}, rest)
{:ok, master}
end
def decode(_) do
{:error, "Bad input: must be a bitstring"}
end
defp decode_item(map, << ch::binary-size(1), rest::binary>>) when ch == "d" do
decode_map(map, %{}, rest)
end
defp decode_item(map, << ch::binary-size(1), rest::binary >>) when ch == "l" do
decode_list(map, [], rest)
end
defp decode_item(map, << ch::binary-size(1), rest::binary >>) when ch == "i" do
decode_int(map, rest)
end
defp decode_item(map, rest), do: decode_string(map, rest)
defp decode_int(map, rest) do
[int, rest] = String.split(rest, "e", parts: 2)
[map, {int, rest}]
end
defp decode_map(master, map, "e"<>rest) do
master = Map.merge(master, map)
[map, {master, rest}]
end
defp decode_map(master, map, rest) do
[master, {key, rest}] = decode_item(master, rest)
[master, {value, rest}] = decode_item(master, rest)
key = String.to_atom(key)
map = Map.put(map, key, value)
decode_map(master, map, rest)
end
defp decode_list(map, list, "e"<>rest), do: [map, {Enum.reverse(list), rest}]
defp decode_list(map, list, rest) do
[map, {item, rest}] = decode_item(map, rest)
decode_list(map, [item | list], rest)
end
defp decode_string(map,rest) do
[count, rest] = String.split(rest, ":", parts: 2)
count = String.to_integer(count)
<< word::binary-size(count), rest::binary >> = rest
[map, {word, rest} ]
end
end