%%%------------------------------------------------------------------- %%% @author Alpha Umaru Shaw %%% @doc %%% %%% @end %%% Company: Skulup Ltd %%% Copyright: (C) 2020 %%%------------------------------------------------------------------- -module(ew_assertions). -author("Alpha Umaru Shaw"). -include("erlwater.hrl"). %% API -export([assert/3, is_boolean/1, is_number/1, is_integer/1, is_string/1, is_proplist/1, is_positive_int/1, is_non_negative_int/1]). -define(BOOLEAN, "boolean"). -define(NUMBER, "number"). -define(INTEGER, "integer"). -define(STRING, "binary or string"). -define(POS_INTEGER, "positive integer"). -define(NON_NEG_INTEGER, "non-negative integer"). -define(PROPLIST, "proplist"). assert(Expression, Arg, Error) -> if Expression -> Arg; true -> erlang:error(Error, [Arg]) end. is_boolean({Key, Value} = Arg) -> assert_type(Key, Arg, Value, fun() -> erlang:is_boolean(Value) end, ?BOOLEAN); is_boolean(Value) -> ?MODULE:is_boolean({Value, Value}), Value. is_number({Key, Value} = Arg) -> assert_type(Key, Arg, Value, fun() -> erlang:is_number(Value) end, ?NUMBER); is_number(Value) -> ?MODULE:is_number({Value, Value}), Value. is_integer({Key, Value} = Arg) -> assert_type(Key, Arg, Value, fun() -> erlang:is_integer(Value) end, ?INTEGER); is_integer(Value) -> ?MODULE:is_integer({Value, Value}), Value. is_positive_int({Key, Value} = Arg) -> assert_type( Key, Arg, Value, fun() -> erlang:is_integer(Value) andalso Value > 0 end, ?POS_INTEGER); is_positive_int(Value) -> ?MODULE:is_positive_int({Value, Value}), Value. is_non_negative_int({Key, Value} = Arg) -> assert_type( Key, Arg, Value, fun() -> erlang:is_integer(Value) andalso Value >= 0 end, ?NON_NEG_INTEGER); is_non_negative_int(Value) -> ?MODULE:is_non_negative_int({Value, Value}), Value. is_string({Key, Value} = Arg) -> assert_type( Key, Arg, Value, fun() -> is_binary(Value) or io_lib:printable_list(Value) end, ?STRING); is_string(Value) -> ?MODULE:is_string({Value, Value}), Value. is_proplist({Key, Value} = Arg) -> assert_type(Key, Arg, Value, fun() -> is_a_prop_list(Value) end, ?PROPLIST); is_proplist(Value) -> ?MODULE:is_proplist({Value, Value}), Value. assert_type(Prop, Arg, Given, Checker, Type) -> case Checker() of true -> Arg; _ -> bad_value(Prop, Given, Type, Arg) end. is_a_prop_list([]) -> true; is_a_prop_list(Ls) when is_list(Ls) -> lists:all( fun({_, _}) -> true; (_) -> false end, Ls); is_a_prop_list(_) -> false. bad_value(Prop, Given, Msg, Args) -> Msg2 = lists:flatten(io_lib:format("value of property: `~p` must be ~s. Given: ~p", [Prop, Msg, Given])), erlang:error({bad_value, Msg2}, [Args]).