storage behavior
@type handler() :: pid() | :file.fd()
@type path() :: String.t()
@type permision() :: non_neg_integer()
@type t() :: struct()
@callback append(t(), handler(), binary()) :: :ok | {:error, term()}
@callback close(t(), handler()) :: :ok | {:error, term()}
@callback mkdir(t(), path(), permision()) :: :ok
@callback new(opts :: keyword()) :: t()
@callback open(t(), path(), permision()) :: {:ok, handler()} | {:error, term()}
@callback read_all(t(), path()) :: {:ok, binary()} | {:error, term()}
@callback rename(t(), path(), path()) :: :ok | {:error, term()}
@callback rm(t(), path()) :: :ok | {:error, term()}
@callback sync(t(), handler()) :: :ok | {:error, term()}
@callback write_all(t(), path(), binary()) :: :ok | {:error, term()}
@spec append(t(), handler(), binary()) :: :ok | {:error, term()}
@spec close(t(), handler()) :: :ok | {:error, term()}
@spec mkdir(t(), path(), permision()) :: :ok
@spec open(t(), path(), permision()) :: {:ok, handler()} | {:error, term()}
@spec read_all(t(), path()) :: {:ok, binary()} | {:error, term()}
@spec rename(t(), path(), path()) :: :ok | {:error, term()}
@spec rm(t(), path()) :: :ok | {:error, term()}
@spec sync(t(), handler()) :: :ok | {:error, term()}
@spec write_all(t(), path(), binary()) :: :ok | {:error, term()}