Skip to main content

lib/dust/protocol/codec.ex

defmodule Dust.Protocol.Codec do
  @doc "Encode a map into the specified wire format."
  def encode(:msgpack, data) when is_map(data) do
    data
    |> stringify_keys()
    |> Msgpax.pack()
    |> case do
      {:ok, iodata} -> {:ok, IO.iodata_to_binary(iodata)}
      error -> error
    end
  end

  def encode(:json, data) when is_map(data) do
    Jason.encode(data)
  end

  @doc "Decode binary data from the specified wire format."
  def decode(:msgpack, binary) when is_binary(binary) do
    Msgpax.unpack(binary)
  end

  def decode(:json, binary) when is_binary(binary) do
    Jason.decode(binary)
  end

  defp stringify_keys(map) when is_map(map) do
    Map.new(map, fn
      {k, v} when is_atom(k) -> {Atom.to_string(k), stringify_keys(v)}
      {k, v} -> {k, stringify_keys(v)}
    end)
  end

  defp stringify_keys(list) when is_list(list), do: Enum.map(list, &stringify_keys/1)
  defp stringify_keys(value), do: value
end