diff --git a/.gitignore b/.gitignore index e5fd73b..0e34380 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ kadena-*.tar # Temporary files, for example, from tests. /tmp/ + +# Dialyzer plt files +/priv/plts diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..0a8152e --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +elixir 1.13 diff --git a/lib/types/base16_string.ex b/lib/types/base16_string.ex new file mode 100644 index 0000000..e3d2f7e --- /dev/null +++ b/lib/types/base16_string.ex @@ -0,0 +1,15 @@ +defmodule Kadena.Types.Base16String do + @moduledoc """ + `Base16String` struct definition. + """ + + @behaviour Kadena.Types.Spec + + @type t :: %__MODULE__{value: String.t()} + + defstruct [:value] + + @impl true + def new(str) when is_binary(str), do: %__MODULE__{value: str} + def new(_str), do: {:error, :invalid_string} +end diff --git a/lib/types/base64_url.ex b/lib/types/base64_url.ex new file mode 100644 index 0000000..5cfd7b4 --- /dev/null +++ b/lib/types/base64_url.ex @@ -0,0 +1,15 @@ +defmodule Kadena.Types.Base64Url do + @moduledoc """ + `Base64Url` struct definition. + """ + + @behaviour Kadena.Types.Spec + + @type t :: %__MODULE__{url: String.t()} + + defstruct [:url] + + @impl true + def new(str) when is_binary(str), do: %__MODULE__{url: str} + def new(_str), do: {:error, :invalid_url} +end diff --git a/lib/types/base64_urls_list.ex b/lib/types/base64_urls_list.ex new file mode 100644 index 0000000..7d3782e --- /dev/null +++ b/lib/types/base64_urls_list.ex @@ -0,0 +1,25 @@ +defmodule Kadena.Types.Base64UrlsList do + @moduledoc """ + `Base64UrlsList` struct definition. + """ + alias Kadena.Types.Base64Url + + @behaviour Kadena.Types.Spec + + @type urls :: list(Base64Url.t()) + + @type t :: %__MODULE__{list: urls()} + + defstruct list: [] + + @impl true + def new(urls), do: build_list(%__MODULE__{}, urls) + + @spec build_list(list :: t(), urls :: urls()) :: t() + defp build_list(list, []), do: list + + defp build_list(%__MODULE__{list: list}, [%Base64Url{} = url | rest]), + do: build_list(%__MODULE__{list: [url | list]}, rest) + + defp build_list(_list, _urls), do: {:error, :invalid_urls} +end diff --git a/lib/types/spec.ex b/lib/types/spec.ex new file mode 100644 index 0000000..238a71b --- /dev/null +++ b/lib/types/spec.ex @@ -0,0 +1,9 @@ +defmodule Kadena.Types.Spec do + @moduledoc """ + Defines base types constructions. + """ + + @type error :: {:error, atom()} + + @callback new(any()) :: struct() | error() +end diff --git a/lib/types/uint8_array.ex b/lib/types/uint8_array.ex new file mode 100644 index 0000000..263906b --- /dev/null +++ b/lib/types/uint8_array.ex @@ -0,0 +1,25 @@ +defmodule Kadena.Types.Uint8Array do + @moduledoc """ + `Uint8Array` struct definition. + """ + + @behaviour Kadena.Types.Spec + + @type values :: binary() | list(integer()) + @type t :: %__MODULE__{value: values} + + defstruct [:value] + + @impl true + def new(buffer) when is_binary(buffer), do: %__MODULE__{value: :binary.bin_to_list(buffer)} + def new(list) when is_list(list), do: check_list(%__MODULE__{value: list}, list) + def new(_value), do: {:error, :invalid_uint8_array} + + @spec check_list(module_list :: t(), values :: list(integer())) :: t() + defp check_list(module_list, []), do: module_list + + defp check_list(module_list, [value | rest]) when is_integer(value) and value >= 0, + do: check_list(module_list, rest) + + defp check_list(_module_list, _values), do: {:error, :invalid_uint8_array} +end diff --git a/test/types/base16_string_test.exs b/test/types/base16_string_test.exs new file mode 100644 index 0000000..371bdd7 --- /dev/null +++ b/test/types/base16_string_test.exs @@ -0,0 +1,23 @@ +defmodule Kadena.Types.Base16StringTest do + @moduledoc """ + `Base16String` struct definition tests. + """ + + use ExUnit.Case + + alias Kadena.Types.Base16String + + describe "new/1" do + test "with a valid string value" do + %Base16String{value: "string"} = Base16String.new("string") + end + + test "with an invalid atom value" do + {:error, :invalid_string} = Base16String.new(:atom) + end + + test "with an invalid nil value" do + {:error, :invalid_string} = Base16String.new(nil) + end + end +end diff --git a/test/types/base64_url_test.exs b/test/types/base64_url_test.exs new file mode 100644 index 0000000..860fd39 --- /dev/null +++ b/test/types/base64_url_test.exs @@ -0,0 +1,23 @@ +defmodule Kadena.Types.Base64UrlTest do + @moduledoc """ + `Base64Url` struct definition tests. + """ + + use ExUnit.Case + + alias Kadena.Types.Base64Url + + describe "new/1" do + test "with a valid url" do + %Base64Url{url: "valid_url"} = Base64Url.new("valid_url") + end + + test "with an invalid url" do + {:error, :invalid_url} = Base64Url.new(:atom) + end + + test "with a nil url" do + {:error, :invalid_url} = Base64Url.new(nil) + end + end +end diff --git a/test/types/base64_urls_list_test.exs b/test/types/base64_urls_list_test.exs new file mode 100644 index 0000000..ac56555 --- /dev/null +++ b/test/types/base64_urls_list_test.exs @@ -0,0 +1,25 @@ +defmodule Kadena.Types.Base64UrlsListTest do + @moduledoc """ + `Base64UrlsList` struct definition tests. + """ + + use ExUnit.Case + + alias Kadena.Types.{Base64Url, Base64UrlsList} + + describe "new/1" do + test "with a valid urls list" do + base_url = Base64Url.new("valid_url") + %Base64UrlsList{list: [base_url, base_url]} = Base64UrlsList.new([base_url, base_url]) + end + + test "with an invalid urls list" do + base_url = Base64Url.new("valid_url") + {:error, :invalid_urls} = Base64UrlsList.new([base_url, :atom, base_url]) + end + + test "with a list of nil" do + {:error, :invalid_urls} = Base64UrlsList.new([nil]) + end + end +end diff --git a/test/types/uint8_array_test.exs b/test/types/uint8_array_test.exs new file mode 100644 index 0000000..7d9a520 --- /dev/null +++ b/test/types/uint8_array_test.exs @@ -0,0 +1,37 @@ +defmodule Kadena.Types.Uint8ArrayTest do + @moduledoc """ + `Uint8Array` struct definition tests. + """ + + use ExUnit.Case + + alias Kadena.Types.Uint8Array + + describe "new/1" do + test "with a valid buffer" do + %Uint8Array{value: [254, 255, 0, 1, 2]} = Uint8Array.new(<<254, 255, 256, 257, 258>>) + end + + test "with a valid list" do + values_list = [134, 147, 230, 65, 174, 43, 190, 158] + %Uint8Array{value: ^values_list} = Uint8Array.new(values_list) + end + + test "with a negative value in the list" do + {:error, :invalid_uint8_array} = Uint8Array.new([230, -65, 174]) + end + + test "with an invalid input" do + {:error, :invalid_uint8_array} = Uint8Array.new(-5) + end + + test "with a nil value" do + {:error, :invalid_uint8_array} = Uint8Array.new(nil) + end + + test "with an invalid list" do + values_list = [134, 147, 230, 65, 174, 43, 190, :atom, 158] + {:error, :invalid_uint8_array} = Uint8Array.new(values_list) + end + end +end