defmodule TL.Build do alias TL.Schema import TL.Binary @moduledoc false def encode(container, content) do {:match, description} = Schema.search "method_or_predicate", container expected_params = description |> Map.get("params") # Map values to their types map = Enum.map expected_params,fn x -> { Map.get(x, "type") |> String.to_atom, Map.get(content, String.to_atom Map.get(x, "name")) } end # Serialized values serialized_values = map |> Enum.map(fn {type, value} -> serialize(value, type) end) # Seralize the constructor serialized_method = description |> Map.get("id") |> String.to_integer |> serialize(:meta32) # Build the final payload serialized_method <> :binary.list_to_bin serialized_values end # Serialize a value given its type def serialize(data, type) do case type do :meta32 -> <> :meta64 -> <> :int -> <> :int64 -> <> :int128 -> <> :int256 -> <> :long -> <> :double -> <> :string -> serialize_string(data) :bytes -> bin = if (is_binary data), do: data, else: encode_signed(data) serialize_string(bin) end end defp serialize_string(string) do len = byte_size string p = fn x -> y = (x - Float.floor x) case y do 0.0 -> 0 _ -> (1-y) * 4 |> round end end if len <= 253 do div = (len + 1) / 4 padding = p.(div) <> <> string <> <<0::size(padding)-unit(8)>> else div = (len + 4) / 4 padding = p.(div) <<254>> <> <> <> string <> <<0::size(padding)-unit(8)>> end end end