defmodule Maru.Params.Runtime do defstruct name: nil, required: false, source: nil, nested: nil, children: [], ignore_func: nil, blank_func: nil, parser_func: nil alias Maru.Params.ParseError def parse_params(params_runtime, params, options \\ []) do parse_params(params_runtime, params, options, %{}) end def parse_params([], _params, _options, result), do: result def parse_params([h | t], params, options, result) do if h.ignore_func.(result) do throw(:ignore) end source = case Keyword.get(options, :keys, :strings) do :strings -> to_string(h.source) _ when is_atom(h.source) -> h.source :atoms when is_binary(h.source) -> String.to_atom(h.source) :atoms! when is_binary(h.source) -> String.to_existing_atom(h.source) end passed? = Map.has_key?(params, source) value = Map.get(params, source) nested = h.nested parsed = if value in [nil, "", ~c"", %{}] do h.blank_func.({value, passed?}) else h.parser_func.({:ok, value}, options) end case parsed do :ignore -> parse_params(t, params, options, result) {:error, step, reason} -> raise Maru.Params.ParseError, attribute: h.name, step: step, reason: reason {:default, value} -> parse_params(t, params, options, Map.put(result, h.name, value)) {:ok, value} when nested == :map -> value = parse_params(h.children, value, options, %{}) parse_params(t, params, options, Map.put(result, h.name, value)) {:ok, value} when nested == :list_of_map -> value = Enum.map(value, fn item -> parse_params(h.children, item, options, %{}) end) parse_params(t, params, options, Map.put(result, h.name, value)) {:ok, value} when nested == :list_of_single -> value = Enum.map(value, fn {:ok, item} -> item {:error, step, reason} -> raise ParseError, attribute: h.name, step: step, reason: reason end) parse_params(t, params, options, Map.put(result, h.name, value)) {:ok, value} when nested == nil -> parse_params(t, params, options, Map.put(result, h.name, value)) end catch :ignore -> parse_params(t, params, options, result) end end