defmodule Hugs.StructDefinition do
alias Hugs.FieldDefinition
alias Hugs.PropsDefinition
@enforce_keys [:module, :props]
defstruct @enforce_keys
def new(module) do
%__MODULE__{module: module, props: PropsDefinition.new()}
end
def add_field(%__MODULE__{props: m} = this, %FieldDefinition{} = field) do
verify_struct_field!(this, field)
%__MODULE__{this | props: PropsDefinition.add_field(m, field)}
end
def add_constraint(%__MODULE__{props: m} = this, module, fun, args) do
%__MODULE__{this | props: PropsDefinition.add_constraint(m, module, fun, args)}
end
def constraints(%__MODULE__{props: m}), do: PropsDefinition.constraints(m)
defp verify_struct_field!(_this, %FieldDefinition{} = field) do
%FieldDefinition{key: key, required: _req?, default: _default, optional: opt?} = field
if not is_atom(key),
do: raise("only atoms are supported for struct keys, got: #{inspect(key)}")
if opt?,
do: raise("struct fields cannot be :optional")
# if not req? and default == :__undef__ do
# IO.warn(
# "field #{inspect(key)} of struct #{inspect(this.module)} is not required and was not given a default value. :__undef__ base default value will be used"
# )
# end
end
def required_keys(%__MODULE__{props: m}), do: PropsDefinition.required_keys(m)
def default_pairs(%__MODULE__{props: m}), do: PropsDefinition.default_pairs(m, false)
end