lib/validators/exclusion.ex

defmodule Dsv.Exclusion do
  use Dsv.Validator

  @moduledoc """
  Ensure a value is not on the forbidden values list.
  Dsv.Exclusion module provides functions to determine if a value is not present in a list.
  """

  message("Value <%= inspect(data) %> can't be on the list <%= inspect(options) %>")

  @doc """
  The `valid?/2` function evaluates whether a given value is not present in a list.

  ## Parameters

    * `value` - The value to be checked.
    * `list` - The list in which the presence of the value is checked.

  ## Returns

  A boolean value:

  - `true` if `value` is not present in `list`.
  - `false` if `value` is present in `list`.

  ## Examples

      iex> Dsv.Exclusion.valid?("test", ["a", :b, "c", %{a: :b}])
      :true

      iex> Dsv.Exclusion.valid?("test", ["test", :b, "c", %{a: :b}])
      :false

      iex> Dsv.Exclusion.valid?("test", [])
      :true

      iex> Dsv.Exclusion.valid?(nil, [nil, 1, 2, 3])
      :false

      iex> Dsv.Exclusion.valid?(nil, [1, 2, 3])
      :true
  """
  # @spec valid?(data :: any, options :: [any]) :: boolean
  def valid?(data, [{:options, options}]), do: valid?(data, options)
  def valid?(data, options) when is_list(options), do: data not in options

  @doc """
  The `validate/2` function evaluates whether a given value is not present in a list.

  ## Parameters

    * `value` - The value to be checked.
    * `list` - The list in which the presence of the value is checked.

  ## Returns

  - `:ok` if `value` is not present in `list`.
  - `{:error, message}` if `value` is present in `list`.

  ## Examples

      iex> Dsv.Exclusion.validate("test", ["a", :b, "c", %{a: :b}])
      :ok

      iex> Dsv.Exclusion.validate("test", ["test", :b, "c", %{a: :b}])
      {:error, ~s(Value "test" can't be on the list ["test", :b, "c", %{a: :b}])}

      iex> Dsv.Exclusion.validate("test", [])
      :ok

      iex> Dsv.Exclusion.validate(nil, [nil, 1, 2, 3])
      {:error, ~s(Value nil can't be on the list [nil, 1, 2, 3])}

      iex> Dsv.Exclusion.validate(nil, [nil, 1, 2, 3], message: "Provided value is not allowed.")
      {:error, "Provided value is not allowed."}

      iex> Dsv.Exclusion.validate(nil, [1, 2, 3])
      :ok
  """
  def validate(data, options), do: super(data, options)

  @doc """
  The `validate/3` function evaluates whether a given value is not present in a list.

  ## Parameters

    * `value` - The value to be checked.
    * `list` - The list in which the presence of the value is checked.
    * `message` - The message that will be returned in case of failure.

  ## Returns

  - `:ok` if `value` is not present in `list`.
  - `{:error, message}` if `value` is present in `list`.

  ## Examples
      iex> Dsv.Exclusion.validate(nil, [nil, 1, 2, 3], message: "Provided value is not allowed.")
      {:error, "Provided value is not allowed."}

      iex> Dsv.Exclusion.validate(nil, [nil, 1, 2, 3], "Provided value is not allowed.")
      {:error, "Provided value is not allowed."}

      iex> Dsv.Exclusion.validate(nil, [1, 2, 3], "Provided value is not allowed.")
      :ok
  """
  def validate(data, options, [{:message, message}]),
    do: validate(data, [{:options, options}, {:message, message}])

  def validate(data, options, message),
    do: validate(data, [{:options, options}, {:message, message}])
end