Current section
Files
Jump to
Current section
Files
lib/zig/type/pointer.ex
defmodule Zig.Type.Pointer do
@moduledoc false
alias Zig.Type
alias Zig.Type.Array
alias Zig.Type.Optional
alias Zig.Type.Struct
use Type
@enforce_keys ~w[child const]a
defstruct @enforce_keys ++ [optional: false]
@type t :: %__MODULE__{
optional: boolean(),
const: boolean(),
child: Type.t()
}
@mutable_types ~w[array struct]
# special case: pointer represents that the data are mutable.
def from_json(
%{"type" => "pointer", "child" => %{"type" => mutable} = child, "is_const" => false},
module
)
when mutable in @mutable_types do
child
|> Type.from_json(module)
|> struct!(mutable: true)
end
# special case: pointer represents that the data are mutable AND optional.
def from_json(
%{
"type" => "optional",
"child" => %{
"type" => "pointer",
"child" => %{"type" => mutable} = child,
"is_const" => false
}
},
module
)
when mutable in @mutable_types do
child
|> Type.from_json(module)
|> struct!(mutable: true)
|> then(&%Optional{child: &1})
end
def from_json(%{"type" => "optional", "child" => %{"type" => "pointer"} = pointer}, module) do
pointer
|> from_json(module)
|> Map.replace!(:optional, true)
end
def from_json(
%{"type" => "pointer", "child" => %{"type" => "unusable:anyopaque"}, "is_const" => const},
_module
) do
%__MODULE__{child: :anyopaque, const: const}
end
def from_json(%{"child" => child, "is_const" => const}, module) do
%__MODULE__{child: Type.from_json(child, module), const: const}
end
@impl true
def marshal_param(_, variable, _, platform), do: Type._default_marshal_param(platform, variable)
@impl true
def marshal_return(_, _, _), do: raise("unreachable")
# validations:
@impl true
def get_allowed?(_), do: false
@impl true
def make_allowed?(%{child: %Array{} = array}), do: Type.make_allowed?(array)
def make_allowed?(%{child: %Struct{} = struct}), do: Type.make_allowed?(struct)
def make_allowed?(_), do: false
@impl true
def in_out_allowed?(%{child: child}), do: Type.get_allowed?(child) and Type.make_allowed?(child)
@impl true
def binary_size(_), do: nil
@impl true
def render_accessory_variables(type, param, prefix) do
if param.in_out do
~s(var #{prefix}: #{Type.render_zig(type.child)} = undefined;)
else
raise "unreachable"
end
end
@impl true
# pointer might be used as a in-out return value.
def payload_options(_, _), do: [error_info: "&error_info"]
@impl true
def render_zig(%{optional: true} = type), do: "?*#{Type.render_zig(type.child)}"
def render_zig(type), do: "*#{Type.render_zig(type.child)}"
@impl true
def render_cleanup(_, _), do: Type._default_cleanup()
@impl true
def render_elixir_spec(type, context), do: Type.render_elixir_spec(type.child, context)
end