defmodule QuackDB.ResultMapper do @moduledoc false @spec rows_to_structs(QuackDB.Result.t(), module()) :: [struct()] def rows_to_structs(%QuackDB.Result{columns: columns, rows: rows}, module) when is_list(columns) and is_list(rows) do fields = Map.keys(struct!(module)) -- [:__struct__] keys = Enum.map(columns, &normalize_key/1) Enum.map(rows, fn row -> keys |> Enum.zip(row) |> Map.new() |> Map.take(fields) |> then(&struct!(module, &1)) end) end def rows_to_structs(%QuackDB.Result{}, _module), do: [] defp normalize_key(key) when is_binary(key) do key |> Macro.underscore() |> String.to_existing_atom() rescue ArgumentError -> key end end