defmodule StellarBase.XDR.SCSpecEntry do @moduledoc """ Representation of Stellar `SCSpecEntry` type. """ alias StellarBase.XDR.{ SCSpecEntryKind, SCSpecFunctionV0, SCSpecUDTStructV0, SCSpecUDTUnionV0, SCSpecUDTEnumV0, SCSpecUDTErrorEnumV0 } @behaviour XDR.Declaration @arms [ SC_SPEC_ENTRY_FUNCTION_V0: SCSpecFunctionV0, SC_SPEC_ENTRY_UDT_STRUCT_V0: SCSpecUDTStructV0, SC_SPEC_ENTRY_UDT_UNION_V0: SCSpecUDTUnionV0, SC_SPEC_ENTRY_UDT_ENUM_V0: SCSpecUDTEnumV0, SC_SPEC_ENTRY_UDT_ERROR_ENUM_V0: SCSpecUDTErrorEnumV0 ] @type code :: SCSpecFunctionV0.t() | SCSpecUDTStructV0.t() | SCSpecUDTUnionV0.t() | SCSpecUDTEnumV0.t() | SCSpecUDTErrorEnumV0.t() @type kind :: SCSpecEntryKind.t() @type t :: %__MODULE__{code: code(), kind: kind()} defstruct [:code, :kind] @spec new(code :: code(), kind :: kind()) :: t() def new(code, %SCSpecEntryKind{} = kind), do: %__MODULE__{code: code, kind: kind} @impl true def encode_xdr(%__MODULE__{code: code, kind: kind}) do kind |> XDR.Union.new(@arms, code) |> XDR.Union.encode_xdr() end @impl true def encode_xdr!(%__MODULE__{code: code, kind: kind}) do kind |> XDR.Union.new(@arms, code) |> XDR.Union.encode_xdr!() end @impl true def decode_xdr(bytes, spec \\ union_spec()) def decode_xdr(bytes, spec) do case XDR.Union.decode_xdr(bytes, spec) do {:ok, {{kind, code}, rest}} -> {:ok, {new(code, kind), rest}} error -> error end end @impl true def decode_xdr!(bytes, spec \\ union_spec()) def decode_xdr!(bytes, spec) do {{kind, code}, rest} = XDR.Union.decode_xdr!(bytes, spec) {new(code, kind), rest} end @spec union_spec() :: XDR.Union.t() defp union_spec do nil |> SCSpecEntryKind.new() |> XDR.Union.new(@arms) end end