feat(funcs): add bitsize/1 and subbits/2,3,6 functions
Given following Rule SQL: ``` select subbits(payload, 1, 8) as firstByte, case when firstByte = 123 then 't/{' when firstByte = 125 then 't/}' else 't/' + str(firstByte) end as tp from "t/#" ``` Input Payload: `{x}` Output: `{"tp": "t/{", "firstByte": 123}` Input Payload: `}x` Output: `{"tp": "t/}", "firstByte": 125}` Input Payload: `a` Output: `{"tp": "t/97", "firstByte": 97}`
This commit is contained in:
parent
573a4b2df8
commit
15d048d8ec
|
@ -78,6 +78,10 @@
|
|||
, bitxor/2
|
||||
, bitsl/2
|
||||
, bitsr/2
|
||||
, bitsize/1
|
||||
, subbits/2
|
||||
, subbits/3
|
||||
, subbits/6
|
||||
]).
|
||||
|
||||
%% Data Type Convertion
|
||||
|
@ -233,7 +237,7 @@ payload() ->
|
|||
|
||||
payload(Path) ->
|
||||
fun(#{payload := Payload}) when erlang:is_map(Payload) ->
|
||||
emqx_rule_maps:nested_get(map_path(Path), Payload);
|
||||
map_get(Path, Payload);
|
||||
(_) -> undefined
|
||||
end.
|
||||
|
||||
|
@ -401,6 +405,74 @@ bitsl(X, I) when is_integer(X), is_integer(I) ->
|
|||
bitsr(X, I) when is_integer(X), is_integer(I) ->
|
||||
X bsr I.
|
||||
|
||||
bitsize(Bits) when is_bitstring(Bits) ->
|
||||
bit_size(Bits).
|
||||
|
||||
subbits(Bits, Len) when is_integer(Len), is_bitstring(Bits) ->
|
||||
subbits(Bits, 1, Len).
|
||||
|
||||
subbits(Bits, Start, Len) when is_integer(Start), is_integer(Len), is_bitstring(Bits) ->
|
||||
get_subbits(Bits, Start, Len, <<"integer">>, <<"unsigned">>, <<"big">>).
|
||||
|
||||
subbits(Bits, Start, Len, Type, Signedness, Endianness) when is_integer(Start), is_integer(Len), is_bitstring(Bits) ->
|
||||
get_subbits(Bits, Start, Len, Type, Signedness, Endianness).
|
||||
|
||||
get_subbits(Bits, Start, Len, Type, Signedness, Endianness) ->
|
||||
Begin = Start - 1,
|
||||
case Bits of
|
||||
<<_:Begin, Rem/bits>> when Rem =/= <<>> ->
|
||||
Sz = bit_size(Rem),
|
||||
do_get_subbits(Rem, Sz, Len, Type, Signedness, Endianness);
|
||||
_ -> undefined
|
||||
end.
|
||||
|
||||
-define(match_bits(Bits0, Pattern, ElesePattern),
|
||||
case Bits0 of
|
||||
Pattern ->
|
||||
SubBits;
|
||||
ElesePattern ->
|
||||
SubBits
|
||||
end).
|
||||
do_get_subbits(Bits, Sz, Len, <<"integer">>, <<"unsigned">>, <<"big">>) ->
|
||||
?match_bits(Bits, <<SubBits:Len/integer-unsigned-big-unit:1, _/bits>>,
|
||||
<<SubBits:Sz/integer-unsigned-big-unit:1>>);
|
||||
do_get_subbits(Bits, Sz, Len, <<"float">>, <<"unsigned">>, <<"big">>) ->
|
||||
?match_bits(Bits, <<SubBits:Len/float-unsigned-big-unit:1, _/bits>>,
|
||||
<<SubBits:Sz/float-unsigned-big-unit:1>>);
|
||||
do_get_subbits(Bits, Sz, Len, <<"bits">>, <<"unsigned">>, <<"big">>) ->
|
||||
?match_bits(Bits, <<SubBits:Len/bits-unsigned-big-unit:1, _/bits>>,
|
||||
<<SubBits:Sz/bits-unsigned-big-unit:1>>);
|
||||
|
||||
do_get_subbits(Bits, Sz, Len, <<"integer">>, <<"signed">>, <<"big">>) ->
|
||||
?match_bits(Bits, <<SubBits:Len/integer-signed-big-unit:1, _/bits>>,
|
||||
<<SubBits:Sz/integer-signed-big-unit:1>>);
|
||||
do_get_subbits(Bits, Sz, Len, <<"float">>, <<"signed">>, <<"big">>) ->
|
||||
?match_bits(Bits, <<SubBits:Len/float-signed-big-unit:1, _/bits>>,
|
||||
<<SubBits:Sz/float-signed-big-unit:1>>);
|
||||
do_get_subbits(Bits, Sz, Len, <<"bits">>, <<"signed">>, <<"big">>) ->
|
||||
?match_bits(Bits, <<SubBits:Len/bits-signed-big-unit:1, _/bits>>,
|
||||
<<SubBits:Sz/bits-signed-big-unit:1>>);
|
||||
|
||||
do_get_subbits(Bits, Sz, Len, <<"integer">>, <<"unsigned">>, <<"little">>) ->
|
||||
?match_bits(Bits, <<SubBits:Len/integer-unsigned-little-unit:1, _/bits>>,
|
||||
<<SubBits:Sz/integer-unsigned-little-unit:1>>);
|
||||
do_get_subbits(Bits, Sz, Len, <<"float">>, <<"unsigned">>, <<"little">>) ->
|
||||
?match_bits(Bits, <<SubBits:Len/float-unsigned-little-unit:1, _/bits>>,
|
||||
<<SubBits:Sz/float-unsigned-little-unit:1>>);
|
||||
do_get_subbits(Bits, Sz, Len, <<"bits">>, <<"unsigned">>, <<"little">>) ->
|
||||
?match_bits(Bits, <<SubBits:Len/bits-unsigned-little-unit:1, _/bits>>,
|
||||
<<SubBits:Sz/bits-unsigned-little-unit:1>>);
|
||||
|
||||
do_get_subbits(Bits, Sz, Len, <<"integer">>, <<"signed">>, <<"little">>) ->
|
||||
?match_bits(Bits, <<SubBits:Len/integer-signed-little-unit:1, _/bits>>,
|
||||
<<SubBits:Sz/integer-signed-little-unit:1>>);
|
||||
do_get_subbits(Bits, Sz, Len, <<"float">>, <<"signed">>, <<"little">>) ->
|
||||
?match_bits(Bits, <<SubBits:Len/float-signed-little-unit:1, _/bits>>,
|
||||
<<SubBits:Sz/float-signed-little-unit:1>>);
|
||||
do_get_subbits(Bits, Sz, Len, <<"bits">>, <<"signed">>, <<"little">>) ->
|
||||
?match_bits(Bits, <<SubBits:Len/bits-signed-little-unit:1, _/bits>>,
|
||||
<<SubBits:Sz/bits-signed-little-unit:1>>).
|
||||
|
||||
%%------------------------------------------------------------------------------
|
||||
%% Data Type Convertion Funcs
|
||||
%%------------------------------------------------------------------------------
|
||||
|
@ -607,52 +679,10 @@ map_get(Key, Map) ->
|
|||
map_get(Key, Map, undefined).
|
||||
|
||||
map_get(Key, Map, Default) ->
|
||||
case maps:find(Key, Map) of
|
||||
{ok, Val} -> Val;
|
||||
error when is_atom(Key) ->
|
||||
%% the map may have an equivalent binary-form key
|
||||
BinKey = emqx_rule_utils:bin(Key),
|
||||
case maps:find(BinKey, Map) of
|
||||
{ok, Val} -> Val;
|
||||
error -> Default
|
||||
end;
|
||||
error when is_binary(Key) ->
|
||||
try %% the map may have an equivalent atom-form key
|
||||
AtomKey = list_to_existing_atom(binary_to_list(Key)),
|
||||
case maps:find(AtomKey, Map) of
|
||||
{ok, Val} -> Val;
|
||||
error -> Default
|
||||
end
|
||||
catch error:badarg ->
|
||||
Default
|
||||
end;
|
||||
error ->
|
||||
Default
|
||||
end.
|
||||
emqx_rule_maps:nested_get(map_path(Key), Map, Default).
|
||||
|
||||
map_put(Key, Val, Map) ->
|
||||
case maps:find(Key, Map) of
|
||||
{ok, _} -> maps:put(Key, Val, Map);
|
||||
error when is_atom(Key) ->
|
||||
%% the map may have an equivalent binary-form key
|
||||
BinKey = emqx_rule_utils:bin(Key),
|
||||
case maps:find(BinKey, Map) of
|
||||
{ok, _} -> maps:put(BinKey, Val, Map);
|
||||
error -> maps:put(Key, Val, Map)
|
||||
end;
|
||||
error when is_binary(Key) ->
|
||||
try %% the map may have an equivalent atom-form key
|
||||
AtomKey = list_to_existing_atom(binary_to_list(Key)),
|
||||
case maps:find(AtomKey, Map) of
|
||||
{ok, _} -> maps:put(AtomKey, Val, Map);
|
||||
error -> maps:put(Key, Val, Map)
|
||||
end
|
||||
catch error:badarg ->
|
||||
maps:put(Key, Val, Map)
|
||||
end;
|
||||
error ->
|
||||
maps:put(Key, Val, Map)
|
||||
end.
|
||||
emqx_rule_maps:nested_put(map_path(Key), Val, Map).
|
||||
|
||||
mget(Key, Map) ->
|
||||
mget(Key, Map, undefined).
|
||||
|
|
|
@ -489,11 +489,15 @@ t_contains(_) ->
|
|||
|
||||
t_map_get(_) ->
|
||||
?assertEqual(1, apply_func(map_get, [<<"a">>, #{a => 1}])),
|
||||
?assertEqual(undefined, apply_func(map_get, [<<"a">>, #{}])).
|
||||
?assertEqual(undefined, apply_func(map_get, [<<"a">>, #{}])),
|
||||
?assertEqual(1, apply_func(map_get, [<<"a.b">>, #{a => #{b => 1}}])),
|
||||
?assertEqual(undefined, apply_func(map_get, [<<"a.c">>, #{a => #{b => 1}}])).
|
||||
|
||||
t_map_put(_) ->
|
||||
?assertEqual(#{<<"a">> => 1}, apply_func(map_put, [<<"a">>, 1, #{}])),
|
||||
?assertEqual(#{a => 2}, apply_func(map_put, [<<"a">>, 2, #{a => 1}])).
|
||||
?assertEqual(#{a => 2}, apply_func(map_put, [<<"a">>, 2, #{a => 1}])),
|
||||
?assertEqual(#{<<"a">> => #{<<"b">> => 1}}, apply_func(map_put, [<<"a.b">>, 1, #{}])),
|
||||
?assertEqual(#{a => #{b => 1, <<"c">> => 1}}, apply_func(map_put, [<<"a.c">>, 1, #{a => #{b => 1}}])).
|
||||
|
||||
t_mget(_) ->
|
||||
?assertEqual(1, apply_func(map_get, [<<"a">>, #{a => 1}])),
|
||||
|
@ -505,6 +509,55 @@ t_map_put(_) ->
|
|||
?assertEqual(#{<<"a">> => 2}, apply_func(map_put, [<<"a">>, 2, #{<<"a">> => 1}])),
|
||||
?assertEqual(#{a => 2}, apply_func(map_put, [<<"a">>, 2, #{a => 1}])).
|
||||
|
||||
t_bitsize(_) ->
|
||||
?assertEqual(8, apply_func(bitsize, [<<"a">>])),
|
||||
?assertEqual(4, apply_func(bitsize, [<<15:4>>])).
|
||||
|
||||
t_subbits(_) ->
|
||||
?assertEqual(1, apply_func(subbits, [<<255:8>>, 1])),
|
||||
?assertEqual(3, apply_func(subbits, [<<255:8>>, 2])),
|
||||
?assertEqual(7, apply_func(subbits, [<<255:8>>, 3])),
|
||||
?assertEqual(15, apply_func(subbits, [<<255:8>>, 4])),
|
||||
?assertEqual(31, apply_func(subbits, [<<255:8>>, 5])),
|
||||
?assertEqual(63, apply_func(subbits, [<<255:8>>, 6])),
|
||||
?assertEqual(127, apply_func(subbits, [<<255:8>>, 7])),
|
||||
?assertEqual(255, apply_func(subbits, [<<255:8>>, 8])).
|
||||
|
||||
t_subbits2(_) ->
|
||||
?assertEqual(1, apply_func(subbits, [<<255:8>>, 1, 1])),
|
||||
?assertEqual(3, apply_func(subbits, [<<255:8>>, 1, 2])),
|
||||
?assertEqual(7, apply_func(subbits, [<<255:8>>, 1, 3])),
|
||||
?assertEqual(15, apply_func(subbits, [<<255:8>>, 1, 4])),
|
||||
?assertEqual(31, apply_func(subbits, [<<255:8>>, 1, 5])),
|
||||
?assertEqual(63, apply_func(subbits, [<<255:8>>, 1, 6])),
|
||||
?assertEqual(127, apply_func(subbits, [<<255:8>>, 1, 7])),
|
||||
?assertEqual(255, apply_func(subbits, [<<255:8>>, 1, 8])).
|
||||
|
||||
t_subbits2_1(_) ->
|
||||
?assertEqual(1, apply_func(subbits, [<<255:8>>, 2, 1])),
|
||||
?assertEqual(3, apply_func(subbits, [<<255:8>>, 2, 2])),
|
||||
?assertEqual(7, apply_func(subbits, [<<255:8>>, 2, 3])),
|
||||
?assertEqual(15, apply_func(subbits, [<<255:8>>, 2, 4])),
|
||||
?assertEqual(31, apply_func(subbits, [<<255:8>>, 2, 5])),
|
||||
?assertEqual(63, apply_func(subbits, [<<255:8>>, 2, 6])),
|
||||
?assertEqual(127, apply_func(subbits, [<<255:8>>, 2, 7])),
|
||||
?assertEqual(127, apply_func(subbits, [<<255:8>>, 2, 8])).
|
||||
|
||||
t_subbits2_integer(_) ->
|
||||
?assertEqual(456, apply_func(subbits, [<<456:32/integer>>, 1, 32, <<"integer">>, <<"signed">>, <<"big">>])),
|
||||
?assertEqual(-456, apply_func(subbits, [<<-456:32/integer>>, 1, 32, <<"integer">>, <<"signed">>, <<"big">>])).
|
||||
|
||||
t_subbits2_float(_) ->
|
||||
R = apply_func(subbits, [<<5.3:64/float>>, 1, 64, <<"float">>, <<"unsigned">>, <<"big">>]),
|
||||
RL = (5.3 - R),
|
||||
ct:pal(";;;;~p", [R]),
|
||||
?assert( (RL >= 0 andalso RL < 0.0001) orelse (RL =< 0 andalso RL > -0.0001)),
|
||||
|
||||
R2 = apply_func(subbits, [<<-5.3:64/float>>, 1, 64, <<"float">>, <<"signed">>, <<"big">>]),
|
||||
|
||||
RL2 = (5.3 + R2),
|
||||
ct:pal(";;;;~p", [R2]),
|
||||
?assert( (RL2 >= 0 andalso RL2 < 0.0001) orelse (RL2 =< 0 andalso RL2 > -0.0001)).
|
||||
|
||||
%%------------------------------------------------------------------------------
|
||||
%% Test cases for Hash funcs
|
||||
|
|
Loading…
Reference in New Issue