Current section
Files
Jump to
Current section
Files
lib/document/type.ex
defmodule Durango.Document.Type do
def type(%module{}, name) do
type(module, name)
end
def type(module, name) when is_atom(module) and is_atom(name) do
module.__document__(:fields)
|> Keyword.get(name, %{})
|> Map.get(:type)
end
def get_type(%module{}) do
module
end
def get_type(x) when is_integer(x) do
:integer
end
def get_type(x) when is_float(x) do
:float
end
def get_type(x) when is_binary(x) do
:string
end
def get_type(x) when is_boolean(x) do
:boolean
end
def get_type(x) when is_list(x) do
x
|> Enum.map(&get_type/1)
|> Enum.uniq
|> case do
[:invalid] ->
:invalid
[type] ->
{:array, type}
_ ->
:invalid
end
end
def get_type(x) when is_map(x) do
:object
end
def get_type(_) do
:invalid
end
def is_type?(%_{} = model, name, type) when is_atom(name) and is_atom(type) do
model
|> Map.get(name)
|> is_type?(type)
end
def is_type?(value, type) do
is_type?({value, type})
end
def is_type?({value, type}) do
case {value, type} do
{_, :any} -> true
{v, :string} when is_binary(v) -> true
{v, :integer} when is_integer(v) -> true
{v, :float} when is_float(v) -> true
{v, :boolean} when is_boolean(v) -> true
{v, {:array, subtype}} -> array_is_type?(v, subtype)
{%module{} = v, :object} -> object_is_type?(v, module)
{v, :object} when is_map(v) -> true
{v, module} when is_atom(module) -> object_is_type?(v, module)
_ -> false
end
end
defp array_is_type?(array, subtype) when is_list(array) do
Enum.all?(array, fn sub_v -> is_type?(sub_v, subtype) end)
end
defp array_is_type?(_, _) do
false
end
defp object_is_type?(object, module) when is_map(object) do
if Durango.Document.is_document?(module) do
object
|> Map.from_struct()
|> Enum.all?(fn {name, value} ->
is_type?({value, type(module, name)})
end)
else
false
end
end
defp object_is_type?(_, _) do
false
end
end