defmodule Salty.Multipart do defmodule Spec do @callback update(binary(), binary()) :: {:ok, binary()} | {:error, atom()} @callback final(binary()) :: {:ok, binary()} | {:error, atom()} @callback final_verify(binary(), binary()) :: :ok | {:error, atom()} end defmodule SignSpec do @callback update(binary(), binary()) :: {:ok, binary()} | {:error, atom()} @callback final(binary(), binary()) :: {:ok, binary()} | {:error, atom()} @callback final_verify(binary(), binary(), binary()) :: :ok | {:error, atom()} end def init(spec) do init_return(spec, spec.init()) end def init(spec, arg1) do init_return(spec, spec.init(arg1)) end def init(spec, arg1, arg2) do init_return(spec, spec.init(arg1, arg2)) end defp init_return(spec, result) do case result do {:ok, next} -> {:ok, {spec, next}} {:error, reason} -> {:error, reason} end end @doc """ """ def update({:ok, {spec, state}}, input) do update({spec, state}, input) end def update({:error, _} = err, _) do err end def update({spec, state}, input) do case spec.update(state, input) do {:ok, next} -> {:ok, {spec, next}} {:error, reason} -> {:error, reason} end end @doc """ """ def final({:ok, {spec, state}}) do final({spec, state}) end def final({:error, _} = err) do err end def final({spec, state}) do spec.final(state) end @doc """ """ def final_verify({:ok, {spec, state}}, expected) do final_verify({spec, state}, expected) end def final_verify({:error, _} = err, _) do err end def final_verify({spec, state}, expected) do spec.final_verify(state, expected) end end