generated from kommitters/.template
-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Soroban Compound Types * Fix minor details --------- Co-authored-by: Felipe Guzmán Sierra <[email protected]>
- Loading branch information
1 parent
5cb5742
commit 3b007ed
Showing
17 changed files
with
713 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
defmodule Soroban.Types.Enum do | ||
@moduledoc """ | ||
`Enum` struct definition. | ||
""" | ||
|
||
@behaviour Soroban.Types.Spec | ||
|
||
alias Soroban.Types.Symbol | ||
alias Stellar.TxBuild.SCVal | ||
|
||
defstruct [:key, :value] | ||
|
||
@type sc_val :: SCVal.t() | ||
@type t :: %__MODULE__{key: String.t(), value: struct()} | ||
|
||
@impl true | ||
def new(key) when is_binary(key), | ||
do: %__MODULE__{key: key} | ||
|
||
def new({key, value}) when is_binary(key) and is_struct(value), | ||
do: %__MODULE__{key: key, value: value} | ||
|
||
def new(_args), do: {:error, :invalid} | ||
|
||
@impl true | ||
def to_sc_val(%__MODULE__{key: key, value: nil}) do | ||
key | ||
|> Symbol.new() | ||
|> Symbol.to_sc_val() | ||
|> (&SCVal.new(vec: [&1])).() | ||
end | ||
|
||
def to_sc_val(%__MODULE__{key: key, value: value}) do | ||
value = param_to_sc_val(value) | ||
|
||
key | ||
|> Symbol.new() | ||
|> Symbol.to_sc_val() | ||
|> (&SCVal.new(vec: [&1, value])).() | ||
end | ||
|
||
def to_sc_val(_error), do: {:error, :invalid_struct_enum} | ||
|
||
@spec param_to_sc_val(param :: struct()) :: sc_val() | ||
defp param_to_sc_val(param) do | ||
struct = param.__struct__ | ||
struct.to_sc_val(param) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
defmodule Soroban.Types.Map do | ||
@moduledoc """ | ||
`Map` struct definition. | ||
""" | ||
|
||
@behaviour Soroban.Types.Spec | ||
|
||
alias Soroban.Types.MapEntry | ||
alias Stellar.TxBuild.SCVal | ||
|
||
defstruct [:values] | ||
|
||
@type errors :: atom() | ||
@type values :: list(MapEntry.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_map_entry_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(&MapEntry.to_sc_map_entry/1) | ||
|> (&SCVal.new(map: &1)).() | ||
end | ||
|
||
def to_sc_val(_error), do: {:error, :invalid_struct_map} | ||
|
||
@spec validate_map_entry_values(values :: values()) :: validation() | ||
def validate_map_entry_values(values) do | ||
if Enum.all?(values, &is_struct(&1, MapEntry)), | ||
do: {:ok, values}, | ||
else: {:error, :invalid_values} | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
defmodule Soroban.Types.MapEntry do | ||
@moduledoc """ | ||
`MapEntry` struct definition. | ||
""" | ||
|
||
@behaviour Soroban.Types.Spec | ||
|
||
alias Stellar.TxBuild.{SCMapEntry, SCVal} | ||
|
||
defstruct [:key, :value] | ||
|
||
@type sc_val :: SCVal.t() | ||
@type t :: %__MODULE__{key: struct(), value: struct()} | ||
|
||
@impl true | ||
def new({key, value}) when is_struct(key) and is_struct(value), | ||
do: %__MODULE__{key: key, value: value} | ||
|
||
def new(_args), do: {:error, :invalid} | ||
|
||
@impl true | ||
def to_sc_map_entry(%__MODULE__{key: key, value: value}) do | ||
key = param_to_sc_val(key) | ||
value = param_to_sc_val(value) | ||
|
||
SCMapEntry.new(key, value) | ||
end | ||
|
||
def to_sc_map_entry(_error), do: {:error, :invalid_struct_map_entry} | ||
|
||
@spec param_to_sc_val(param :: struct()) :: sc_val() | ||
defp param_to_sc_val(param) do | ||
struct = param.__struct__ | ||
struct.to_sc_val(param) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
defmodule Soroban.Types.Option do | ||
@moduledoc """ | ||
`Option` struct definition. | ||
""" | ||
|
||
@behaviour Soroban.Types.Spec | ||
|
||
alias Stellar.TxBuild.SCVal | ||
|
||
defstruct [:value] | ||
|
||
@type sc_val :: SCVal.t() | ||
@type value :: struct() | nil | ||
@type t :: %__MODULE__{value: value()} | ||
|
||
@impl true | ||
def new(value \\ nil) | ||
def new(nil), do: %__MODULE__{} | ||
def new(value) when is_struct(value), do: %__MODULE__{value: value} | ||
def new(_value), do: {:error, :invalid_option} | ||
|
||
@impl true | ||
def to_sc_val(%__MODULE__{value: nil}), do: SCVal.new(void: nil) | ||
def to_sc_val(%__MODULE__{value: value}), do: param_to_sc_val(value) | ||
def to_sc_val(_error), do: {:error, :invalid_struct_bool} | ||
|
||
@spec param_to_sc_val(param :: struct()) :: sc_val() | ||
defp param_to_sc_val(param) do | ||
struct = param.__struct__ | ||
struct.to_sc_val(param) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
defmodule Soroban.Types.StructField do | ||
@moduledoc """ | ||
`StructField` struct definition. | ||
""" | ||
|
||
@behaviour Soroban.Types.Spec | ||
|
||
alias Soroban.Types.Symbol | ||
alias Stellar.TxBuild.{SCMapEntry, SCVal} | ||
|
||
defstruct [:key, :value] | ||
|
||
@type key :: String.t() | ||
@type sc_val :: SCVal.t() | ||
@type t :: %__MODULE__{key: key(), value: struct()} | ||
|
||
@impl true | ||
def new({key, value}) when is_binary(key) and is_struct(value), | ||
do: %__MODULE__{key: key, value: value} | ||
|
||
def new(_args), do: {:error, :invalid} | ||
|
||
@impl true | ||
def to_sc_map_entry(%__MODULE__{key: key, value: value}) do | ||
value = param_to_sc_val(value) | ||
|
||
key | ||
|> Symbol.new() | ||
|> Symbol.to_sc_val() | ||
|> SCMapEntry.new(value) | ||
end | ||
|
||
def to_sc_map_entry(_error), do: {:error, :invalid_struct_field} | ||
|
||
@spec param_to_sc_val(param :: struct()) :: sc_val() | ||
defp param_to_sc_val(param) do | ||
struct = param.__struct__ | ||
struct.to_sc_val(param) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
defmodule Soroban.Types.Tuple do | ||
@moduledoc """ | ||
`Tuple` struct definition. | ||
""" | ||
|
||
@behaviour Soroban.Types.Spec | ||
|
||
alias Stellar.TxBuild.SCVal | ||
|
||
defstruct [:values] | ||
|
||
@type values :: list(struct()) | ||
@type errors :: atom() | ||
@type t :: %__MODULE__{values: values()} | ||
|
||
@impl true | ||
def new(values) when is_list(values), do: %__MODULE__{values: values} | ||
|
||
def new(_values), do: {:error, :invalid} | ||
|
||
@impl true | ||
def to_sc_val(%__MODULE__{values: values}) do | ||
values | ||
|> Enum.map(fn %{__struct__: struct} = arg -> struct.to_sc_val(arg) end) | ||
|> (&SCVal.new(vec: &1)).() | ||
end | ||
|
||
def to_sc_val(_error), do: {:error, :invalid_struct_tuple} | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
defmodule Soroban.Types.Vec do | ||
@moduledoc """ | ||
`Vec` struct definition. | ||
""" | ||
|
||
@behaviour Soroban.Types.Spec | ||
|
||
alias Stellar.TxBuild.SCVal | ||
|
||
defstruct [:values] | ||
|
||
@type values :: list(struct()) | ||
@type errors :: atom() | ||
@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_vec_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(fn %{__struct__: struct} = arg -> struct.to_sc_val(arg) end) | ||
|> (&SCVal.new(vec: &1)).() | ||
end | ||
|
||
def to_sc_val(_error), do: {:error, :invalid_struct_vec} | ||
|
||
@spec validate_vec_values(values :: values()) :: validation() | ||
defp validate_vec_values([value | _] = values) do | ||
if Enum.any?(values, fn val -> val.__struct__ != value.__struct__ end), | ||
do: {:error, :invalid_args}, | ||
else: {:ok, values} | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
defmodule Soroban.Types.EnumTest do | ||
use ExUnit.Case | ||
|
||
alias Soroban.Types.{Enum, UInt32} | ||
alias Stellar.TxBuild.SCVal | ||
|
||
setup do | ||
key = "key" | ||
value = UInt32.new(100) | ||
enum = Enum.new({key, value}) | ||
enum2 = Enum.new(key) | ||
|
||
%{ | ||
key: key, | ||
value: value, | ||
enum: enum, | ||
enum2: enum2 | ||
} | ||
end | ||
|
||
describe "new/1" do | ||
test "with only key", %{key: key} do | ||
%Enum{key: ^key, value: nil} = Enum.new(key) | ||
end | ||
|
||
test "with key and value", %{key: key, value: value} do | ||
%Enum{key: ^key, value: ^value} = Enum.new({key, value}) | ||
end | ||
|
||
test "with a nil value" do | ||
{:error, :invalid} = Enum.new(nil) | ||
end | ||
|
||
test "with an atom value" do | ||
{:error, :invalid} = Enum.new(:atom) | ||
end | ||
end | ||
|
||
describe "to_sc_val/1" do | ||
test "with a valid enum type without value struct", %{enum2: enum2} do | ||
%SCVal{ | ||
type: :vec, | ||
value: [ | ||
%SCVal{type: :symbol, value: "key"} | ||
] | ||
} = Enum.to_sc_val(enum2) | ||
end | ||
|
||
test "with a valid enum type struct", %{enum: enum} do | ||
%SCVal{ | ||
type: :vec, | ||
value: [ | ||
%SCVal{type: :symbol, value: "key"}, | ||
%SCVal{type: :u32, value: 100} | ||
] | ||
} = Enum.to_sc_val(enum) | ||
end | ||
|
||
test "with an invalid value" do | ||
{:error, :invalid_struct_enum} = Enum.to_sc_val(nil) | ||
end | ||
end | ||
end |
Oops, something went wrong.