Current section

Files

Jump to
yaml_elixir lib yaml_elixir mapper.ex
Raw

lib/yaml_elixir/mapper.ex

defmodule YamlElixir.Mapper do
def process(nil, options), do: empty_container(options)
def process(yaml, options) when is_list(yaml), do: Enum.map(yaml, &process(&1, options))
def process(yaml, options) do
yaml
|> _to_map(options)
|> extract_map(options)
end
defp extract_map(nil, options), do: empty_container(options)
defp extract_map(map, _), do: map
defp _to_map({:yamerl_doc, document}, options), do: _to_map(document, options)
defp _to_map({:yamerl_seq, :yamerl_node_seq, _tag, _loc, seq, _n}, options),
do: Enum.map(seq, &_to_map(&1, options))
defp _to_map({:yamerl_map, :yamerl_node_map, _tag, _loc, map_tuples}, options),
do: _tuples_to_map(map_tuples, empty_container(options), options)
defp _to_map(
{:yamerl_str, :yamerl_node_str, _tag, _loc, <<?:, _::binary>> = element},
options
),
do: key_for(element, options)
defp _to_map({:yamerl_null, :yamerl_node_null, _tag, _loc}, _options), do: nil
defp _to_map({_yamler_element, _yamler_node_element, _tag, _loc, elem}, _options), do: elem
defp _tuples_to_map([], map, _options), do: map
defp _tuples_to_map([{key, val} | rest], map, options) do
agregator_module = maps_aggregator(options)
case key do
{:yamerl_seq, :yamerl_node_seq, _tag, _log, _seq, _n} ->
_tuples_to_map(
rest,
agregator_module.(map, _to_map(key, options), _to_map(val, options)),
options
)
{_yamler_element, _yamler_node_element, _tag, _log, name} ->
_tuples_to_map(
rest,
agregator_module.(map, key_for(name, options), _to_map(val, options)),
options
)
end
end
defp key_for(<<?:, name::binary>> = original_name, options) do
options
|> Keyword.get(:atoms)
|> maybe_atom(name, original_name)
end
defp key_for(name, _options), do: name
defp maybe_atom(true, name, _original_name), do: String.to_atom(name)
defp maybe_atom(_, _name, original_name), do: original_name
defp empty_container(options) do
with true <- Keyword.get(options, :maps_as_keywords) do
[]
else
_ -> %{}
end
end
defp append_kv(list, key, value),
do: [{key, value} | list]
defp append_list_kv(list, key, value),
do: list ++ [{String.to_atom(key), value}]
defp maps_aggregator(options) do
if Keyword.get(options, :maps_as_keywords) do
if Keyword.get(options, :atoms) do
&append_list_kv/3
else
&append_kv/3
end
else
&Map.put_new/3
end
end
end