RTypes v0.2.1 RTypes View Source
RTypes is an Elixir library which helps automatically create a validation function for a given user type. The function can be used to check the shape of the data after de-serialisation or in unit-tests.
Let's suppose we have a type
@type t :: 0..255
and we have a value x
. To ensure that our value corresponds to the type t
we
can use the function
def t?(x) when is_integer(x) and x >= 0 and x <= 255, do: true
def t?(_), do: false
Now, if we have a compound type
@type list_of_ts :: [t]
and a value xs
, we can use is_list/1
guard on xs
and then ensure that all
elements of the list conform to t
. And if we have a more complex structure
@type state(a, b) :: %{key1: {a, b}, key2: list_of_ts()}
and a value s
, we can check that s
is a map which has keys key1
and
key2
, apply the logic above for the value of key2
and for any concrete types
a
and b
we can check that he value of key1
is a tuple of length 2 and its
elements conform to a
and b
respectively. So we just recursively apply those
checks.
Usage
The library defines make_validator/1
and make_predicate/1
macros, and
make_validator/3
and make_predicate/3
functions which can be used at run
time. The difference between the two is that a validator
returns :ok
or
{:error, reason}
where reason
explains what went wrong, while a
predicate
returns only true
or false
and is somewhat faster.
iex> require RTypes
iex> port_number? = RTypes.make_predicate(:inet.port_number())
iex> port_number?.(8080)
true
iex> port_number?.(80000)
false
iex> validate_is_kwlist = RTypes.make_validator(Keyword, :t, [{:type, 0, :pos_integer, []}])
iex> validate_is_kwlist.(key1: 4, key2: 5)
:ok
iex> match?({:error, _reason}, validate_is_kwlist.([1, 2, 3]))
true
Link to this section Summary
Types
t:error_decription/1
is a keyword list which details the validation error.
Functions
Derive a predicate for the given type expression.
Return a predicate given a module name, type name, and type parameters.
Derive a validtation function for the given type expression.
Derive a validation function given a module name, type name, and type parameters.
Link to this section Types
error_description() View Source
t:error_decription/1
is a keyword list which details the validation error.
Link to this section Functions
derive(code) View Source (macro)
derive(mod, type_name, type_args) View Source
derive!(code) View Source (macro)
derive!(mod, type_name, type_args) View Source
format_error_description(desc)
View Source
format_error_description(error_description()) :: String.t()
format_error_description(error_description()) :: String.t()
make_predicate(code) View Source (macro)
Derive a predicate for the given type expression.
iex> require RTypes
iex> non_neg_integer? = RTypes.make_predicate(non_neg_integer())
iex> non_neg_integer?.(10)
true
iex> non_neg_integer?.(0)
true
iex> non_neg_integer?.(-3)
false
iex> non_neg_integer?.(:ok)
false
make_predicate(mod, type_name, type_args)
View Source
make_predicate(module(), atom(), [RTypes.Extractor.type()]) ::
(any() -> boolean())
make_predicate(module(), atom(), [RTypes.Extractor.type()]) :: (any() -> boolean())
Return a predicate given a module name, type name, and type parameters.
The predicate behaves the same way as the one produced by make_predicate/1
macro.
make_validator(code) View Source (macro)
Derive a validtation function for the given type expression.
Usage
iex> require RTypes
iex> validate_port_number = RTypes.make_validator(:inet.port_number())
iex> validate_port_number.(8080)
:ok
iex> match?({:error, _}, validate_port_number.(70000))
true
iex> validate_kw_list = RTypes.make_validator(Keyword.t(pos_integer()))
iex> validate_kw_list.([a: 1, b: 2])
:ok
Note that the macro expects its argument provided as in
MyModule.my_type(arg1, arg2)
The returned function either returns :ok
or {:error, reason}
where
reason
details what went wrong.
make_validator(mod, type_name, type_args)
View Source
make_validator(module(), atom(), [RTypes.Extractor.type()]) ::
(term() -> :ok | {:error, error_description()})
make_validator(module(), atom(), [RTypes.Extractor.type()]) :: (term() -> :ok | {:error, error_description()})
Derive a validation function given a module name, type name, and type parameters.
Type parameters must be of some concrete type.
Example
iex> validate_kw_list = RTypes.make_validator(Keyword, :t, [{:type, 0, :pos_integer, []}])
iex> validate_kw_list.(key1: 4, key2: 5)
:ok
The function returns either :ok
or {:error, error_description}
where
error_description
details what went wrong.