lib/fussy/validators/atom.ex

defmodule Fussy.Validators.Atom do
  @behaviour Fussy.Validator

  defstruct [:atom]

  @opaque t :: %__MODULE__{}

  @spec new(atom()) :: __MODULE__.t()

  def new(atom), do: %__MODULE__{atom: atom}

  @impl true
  def validate(%__MODULE__{atom: atom}, term) when atom == term, do: {:ok, term}

  @impl true
  def validate(%__MODULE__{atom: atom} = v, term) when is_binary(term) do
    validate(v, String.to_existing_atom(term))
  rescue
    _ in ArgumentError ->
      {:error, ["must be #{inspect(atom)} or \"#{atom}\""]}
  end

  @impl true
  def validate(%__MODULE__{atom: atom}, _),
    do: {:error, ["must be #{inspect(atom)} or \"#{atom}\""]}
end