lib/lapin/message/payload.ex

defprotocol Lapin.Message.Payload do
  @moduledoc """
  You can use this protocol to implement a custom message payload transformation.
  For example you could implement a JSON message with a predefined structure by
  first implementing a struct for your payload:

  ```elixir
  defmodule Example.Payload do
    defstruct [a: "a", b: "b", c: nil]
  end
  ```

  and then providing an implementation of `Lapin.Message.Payload` for it:

  ```elixir
  defimpl Lapin.Message.Payload, for: Example.Payload do
    def content_type(_payload), do: "application/json"
    def encode(payload), do: Poison.encode(payload)
    def decode_into(payload, data), do: Poison.decode(data, as: payload)
  end
  ```

  Please note you will need to add the `poison` library as a dependency on in
  your project `mix.exs` for this to work.

  Lapin will automatically encode and set the `content-type` property on publish.

  To decode messages before consuming, implement the `payload_for/2` callback
  of `Lapin.Connection` and return an instance of the payload to decode into.

  ```elixir
  defmodule Example.Connection do
    def payload_for(_channel, _message), do: %Example.Payload{}
  end
  ```

  The default implementation simply returns the unaltered binary data and sets
  the message `content-type` property to `nil`.
  """

  @typedoc "Data type implementing the `Lapin.Message.Payload` protocol"
  @type t :: term

  @typedoc "MIME content-type as defined by RFC 2045"
  @type content_type :: String.t() | nil

  @typedoc "Encode function return values"
  @type on_encode :: {:ok, binary} | {:error, term}

  @typedoc "Decode function return values"
  @type on_decode :: {:ok, t} | {:error, term}

  @doc """
  Returns the message `content-type`
  """
  @spec content_type(t) :: content_type
  def content_type(payload)

  @doc """
  Returns the encoded payload body
  """
  @spec encode(t) :: on_encode
  def encode(payload)

  @doc """
  Returns the payload with message data decoded
  """
  @spec decode_into(t, binary) :: on_decode
  def decode_into(payload, data)
end