From b5e2fecca5e32baffec02e71039b068b4b12c907 Mon Sep 17 00:00:00 2001 From: Umgeher Torgersen Date: Sun, 13 Oct 2024 19:36:09 +0000 Subject: [PATCH] version: 1.0.0 + map_validate/2: a simple way to validate maps + gitversion.mk removed --- .gitignore | 12 +++++++++--- Makefile | 6 +----- src/utools.erl | 40 ++++++++++++++++++++++++++++++++++++++++ test/map_validate.erl | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 test/map_validate.erl diff --git a/.gitignore b/.gitignore index 37accca..5e1dcff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,10 @@ -ebin/* +deps +ebin +_rel .erlang.mk/ -utools.d -deps \ No newline at end of file +config +*.d +*.plt +*.beam +*.pem +*.dump \ No newline at end of file diff --git a/Makefile b/Makefile index e45c6dd..7072813 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,8 @@ PROJECT = utools PROJECT_DESCRIPTION = Umgeher Erlang Tools -PROJECT_VERSION = 0.2.0 +PROJECT_VERSION = 1.0.0 # Whitespace to be used when creating files from templates. SP = 2 -BUILD_DEPS = gitversion.mk -DEP_PLUGINS = gitversion.mk -dep_gitversion.mk = git https://git.sr.ht/~umgeher/gitversion.mk master - include erlang.mk diff --git a/src/utools.erl b/src/utools.erl index 9665650..ab21142 100644 --- a/src/utools.erl +++ b/src/utools.erl @@ -4,6 +4,7 @@ -export([b32_encode/1]). -export([hex_encode/1]). -export([hotp/2]). +-export([map_validate/2]). -export([rand_bytes/0, rand_bytes/1]). -export([rand_chars/1]). -export([rand_hash/0]). @@ -85,6 +86,45 @@ hotp(Token, Time) -> P = << <<48:8>> || _ <- lists:seq(1, 6 - byte_size(T)) >>, {ok, <

>}. +map_validate({_, _, {error, _} = Error}) -> + Error; +map_validate({Map, #{with := W} = Doc, R}) when is_list(W) -> + map_validate({maps:with(W, Map), maps:remove(with, Doc), R}); +map_validate({Map, #{rules := []} = Doc, R}) -> + map_validate({Map, maps:remove(rules, Doc), R}); +map_validate({Map, #{rules := [#{key := K, required := true} = Rule | T]} = Doc, R}) -> + map_validate({Map, Doc#{rules => T}, map_validate_rule(maps:get(K, Map, required), maps:remove(required, Rule), R)}); +map_validate({Map, #{rules := [#{key := K, default := nil} = Rule | T]} = Doc, R}) -> + map_validate({Map, Doc#{rules => T}, map_validate_rule(maps:get(K, Map, nil), maps:remove(required, Rule), R)}); +map_validate({Map, #{rules := [#{key := K, default := V} = Rule | T]} = Doc, R}) -> + map_validate({Map, Doc#{rules => T}, map_validate_rule(maps:get(K, Map, V), maps:remove(required, Rule), R)}); +map_validate({Map, #{rules := [_ | T]} = Doc, R}) -> + map_validate({Map, Doc#{rules => T}, R}); +map_validate({Map, #{merge := true} = Doc, R}) -> + map_validate({nil, maps:remove(merge, Doc), maps:merge(Map, R)}); +map_validate({_, #{without := W}, R}) when is_list(W) -> + map_validate({nil, #{}, maps:without(W, R)}); +map_validate({_, #{}, R}) -> + R. + +map_validate(#{} = Map, #{} = Doc) -> + map_validate({Map, Doc, #{}}); +map_validate(_, _) -> + {error, 'no data'}. + +map_validate_rule(required, #{key := K}, _) -> + {error, K}; +map_validate_rule(nil, _, M) -> + M; +map_validate_rule(V, #{prefn := FN} = Rule, M) when is_function(FN) -> + map_validate_rule(FN(V), maps:remove(prefn, Rule), M); +map_validate_rule(V, #{posfn := FN} = Rule, M) when is_function(FN) -> + map_validate_rule(FN(V), maps:remove(posfn, Rule), M); +map_validate_rule(V, #{key := K}, M) -> + M#{K => V}; +map_validate_rule(_, _, _) -> + {error, invalid}. + rand_bytes() -> rand_bytes(8). diff --git a/test/map_validate.erl b/test/map_validate.erl new file mode 100644 index 0000000..2388b6c --- /dev/null +++ b/test/map_validate.erl @@ -0,0 +1,32 @@ +-module(map_validate). +-include_lib("eunit/include/eunit.hrl"). + +-define(SAMPLE, #{<<"name">> => <<"umgeher">>, email => <<"me@umgeher.org">>}). + +returning_no_data_test() -> + ?assertEqual({error, 'no data'}, utools:map_validate('not a map', #{})), + ?assertEqual({error, 'no data'}, utools:map_validate(#{}, 'not a map')), + ?assertEqual({error, 'no data'}, utools:map_validate('not a map', 'not a map')). + +ok_without_doc_test() -> + ?assertEqual(#{}, utools:map_validate(?SAMPLE, #{})). + +ok_rule_required_test() -> + Rule = #{ + key => <<"name">>, + required => true + }, + ?assertEqual(#{<<"name">> => <<"umgeher">>}, utools:map_validate(?SAMPLE, #{rules => [Rule]})). + +error_required_missing_test() -> + Rule = #{key => some, required => true}, + ?assertEqual({error, some}, utools:map_validate(?SAMPLE, #{rules => [Rule]})). + +ok_rule_not_required_with_default_value_test() -> + Rule = #{key => some, default => 123}, + ?assertEqual(#{some => 123}, utools:map_validate(?SAMPLE, #{rules => [Rule]})). + +ok_merge_test() -> + Rule = #{key => some, default => 123}, + ?assertEqual(maps:merge(?SAMPLE, #{some => 123}), utools:map_validate(?SAMPLE, #{merge => true, rules => [Rule]})). +