defmodule Stellar.TxBuild.SCStatus do @moduledoc """ `SCStatus` struct definition. """ @behaviour Stellar.TxBuild.XDR alias StellarBase.XDR.{ SCUnknownErrorCode, SCHostValErrorCode, SCHostObjErrorCode, SCHostFnErrorCode, SCHostStorageErrorCode, SCHostContextErrorCode, SCVmErrorCode, SCHostAuthErrorCode, SCStatusType, UInt32, Void, SCStatus } @type validation :: {:ok, any()} | {:error, atom()} @type value :: SCUnknownErrorCode.t() | SCHostValErrorCode.t() | SCHostObjErrorCode.t() | SCHostFnErrorCode.t() | SCHostStorageErrorCode.t() | SCHostContextErrorCode.t() | SCVmErrorCode.t() | SCHostAuthErrorCode.t() | SCStatusType.t() | UInt32.t() | Void.t() @type t :: %__MODULE__{ type: String.t(), value: value() } @allowed_types ~w(ok unknown_error host_value_error host_object_error host_function_error host_storage_error host_context_error vm_error contract_error host_auth_error)a defstruct [:type, :value] @impl true def new(args, opts \\ nil) def new([{type, value}], _opts) when type in @allowed_types do with {:ok, _value} <- validate_sc_status({type, value}) do %__MODULE__{ type: type, value: value } end end def new(_args, _opts), do: {:error, :invalid_sc_val_type} @impl true def to_xdr(%__MODULE__{type: :ok, value: value}) do type = SCStatusType.new(:SST_OK) value |> Void.new() |> SCStatus.new(type) end def to_xdr(%__MODULE__{type: :unknown_error, value: value}) do type = SCStatusType.new(:SST_UNKNOWN_ERROR) value |> SCUnknownErrorCode.new() |> SCStatus.new(type) end def to_xdr(%__MODULE__{type: :host_value_error, value: value}) do type = SCStatusType.new(:SST_HOST_VALUE_ERROR) value |> SCHostValErrorCode.new() |> SCStatus.new(type) end def to_xdr(%__MODULE__{type: :host_object_error, value: value}) do type = SCStatusType.new(:SST_HOST_OBJECT_ERROR) value |> SCHostObjErrorCode.new() |> SCStatus.new(type) end def to_xdr(%__MODULE__{type: :host_function_error, value: value}) do type = SCStatusType.new(:SST_HOST_FUNCTION_ERROR) value |> SCHostFnErrorCode.new() |> SCStatus.new(type) end def to_xdr(%__MODULE__{type: :host_storage_error, value: value}) do type = SCStatusType.new(:SST_HOST_STORAGE_ERROR) value |> SCHostStorageErrorCode.new() |> SCStatus.new(type) end def to_xdr(%__MODULE__{type: :host_context_error, value: value}) do type = SCStatusType.new(:SST_HOST_CONTEXT_ERROR) value |> SCHostContextErrorCode.new() |> SCStatus.new(type) end def to_xdr(%__MODULE__{type: :vm_error, value: value}) do type = SCStatusType.new(:SST_VM_ERROR) value |> SCVmErrorCode.new() |> SCStatus.new(type) end def to_xdr(%__MODULE__{type: :contract_error, value: value}) do type = SCStatusType.new(:SST_CONTRACT_ERROR) value |> UInt32.new() |> SCStatus.new(type) end def to_xdr(%__MODULE__{type: :host_auth_error, value: value}) do type = SCStatusType.new(:SST_HOST_AUTH_ERROR) value |> SCHostAuthErrorCode.new() |> SCStatus.new(type) end @spec validate_sc_status(tuple :: tuple()) :: validation() def validate_sc_status({:ok, nil}), do: {:ok, nil} def validate_sc_status({:ok, _value}), do: {:error, :invalid_void} def validate_sc_status({:unknown_error, value}) do case value |> SCUnknownErrorCode.new() |> SCUnknownErrorCode.encode_xdr() do {:ok, _unknown_error} -> {:ok, value} {:error, _reason} -> {:error, :invalid_unknown_error} end end def validate_sc_status({:host_value_error, value}) do case value |> SCHostValErrorCode.new() |> SCHostValErrorCode.encode_xdr() do {:ok, _host_value_error} -> {:ok, value} {:error, _reason} -> {:error, :invalid_host_value_error} end end def validate_sc_status({:host_object_error, value}) do case value |> SCHostObjErrorCode.new() |> SCHostObjErrorCode.encode_xdr() do {:ok, _host_object_error} -> {:ok, value} {:error, _reason} -> {:error, :invalid_host_object_error} end end def validate_sc_status({:host_function_error, value}) do case value |> SCHostFnErrorCode.new() |> SCHostFnErrorCode.encode_xdr() do {:ok, _host_function_error} -> {:ok, value} {:error, _reason} -> {:error, :invalid_host_function_error} end end def validate_sc_status({:host_storage_error, value}) do case value |> SCHostStorageErrorCode.new() |> SCHostStorageErrorCode.encode_xdr() do {:ok, _host_storage_error} -> {:ok, value} {:error, _reason} -> {:error, :invalid_host_storage_error} end end def validate_sc_status({:host_context_error, value}) do case value |> SCHostContextErrorCode.new() |> SCHostContextErrorCode.encode_xdr() do {:ok, _host_context_error} -> {:ok, value} {:error, _reason} -> {:error, :invalid_host_context_error} end end def validate_sc_status({:vm_error, value}) do case value |> SCVmErrorCode.new() |> SCVmErrorCode.encode_xdr() do {:ok, _vm_error} -> {:ok, value} {:error, _reason} -> {:error, :invalid_vm_error} end end def validate_sc_status({:contract_error, value}) do case value |> UInt32.new() |> UInt32.encode_xdr() do {:ok, _uint32} -> {:ok, value} {:error, _reason} -> {:error, :invalid_uint32} end end def validate_sc_status({:host_auth_error, value}) do case value |> SCHostAuthErrorCode.new() |> SCHostAuthErrorCode.encode_xdr() do {:ok, _host_auth_error} -> {:ok, value} {:error, _reason} -> {:error, :invalid_host_auth_error} end end end