Skip to main content

lib/chat_code/encoder.ex

defmodule GW2.ChatCode.Encoder do
  @moduledoc false

  @uint24_max 0xFF_FF_FF

  @callback encode(GW2.ChatCode.parsed_struct()) :: {:ok, binary()} | {:error, atom()}
  @callback decode(binary()) :: {:ok, GW2.ChatCode.parsed_struct()} | {:error, atom()}

  ## Helpers

  @spec encode_id(term()) :: {:ok, binary()} | {:error, :invalid_id}
  def encode_id(id) when is_integer(id) and id in 0..@uint24_max do
    {:ok, <<id::little-24>>}
  end

  def encode_id(_), do: {:error, :invalid_id}

  @spec decode_id(binary()) :: {:ok, {non_neg_integer(), binary()}} | {:error, :invalid_id}
  def decode_id(<<id::little-24, 0x00, rest::binary>>), do: {:ok, {id, rest}}
  def decode_id(_), do: {:error, :invalid_id}

  @spec valid_id?(term()) :: boolean()
  def valid_id?(id), do: is_integer(id) and id in 0..@uint24_max

  @spec maybe_valid_id?(term()) :: boolean()
  def maybe_valid_id?(nil), do: true
  def maybe_valid_id?(id) when is_integer(id), do: valid_id?(id)
  def maybe_valid_id?(_), do: false
end