Current section
Files
Jump to
Current section
Files
lib/zig/type/enum.ex
defmodule Zig.Type.Enum do
@moduledoc false
alias Zig.Parameter
alias Zig.Return
alias Zig.Type
use Type
defstruct [:tags, :name]
@type t :: %__MODULE__{tags: %{optional(atom) => String.t()}, name: String.t()}
def from_json(%{"tags" => tags, "name" => name}, module) do
%__MODULE__{
tags: Map.new(tags, fn {key, val} -> {String.to_atom(key), val} end),
name: String.trim_leading(name, ".#{module}.")
}
end
def inspect(enum, opts) do
~s(%Zig.Type.Enum{name: "#{enum.name}", tags: #{Kernel.inspect(enum.tags, opts)}})
end
@impl true
def get_allowed?(_), do: true
@impl true
def make_allowed?(_), do: true
@impl true
def in_out_allowed?(_), do: false
@impl true
def binary_size(_), do: nil
@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)
@impl true
def render_accessory_variables(_, _, _), do: Type._default_accessory_variables()
@impl true
def payload_options(_, _), do: Type._default_payload_options()
@impl true
def render_cleanup(_, _), do: Type._default_cleanup()
@impl true
def render_zig(%{name: name}), do: name
@impl true
def render_elixir_spec(%{tags: tags}, %Parameter{}) do
tags
|> integers()
|> Kernel.++(atoms(tags))
|> unionize
end
def render_elixir_spec(type, %Return{as: as}), do: render_elixir_spec(type, as)
def render_elixir_spec(type, :integer) do
type.tags
|> integers()
|> unionize
end
def render_elixir_spec(type, :default) do
type.tags
|> atoms()
|> unionize
end
defp integers(tags) do
tags
|> Map.values()
|> Enum.sort(:desc)
|> Enum.reduce([], &accumulate/2)
end
defp atoms(tags) do
tags
|> Map.keys()
|> Enum.sort(:asc)
end
defp accumulate(number, []), do: [number]
defp accumulate(number, [succ | rest]) when succ == number + 1, do: [number..succ | rest]
defp accumulate(number, [succ..last | rest]) when succ == number + 1, do: [number..last | rest]
defp accumulate(number, noncontiguous), do: [number | noncontiguous]
defp unionize(content) do
content
|> Enum.map(&rerender/1)
|> Enum.reduce(fn a, b ->
quote do
unquote(a) | unquote(b)
end
end)
end
defp rerender(a..b) do
quote do
unquote(a)..unquote(b)
end
end
defp rerender(number), do: number
end