defmodule Soroban.Types.Struct do @moduledoc """ `Struct` struct definition. """ @behaviour Soroban.Types.Spec alias Soroban.Types.StructField alias Stellar.TxBuild.SCVal defstruct [:values] @type errors :: atom() @type values :: list(StructField.t()) @type validation :: {:ok, values()} | {:error, errors()} @type t :: %__MODULE__{values: values} @impl true def new(values) when is_list(values) do with {:ok, values} <- validate_struct_field_values(values) do %__MODULE__{values: values} end end def new(_values), do: {:error, :invalid} @impl true def to_sc_val(%__MODULE__{values: values}) do values |> Enum.map(&StructField.to_sc_map_entry/1) |> (&SCVal.new(map: &1)).() end def to_sc_val(_error), do: {:error, :invalid_struct} @spec validate_struct_field_values(values :: values()) :: validation() def validate_struct_field_values(values) do if Enum.all?(values, &is_struct(&1, StructField)), do: {:ok, values}, else: {:error, :invalid_values} end end