Current section
Files
Jump to
Current section
Files
lib/rustq/native/enum_descriptor.ex
defmodule RustQ.Native.EnumDescriptor do
@moduledoc """
Resolved metadata for a native Rust enum.
A descriptor combines package-scoped enum identity with parsed `RustQ.Syn.Enum`
metadata and, when available, a web source link derived from Cargo metadata.
"""
alias RustQ.Syn.Enum, as: SynEnum
alias RustQ.Syn.Index
defstruct [:package, :name, :enum, :source_url]
@type t :: %__MODULE__{
package: String.t() | nil,
name: String.t(),
enum: SynEnum.t(),
source_url: String.t() | nil
}
@doc "Returns descriptor variants as `{atom_name, rust_variant}` pairs."
@spec variants(t()) :: [{atom(), String.t()}]
def variants(%__MODULE__{enum: %{__struct__: SynEnum, variants: variants}}) do
Enum.map(variants, &{RustQ.Atom.identifier!(Macro.underscore(&1)), &1})
end
@doc "Resolves a native enum through a `RustQ.Syn.Index`."
@spec resolve!(Index.t(), String.t(), keyword()) :: t()
def resolve!(%Index{} = index, name, opts \\ []) when is_binary(name) do
package_name = Keyword.get(opts, :package)
validate_package!(index, package_name)
enum = Index.enum!(index, name)
%__MODULE__{
package: package_name || package_name(index.package),
name: name,
enum: enum,
source_url: source_url(index.package, enum)
}
end
defp validate_package!(%Index{package: nil}, _package_name), do: :ok
defp validate_package!(_index, nil), do: :ok
defp validate_package!(%Index{package: %{name: name}}, name), do: :ok
defp validate_package!(%Index{package: package}, package_name) do
raise ArgumentError,
"native enum package #{inspect(package_name)} does not match indexed package #{inspect(package.name)}"
end
defp package_name(nil), do: nil
defp package_name(%{name: name}), do: name
defp source_url(nil, _enum), do: nil
defp source_url(package, %{__struct__: RustQ.Syn.Enum, source_path: path, source_line: line})
when is_binary(path) and is_integer(line),
do: RustQ.Cargo.source_link(package, path, line)
defp source_url(_package, _enum), do: nil
end