Skip to content
Permalink
Browse files

Add rule engine utils

  • Loading branch information...
terry-xiaoyu committed May 21, 2019
1 parent fc44b7c commit fa37205850c6efe9af5f8ca2f230e17c7de2adb4
Showing with 106 additions and 0 deletions.
  1. +74 −0 src/emqx_rule_utils.erl
  2. +32 −0 test/emqx_rule_utils_tests.erl
@@ -0,0 +1,74 @@
%% Copyright (c) 2019 EMQ Technologies Co., Ltd. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.

-module(emqx_rule_utils).

%% preprocess and process tempalte string with place holders
-export([ preproc_tmpl/1
, proc_tmpl/2]).

%% type converting
-export([ str/1
, bin/1
, number_to_binary/1
]).

-define(EX_PLACE_HOLDER, "(\\$\\{[a-zA-Z0-9\\._]+\\})").

-type(tmpl_token() :: list({var, fun()} | {str, binary()})).

%% preprocess template string with place holders
-spec(preproc_tmpl(binary()) -> tmpl_token()).
preproc_tmpl(Str) ->
Tokens = re:split(Str, ?EX_PLACE_HOLDER, [{return,binary},group]),
preproc_tmpl(Tokens, []).

preproc_tmpl([], Acc) ->
lists:reverse(Acc);
preproc_tmpl([[Tkn, Phld]| Tokens], Acc) ->
preproc_tmpl(Tokens,
[{var, fun(Data) -> bin(maps:get(atom_key(var(Phld)), Data, undefined)) end},
{str, Tkn} | Acc]);
preproc_tmpl([[Tkn]| Tokens], Acc) ->
preproc_tmpl(Tokens, [{str, Tkn} | Acc]).

-spec(proc_tmpl(tmpl_token(), binary()) -> binary()).
proc_tmpl(Tokens, Data) ->
list_to_binary(
lists:map(
fun ({str, Tkn}) -> Tkn;
({var, GetVal}) -> GetVal(Data)
end, Tokens)).

atom_key(Key) ->
try binary_to_existing_atom(Key, utf8)
catch error:badarg -> error({invalid_key, Key})
end.

var(<<"${", Val/binary>>) ->
binary:part(Val, {0, byte_size(Val)-1}).

str(List) when is_list(List) -> List;
str(Bin) when is_binary(Bin) -> binary_to_list(Bin);
str(Atom) when is_atom(Atom) -> atom_to_list(Atom).

bin(List) when is_list(List) -> list_to_binary(List);
bin(Bin) when is_binary(Bin) -> Bin;
bin(Num) when is_number(Num) -> number_to_binary(Num);
bin(Atom) when is_atom(Atom) -> atom_to_binary(Atom, utf8).

number_to_binary(Int) when is_integer(Int) ->
integer_to_binary(Int);
number_to_binary(Float) when is_float(Float) ->
float_to_binary(Float).
@@ -0,0 +1,32 @@
%% Copyright (c) 2019 EMQ Technologies Co., Ltd. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.

-module(emqx_rule_utils_tests).

-include_lib("eunit/include/eunit.hrl").

preproc_tmpl_test_() ->
[ ?_assertMatch([{str, <<"value: a">>} | _], emqx_rule_utils:preproc_tmpl(<<"value: a">>))
, ?_assertMatch([{str, <<"value: ">>} | _], emqx_rule_utils:preproc_tmpl(<<"value: ${a}">>))
, ?_assertMatch([{str,<<"key: ">>}, {var,_},
{str,<<", value: ">>}, {var,_},
{str,<<".">>}], emqx_rule_utils:preproc_tmpl(<<"key: ${k}, value: ${v}.">>))
].

proc_tmpl_test_() ->
Tokens0 = emqx_rule_utils:preproc_tmpl(<<"key: ${k}, value: ${v}.">>),
Tokens1 = emqx_rule_utils:preproc_tmpl(<<"str = ${k}:${v}:${k}.">>),
[ ?_assertEqual(<<"key: greet, value: hello.">>, emqx_rule_utils:proc_tmpl(Tokens0, #{k => greet, v => hello}))
, ?_assertEqual(<<"str = greet:hello:greet.">>, emqx_rule_utils:proc_tmpl(Tokens1, #{k => greet, v => hello}))
].

0 comments on commit fa37205

Please sign in to comment.
You can’t perform that action at this time.