defmodule Hugs do alias Hugs.StructDefinition alias Hugs.PropsDefinition alias Hugs.FieldDefinition # --------------------------------------------------------------------------- # Contracts definition helpers # --------------------------------------------------------------------------- @doc """ Writes the given definition in the calling module. """ defmacro define(dfn) do dfn_code = Macro.to_string(dfn) quote bind_quoted: [dfn: dfn, dfn_code: dfn_code], location: :keep do @__hugs_dfn dfn require Hugs.Compiler case @__hugs_dfn do %Hugs.StructDefinition{} = sdef -> Hugs.Compiler.define_struct(sdef) %Hugs.PropsDefinition{} = sdef -> Hugs.Compiler.define_props(sdef) other -> raise """ Hugs.define/1 received unexpected definition. Got: #{inspect(other, pretty: true)} Code: #{dfn_code} """ end def __hugs__(:definition), do: @__hugs_dfn end end def build_struct(module), do: StructDefinition.new(module) def build_props(), do: PropsDefinition.new() defmacro build_struct() do quote do Hugs.StructDefinition.new(__MODULE__) end end def field(%cmod{} = container, key, opts \\ []) do cmod.add_field(container, FieldDefinition.new(key, opts)) end def constraint(%cmod{} = container, module, fun, args) when is_atom(module) and is_atom(fun) and is_list(args), do: cmod.add_constraint(container, module, fun, args) # --------------------------------------------------------------------------- # Normalization / Denormalization helpers # --------------------------------------------------------------------------- def denormalize(data, target) do Hugs.Norde.denormalize(data, target) end def denormalize!(data, target) do case denormalize(data, target) do {:ok, value} -> value {:error, reason} -> raise reason end end # flipped version of denormalize to pipe the definition instead of the data def denormalize_data(target, data) do denormalize(data, target) end end