fix(topic): respect special topic rules when intersecting

This commit is contained in:
Andrew Mayorov 2024-05-29 12:49:53 +02:00 committed by Serge Tupchii
parent de1ac131f7
commit 24be189728
2 changed files with 24 additions and 1 deletions

View File

@ -111,11 +111,18 @@ match(_, _) ->
-spec intersection(TopicOrFilter, TopicOrFilter) -> TopicOrFilter | false when
TopicOrFilter :: emqx_types:topic().
intersection(Topic1, Topic2) when is_binary(Topic1), is_binary(Topic2) ->
case intersection(words(Topic1), words(Topic2), []) of
case intersect_start(words(Topic1), words(Topic2)) of
[] -> false;
Intersection -> join(lists:reverse(Intersection))
end.
intersect_start([<<"$", _/bytes>> | _], [W | _]) when ?IS_WILDCARD(W) ->
[];
intersect_start([W | _], [<<"$", _/bytes>> | _]) when ?IS_WILDCARD(W) ->
[];
intersect_start(Words1, Words2) ->
intersection(Words1, Words2, []).
intersection(Words1, ['#'], Acc) ->
lists:reverse(Words1, Acc);
intersection(['#'], Words2, Acc) ->

View File

@ -28,6 +28,7 @@
[
wildcard/1,
match/2,
intersection/2,
validate/1,
prepend/2,
join/1,
@ -128,6 +129,21 @@ t_match_perf(_) ->
true = match(Name, Filter),
ok = bench('match/2', fun emqx_topic:match/2, [Name, Filter]).
t_intersect(_) ->
<<"t/global/1/+">> = intersection(<<"t/global/#">>, <<"t/+/1/+">>),
<<"t/global/#">> = intersection(<<"t/global/#">>, <<"#">>),
<<"t/global/#">> = intersection(<<"t/global/#">>, <<"t/global/#">>),
<<"1/2/3/4/5">> = intersection(<<"1/+/3/+/5/#">>, <<"+/2/+/4/+">>),
<<"t/local/1">> = intersection(<<"t/local/1/#">>, <<"t/local/+">>),
false = intersection(<<"t/global/#">>, <<"t/local/+">>),
false = intersection(<<"t/local/1/+">>, <<"t/local/+">>).
t_sys_intersect(_) ->
<<"$SYS/broker/+">> = intersection(<<"$SYS/broker/#">>, <<"$SYS/+/+">>),
<<"$SYS/broker">> = intersection(<<"$SYS/broker">>, <<"$SYS/+">>),
false = intersection(<<"$SYS/broker">>, <<"+/+">>),
false = intersection(<<"$SYS/broker">>, <<"#">>).
t_validate(_) ->
true = validate(<<"a/+/#">>),
true = validate(<<"a/b/c/d">>),