defmodule MyspaceIPFS.Utils do
@moduledoc """
Some common functions that are used throughout the library.
"""
@doc """
Filter out any empty values from a list.
Removes nil, {}, [], and "".
"""
@spec filter_empties(list) :: list
def filter_empties(list) do
list
|> Enum.filter(fn x -> x != nil end)
|> Enum.filter(fn x -> x != {} end)
|> Enum.filter(fn x -> x != [] end)
|> Enum.filter(fn x -> x != "" end)
end
@doc """
Extracts the data from a response. Given a response, it will structure the
data in a way that is easier to work with. IPFS only sends strings. This
function will convert the string to a list of maps.
"""
@spec map_response_data(any) :: list
def map_response_data(response) do
extract_data_from_plain_response(response)
|> filter_empties()
|> convert_list_of_tuples_to_map()
end
@doc """
Wraps the data in an elixir standard response tuple.
{:ok, data} or {:error, data}
"""
@spec okify(any) :: {:ok, any} | {:error, any}
def okify({:error, _} = err), do: err
def okify(res), do: {:ok, res}
@doc """
Unlists a list if it only contains one element.
"""
@spec unlist(list) :: any
def unlist(list) do
case list do
[x] -> x
_ -> list
end
end
# Private functions
defp convert_list_of_tuples_to_map(list) do
list
|> filter_empties()
|> Enum.map(fn x -> list_of_tuples_to_map(x) end)
end
defp extract_data_from_plain_response(binary) do
binary
|> split_string_by_newline()
|> filter_empties()
|> Enum.map(fn x -> extract_tuples_from_string(x) end)
end
defp extract_tuples_from_string(string) do
string
|> split_string_by_comma()
|> filter_empties()
|> Enum.map(fn x -> tuplestring_to_tuple(x) end)
end
defp filter_empty_keys(map) do
map
|> Enum.reject(fn {x, _} -> is_nil(x) end)
|> Enum.reject(fn {x, _} -> x == "" end)
end
defp get_value_from_string(string) do
# IO.puts("ValueString: #{string}")
with data = Regex.run(~r/:"(.+?)"/, string),
true <- not is_nil(data) do
Enum.at(data, 1)
else
_ -> nil
end
end
defp get_name_from_string(string) do
# IO.puts("NameString: #{string}")
with data = Regex.run(~r/"(.+?)":/, string),
true <- not is_nil(data) do
Enum.at(data, 1)
else
_ -> nil
end
end
defp list_of_tuples_to_map(list) do
list
|> filter_empties()
|> Enum.into(%{})
|> filter_empty_keys()
end
defp split_string_by_newline(string) do
Regex.split(~r/\n/, string)
end
defp split_string_by_comma(string) do
Regex.split(~r/,/, string)
end
defp tuplestring_to_tuple(string) do
{get_name_from_string(string), get_value_from_string(string)}
end
end