lib/schema_validator/result.ex

defmodule Mecto.SchemaValidator.Result do
  @moduledoc """
  Used by `Mecto.SchemaValidator` to track the results of schema validation.
  """

  alias __MODULE__, as: Self

  defstruct path: [], ok: %{}, error: []

  def merge(%Self{} = result, key, value) when is_atom(value),
    do: %{result | ok: Map.put(result.ok, key, value)}

  def merge(%Self{} = result, key, %Self{} = other) do
    if Enum.empty?(other.error) do
      %{result | ok: Map.put(result.ok, key, other.ok)}
    else
      %{result | error: result.error ++ other.error}
    end
  end

  def merge(%Self{} = result, key, other) when is_list(other) do
    other =
      Enum.reduce(other, %Self{}, fn {key, a}, b ->
        merge(b, key, a)
      end)

    merge(result, key, other)
  end

  def add_error(%Self{} = result, field, error) do
    path =
      result.path
      |> Enum.concat([field])
      |> Enum.reduce(fn
        path_entry, path when is_integer(path_entry) ->
          "#{path}[#{path_entry}]"

        path_entry, path ->
          "#{path}.#{path_entry}"
      end)

    error = "#{path} #{error}"

    %{result | error: [error | result.error]}
  end
end