Packages
ex_gram
0.27.0
0.67.0
0.66.0
0.65.0
0.64.0
0.63.0
0.62.0
0.61.0
0.60.0
0.58.0
0.57.0
0.56.1
0.56.0
0.55.1
0.55.0
0.54.0
0.53.0
0.52.2
0.52.1
0.52.0
0.51.1
0.51.0
0.50.2
0.50.1
0.50.0
0.41.0
0.40.0
0.34.0
0.33.0
0.32.0
0.31.0
0.30.0
0.29.0
0.28.0
0.27.0
0.26.0
0.25.0
0.24.1
0.24.0
0.23.0
0.22.0
0.21.0
0.20.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.0
0.9.0
0.8.1
0.8.0
0.7.1
0.7.0
0.6.2
0.6.1
0.6.0
0.5.0
0.5.0-rc6
0.5.0-rc5
0.5.0-rc4
0.5.0-rc3
0.5.0-rc2
Telegram Bot API low level and framework
Current section
Files
Jump to
Current section
Files
lib/ex_gram/macros/checker.ex
defmodule ExGram.Macros.Checker do
@moduledoc """
Type checker for the method executer.
"""
@type valid_type :: :integer | :string | :boolean | :float | :file | {:array, valid_type} | atom
@type param_type :: maybe_improper_list(any, [valid_type])
@type params_types :: [param_type]
@type error_type_element :: {any, [valid_type]}
@spec check_types(params_types) :: :ok | {:error, [{error_type_element, integer}]}
def check_types(params) do
errors =
params
|> Enum.map(&check_any_type/1)
|> Enum.with_index()
|> Enum.filter(fn
{:ok, _} ->
false
_ ->
true
end)
case errors do
[] ->
:ok
_ ->
{:error, errors}
end
end
defp check_any_type([value, types]) do
case Enum.any?(types, &check_type(&1, value)) do
true -> :ok
_ -> {value, types}
end
end
defp check_type(types, x) when is_list(types), do: Enum.any?(types, &check_type(&1, x))
defp check_type(:integer, x), do: is_integer(x)
defp check_type(:string, x), do: is_bitstring(x)
defp check_type(:boolean, x), do: is_boolean(x)
defp check_type(:float, x), do: is_float(x)
defp check_type(:file, {:file, _p}), do: true
defp check_type(:file, {:file_content, _c, _fn}), do: true
defp check_type(:file, _o), do: false
defp check_type({:array, _}, []), do: true
defp check_type({:array, t}, x) when is_list(x) do
Enum.all?(x, &check_type(t, &1))
end
defp check_type({:array, _t}, _), do: false
defp check_type(:any, _x), do: true
defp check_type(t1, %{__struct__: t1}), do: true
defp check_type(t1, %{__struct__: t2} = struct) do
check_same_struct(t1, t2) || check_subtypes(t1, struct)
end
# defp check_type(t1, %{__struct__: t2}), do: t1 == t2
defp check_type(%{}, x), do: is_map(x)
defp check_same_struct(t1, t2) do
t2s = Atom.to_string(t2)
t2a =
if name_is_model?(t2s) do
name = last_part_name(t2s)
String.to_atom("Elixir.#{name}")
else
t2
end
t1 == t2a
end
defp check_subtypes(t1, struct) do
subtypes = extract_subtypes(t1)
Enum.any?(subtypes, &check_type(&1, struct))
end
defp extract_subtypes(mod) when is_atom(mod), do: extract_subtypes(Atom.to_string(mod))
defp extract_subtypes(mods) when is_binary(mods) do
# mods = Atom.to_string(mod)
mod =
if name_is_model?(mods) do
String.to_atom(mods)
else
name = last_part_name(mods)
String.to_atom("Elixir.ExGram.Model.#{name}")
end
try do
mod.subtypes()
rescue
_ -> []
catch
_ -> []
end
end
defp extract_subtypes(_), do: []
defp name_is_model?("Elixir.ExGram.Model." <> _), do: true
defp name_is_model?(_), do: false
defp last_part_name(name), do: name |> String.split(".") |> List.last()
end