folz / bento

:bento: A fast, correct, pure-Elixir library for reading and writing Bencoded metainfo (.torrent) files.
Mozilla Public License 2.0
95 stars 14 forks source link

Unable to encode Tuple #17

Closed mogeko closed 1 year ago

mogeko commented 1 year ago

When Bento.encode/1 encounters a Tuple, an error will be reported.

iex(1)> Bento.encode {:does, :not, :work}     
** (Protocol.UndefinedError) protocol Bento.Encoder not implemented for {:does, :not, :work} of type Tuple
    (bento 1.0.0-dev) lib/bento/encoder.ex:35: Bento.Encoder.impl_for!/1
    (bento 1.0.0-dev) lib/bento/encoder.ex:56: Bento.Encoder.encode/1
    (bento 1.0.0-dev) lib/bento.ex:36: Bento.encode!/2
    (bento 1.0.0-dev) lib/bento.ex:22: Bento.encode/2
    iex:1: (file)
mogeko commented 1 year ago

This problem can be solved by @fallback_to_any.

defprotocol Bento.Encoder do

  @type bencodable :: atom() | String.t() | integer() | map() | Enumerable.t()
  @type t :: iodata()

  @fallback_to_any true
  @spec encode(bencodable) :: t | :error
  def encode(value)
end

defimpl Bento.Encoder, for: Any do
  def encode(_any), do: :error
end

Now, any type that does not meet expectations (e.g. Tuple, PID, Port...) will return :error instead of reporting an error.

mogeko commented 1 year ago

Or, as a better choice, we can raise an Bento.EncodeError directly.

defimpl Bento.Encoder, for: Any do
  def encode(_any), do: raise Bento.EncodeError
end

It can be rescued by Bento.encode/1.