Current section

Files

Jump to
kvasir_agent lib kvasir command decoder.ex
Raw

lib/kvasir/command/decoder.ex

defmodule Kvasir.Command.Decoder do
def decode(value, meta \\ %Kvasir.Command.Meta{}) do
with {:ok, data} <- Jason.decode(value) do
do_decode(data, Kvasir.Command.Meta.decode(data["meta"], meta))
end
end
defp do_decode(data, meta) do
command = Module.concat("Elixir", data["type"])
if Code.ensure_compiled?(command),
do: decode_command(command, data["payload"], meta),
else: {:error, :unknown_comand}
end
defp decode_command(command, data, meta),
do: do_decode_command(command.__command__(:fields), data, %{__meta__: meta}, command)
defp do_decode_command([], _data, acc, command), do: {:ok, struct!(command, acc)}
defp do_decode_command([{property, type, opts} | props], data, acc, command) do
with {:ok, value} <- Map.fetch(data, to_string(property)),
{:ok, parsed_value} <- Kvasir.Type.load(type, value, opts) do
do_decode_command(props, data, Map.put(acc, property, parsed_value), command)
else
:error ->
if opts[:optional],
do: do_decode_command(props, data, acc, command),
else: {:error, :missing_field}
error = {:error, _} ->
error
end
end
end