Current section

Files

Jump to
zigler lib zig type tuple.ex
Raw

lib/zig/type/tuple.ex

defmodule Zig.Type.Tuple do
@moduledoc false
alias Zig.Parameter
alias Zig.Return
alias Zig.Type
use Type
defstruct [:name, :elements]
@type t :: %__MODULE__{
name: String.t(),
elements: [Type.t()]
}
def from_json(%{"name" => name, "fields" => fields}, module) do
# Fields are in order already for tuples (named "0", "1", "2", etc.)
elements =
fields
|> Enum.sort_by(& &1["name"])
|> Enum.map(fn desc -> Type.from_json(desc["type"], module) end)
%__MODULE__{
name: String.trim_leading(name, ".#{module}."),
elements: elements
}
end
@impl true
def render_elixir_spec(tuple, %Return{as: as}) do
render_elixir_spec(tuple, as)
end
def render_elixir_spec(tuple, %Parameter{} = params) do
render_tuple_spec(tuple, params)
end
def render_elixir_spec(tuple, context) do
render_tuple_spec(tuple, context)
end
@impl true
def render_erlang_spec(tuple, %Return{as: as}), do: render_erlang_spec(tuple, as)
def render_erlang_spec(tuple, %Parameter{} = params), do: render_erlang_tuple_spec(tuple, params)
def render_erlang_spec(tuple, context), do: render_erlang_tuple_spec(tuple, context)
defp render_erlang_tuple_spec(%{elements: elements}, context) do
element_specs =
elements
|> Enum.with_index()
|> Enum.map_join(", ", fn {element, index} ->
element_opts = element_opts(context, index)
Type.render_erlang_spec(element, element_opts)
end)
"{#{element_specs}}"
end
defp render_tuple_spec(%{elements: elements}, context) do
element_specs =
elements
|> Enum.with_index()
|> Enum.map(fn {element, index} ->
element_opts = element_opts(context, index)
Type.render_elixir_spec(element, element_opts)
end)
quote do
{unquote_splicing(element_specs)}
end
end
defp element_opts({:tuple, list}, index) when is_list(list) do
Enum.find_value(list, :default, fn
{^index, type} -> type
_ -> nil
end)
end
defp element_opts(%Parameter{} = params, _index), do: params
defp element_opts(_, _), do: :default
@impl true
def render_zig(%{name: name}), do: "nif.#{name}"
@impl true
def get_allowed?(tuple) do
Enum.all?(tuple.elements, &Type.get_allowed?/1)
end
@impl true
def make_allowed?(tuple) do
Enum.all?(tuple.elements, &Type.make_allowed?/1)
end
@impl true
def in_out_allowed?(_), do: false
@impl true
def binary_size(_), do: nil
@impl true
def render_cleanup(_, _), do: Type._default_cleanup()
@impl true
def needs_size?(_), do: false
@impl true
def payload_options(_, _), do: Type._default_payload_options()
@impl true
def marshal_param(_, variable, _, platform), do: Type._default_marshal_param(platform, variable)
@impl true
def marshal_return(_, variable, platform), do: Type._default_marshal_return(platform, variable)
end