lib/flamel/wrap.ex

defmodule Flamel.Wrap do
  @moduledoc """
  Some helper functions for wrapping and unwraping values in tuples
  """

  defdelegate ok?(value), to: Flamel.Result
  defdelegate error?(value), to: Flamel.Result
  defdelegate unwrap_ok!(value), to: Flamel.Result, as: :ok!
  defdelegate unwrap_ok_or_nil(value), to: Flamel.Result, as: :ok_or_nil
  defdelegate unwrap_error!(value), to: Flamel.Result, as: :error!
  defdelegate unwrap_error_or_nil(value), to: Flamel.Result, as: :error_or_nil

  @doc """
  Takes an {:ok, value} or {:error, message} tuple and returns the value

  ## Examples

      iex> Flamel.Wrap.unwrap({:ok, []})
      []

      iex> Flamel.Wrap.unwrap({:error, "message"})
      "message"
  """
  def unwrap({:ok, value}), do: value
  def unwrap({:error, value}), do: value
  def unwrap({:reply, value}), do: value
  def unwrap({:noreply, value}), do: value
  def unwrap({:continue, value}), do: value
  def unwrap({:cont, value}), do: value

  @doc """
  Takes a value and wraps it in a tuple with the specified
  atom as the first item

  ## Examples

      iex> Flamel.Wrap.wrap(:ok, [])
      {:ok, []}

      iex> Flamel.Wrap.wrap(:error, "message")
      {:error, "message"}

      iex> Flamel.Wrap.wrap(:stop, :shutdown, %{})
      {:stop, :shutdown, %{}}
  """
  @spec wrap(atom(), term()) :: {atom(), term()}
  def wrap(item, value), do: {item, value}

  @spec wrap(atom(), term(), term()) :: {atom(), term(), term()}
  def wrap(item, first, second), do: {item, first, second}

  @doc """
  Takes a value and wraps it in a :ok tuple

  ## Examples

      iex> Flamel.Wrap.ok([])
      {:ok, []}

      iex> Flamel.Wrap.ok("message")
      {:ok, "message"}
  """
  @spec ok(term()) :: {:ok, term()}
  def ok(value), do: Flamel.Wrap.wrap(:ok, value)

  @spec ok(term(), term()) :: {:ok, term(), term()}
  def ok(first, second), do: Flamel.Wrap.wrap(:ok, first, second)

  @doc """
  Takes a value and wraps it in a :error tuple

  ## Examples

      iex> Flamel.Wrap.error([])
      {:error, []}

      iex> Flamel.Wrap.error("message")
      {:error, "message"}

      iex> Flamel.Wrap.error(:first, :second)
      {:error, :first, :second}
  """
  @spec error(term()) :: {:error, term()}
  def error(value), do: Flamel.Wrap.wrap(:error, value)

  @spec error(term(), term()) :: {:error, term(), term()}
  def error(first, second), do: Flamel.Wrap.wrap(:error, first, second)

  @doc """
  Takes a value and wraps it in a :noreply tuple

  ## Examples

      iex> Flamel.Wrap.noreply([])
      {:noreply, []}

      iex> Flamel.Wrap.noreply("message")
      {:noreply, "message"}

      iex> Flamel.Wrap.noreply(:first, :second)
      {:noreply, :first, :second}
  """
  @spec noreply(term()) :: {:noreply, term()}
  def noreply(value), do: Flamel.Wrap.wrap(:noreply, value)

  @spec noreply(term(), term()) :: {:noreply, term(), term()}
  def noreply(first, second), do: Flamel.Wrap.wrap(:noreply, first, second)

  @doc """
  Takes a value and wraps it in a :reply tuple

  ## Examples

      iex> Flamel.Wrap.reply([])
      {:reply, []}

      iex> Flamel.Wrap.reply("message")
      {:reply, "message"}

      iex> Flamel.Wrap.reply(:first, :second)
      {:reply, :first, :second}
  """
  @spec reply(term()) :: {:reply, term()}
  def reply(value), do: Flamel.Wrap.wrap(:reply, value)

  @spec reply(term(), term()) :: {:reply, term(), term()}
  def reply(first, second), do: Flamel.Wrap.wrap(:reply, first, second)

  @doc """
  Takes a value and wraps it in a :cont tuple

  ## Examples

      iex> Flamel.Wrap.cont([])
      {:cont, []}

      iex> Flamel.Wrap.cont("message")
      {:cont, "message"}
  """
  @spec cont(term()) :: {:cont, term()}
  def cont(value), do: Flamel.Wrap.wrap(:cont, value)

  @doc """
  Takes a value and wraps it in a :continue tuple

  ## Examples

      iex> Flamel.Wrap.continue(:load_something)
      {:continue, :load_something}

      iex> Flamel.Wrap.continue("message")
      {:continue, "message"}

      iex> Flamel.Wrap.continue(:first, :second)
      {:continue, :first, :second}
  """
  @spec continue(term()) :: {:continue, term()}
  def continue(value), do: Flamel.Wrap.wrap(:continue, value)

  @spec continue(term(), term()) :: {:continue, term(), term()}
  def continue(first, second), do: Flamel.Wrap.wrap(:continue, first, second)

  @doc """
  Takes a value and wraps it in a :stop tuple

  ## Examples

      iex> Flamel.Wrap.stop(:shutdown, %{})
      {:stop, :shutdown, %{}}
  """
  @spec stop(term(), term()) :: {:stop, term(), term()}
  def stop(first, second), do: Flamel.Wrap.wrap(:stop, first, second)
end