From 9ace40a3871cab903c259004d35acdf13110a683 Mon Sep 17 00:00:00 2001 From: Daniel Widgren Date: Sun, 7 Nov 2021 16:50:40 +0100 Subject: [PATCH 1/3] Fixed so we don't get non_deterministic error, but fails to fetch paths --- src/routing_tree.erl | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/routing_tree.erl b/src/routing_tree.erl index 7ff1bf1..d1ab5b8 100644 --- a/src/routing_tree.erl +++ b/src/routing_tree.erl @@ -252,26 +252,37 @@ find_comparator(Comparator, [_Node|Tl]) -> find_comparator(Comparator, Tl). check_conflicting_nodes(_, _, _, _, []) -> false; -check_conflicting_nodes(segment, Ident, [] = Tl, CompNode, Siblings) -> - first(fun(#node{value = Value, segment = Segment, is_binding = false, is_wildcard = false} = Node) -> - {[ C || #node_comp{comparator = C} <- Value, - C == CompNode#node_comp.comparator ] /= [] andalso Segment == Ident andalso Tl /= [], {duplicate, Node}}; - (#node{is_binding = true} = Node) -> - {true, {conflict, Node}}; - (#node{is_wildcard = true} = Node) -> - {true, {conflict, Node}} - end, Siblings); +check_conflicting_nodes(segment, Ident, [], CompNode, Siblings) -> + check_aux(Siblings, CompNode, Ident, segment); check_conflicting_nodes(binding, Ident, _Tl, CompNode, Siblings) -> - first(fun(#node{is_binding = true, value = Value, segment = Segment}) -> Segment == Ident andalso - [ X || #node_comp{comparator = C, value = X} <- Value, - C == CompNode#node_comp.comparator ] /= []; - (#node{is_wildcard = true}) -> true; - (#node{value = Value} = Node) -> - {[ X || #node_comp{comparator = C, value = X} <- Value, C == CompNode#node_comp.comparator ] /= [], {conflict, Node}} - end, Siblings); + check_aux(Siblings, CompNode, Ident, binding); check_conflicting_nodes(_, _, _, _, _) -> false. +check_aux([], _, _, _) -> false; +check_aux([Elem|T], CompNode, Ident, binding) -> + case check_conflicting_nodes_binding(Elem, CompNode, Ident) of + {true, Res} -> Res; + _ -> check_aux(T, CompNode, Ident, binding) + end; +check_aux([Elem|T], CompNode, Ident, segment) -> + case check_conflicting_nodes_segment(Elem, CompNode, Ident) of + {true, Res} -> Res; + _ -> check_aux(T, CompNode, Ident, segment) + end. +check_conflicting_nodes_segment(#node{value = Value, segment = Segment, is_binding = false, is_wildcard = false} = Node, CompNode, Ident) -> + {[ C || #node_comp{comparator = C} <- Value, + C == CompNode#node_comp.comparator ] /= [] andalso Segment == Ident, {duplicate, Node}}; +check_conflicting_nodes_segment(#node{is_binding = true} = Node, _, _) -> {true, {conflict, Node}}; +check_conflicting_nodes_segment(#node{is_wildcard = true} = Node, _, _) -> {true, {conflict, Node}}. + + check_conflicting_nodes_binding(#node{value = Value, segment = Segment} = Node, CompNode, Ident) -> + Segment == Ident andalso + {[ X || #node_comp{comparator = C, value = X} <- Value, + C == CompNode#node_comp.comparator ] /= [], {conflict, Node}}; +check_conflicting_nodes_binding(#node{is_wildcard = true}, _, _) -> true; +check_conflicting_nodes_binding(#node{value = Value} = Node, CompNode, _) -> + {[ X || #node_comp{comparator = C, value = X} <- Value, C == CompNode#node_comp.comparator ] /= [], {conflict, Node}}. first(_Fun, []) -> false; first(Fun, [Elem|Tl]) -> From 7245168fdbb3ec3f8e255171271ee1ed9f09647b Mon Sep 17 00:00:00 2001 From: Daniel Widgren Date: Sun, 7 Nov 2021 16:50:40 +0100 Subject: [PATCH 2/3] Fixed so we don't get non_deterministic error, but fails to fetch paths --- src/routing_tree.erl | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/routing_tree.erl b/src/routing_tree.erl index 7ff1bf1..d1ab5b8 100644 --- a/src/routing_tree.erl +++ b/src/routing_tree.erl @@ -252,26 +252,37 @@ find_comparator(Comparator, [_Node|Tl]) -> find_comparator(Comparator, Tl). check_conflicting_nodes(_, _, _, _, []) -> false; -check_conflicting_nodes(segment, Ident, [] = Tl, CompNode, Siblings) -> - first(fun(#node{value = Value, segment = Segment, is_binding = false, is_wildcard = false} = Node) -> - {[ C || #node_comp{comparator = C} <- Value, - C == CompNode#node_comp.comparator ] /= [] andalso Segment == Ident andalso Tl /= [], {duplicate, Node}}; - (#node{is_binding = true} = Node) -> - {true, {conflict, Node}}; - (#node{is_wildcard = true} = Node) -> - {true, {conflict, Node}} - end, Siblings); +check_conflicting_nodes(segment, Ident, [], CompNode, Siblings) -> + check_aux(Siblings, CompNode, Ident, segment); check_conflicting_nodes(binding, Ident, _Tl, CompNode, Siblings) -> - first(fun(#node{is_binding = true, value = Value, segment = Segment}) -> Segment == Ident andalso - [ X || #node_comp{comparator = C, value = X} <- Value, - C == CompNode#node_comp.comparator ] /= []; - (#node{is_wildcard = true}) -> true; - (#node{value = Value} = Node) -> - {[ X || #node_comp{comparator = C, value = X} <- Value, C == CompNode#node_comp.comparator ] /= [], {conflict, Node}} - end, Siblings); + check_aux(Siblings, CompNode, Ident, binding); check_conflicting_nodes(_, _, _, _, _) -> false. +check_aux([], _, _, _) -> false; +check_aux([Elem|T], CompNode, Ident, binding) -> + case check_conflicting_nodes_binding(Elem, CompNode, Ident) of + {true, Res} -> Res; + _ -> check_aux(T, CompNode, Ident, binding) + end; +check_aux([Elem|T], CompNode, Ident, segment) -> + case check_conflicting_nodes_segment(Elem, CompNode, Ident) of + {true, Res} -> Res; + _ -> check_aux(T, CompNode, Ident, segment) + end. +check_conflicting_nodes_segment(#node{value = Value, segment = Segment, is_binding = false, is_wildcard = false} = Node, CompNode, Ident) -> + {[ C || #node_comp{comparator = C} <- Value, + C == CompNode#node_comp.comparator ] /= [] andalso Segment == Ident, {duplicate, Node}}; +check_conflicting_nodes_segment(#node{is_binding = true} = Node, _, _) -> {true, {conflict, Node}}; +check_conflicting_nodes_segment(#node{is_wildcard = true} = Node, _, _) -> {true, {conflict, Node}}. + + check_conflicting_nodes_binding(#node{value = Value, segment = Segment} = Node, CompNode, Ident) -> + Segment == Ident andalso + {[ X || #node_comp{comparator = C, value = X} <- Value, + C == CompNode#node_comp.comparator ] /= [], {conflict, Node}}; +check_conflicting_nodes_binding(#node{is_wildcard = true}, _, _) -> true; +check_conflicting_nodes_binding(#node{value = Value} = Node, CompNode, _) -> + {[ X || #node_comp{comparator = C, value = X} <- Value, C == CompNode#node_comp.comparator ] /= [], {conflict, Node}}. first(_Fun, []) -> false; first(Fun, [Elem|Tl]) -> From 2d4ed413514772417f66c8d9c8d51b33dfc99301 Mon Sep 17 00:00:00 2001 From: Daniel Widgren Date: Mon, 8 Nov 2021 22:48:53 +0100 Subject: [PATCH 3/3] Fixed insert when next segment is empty. --- src/routing_tree.erl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/routing_tree.erl b/src/routing_tree.erl index d1ab5b8..3bca38b 100644 --- a/src/routing_tree.erl +++ b/src/routing_tree.erl @@ -185,6 +185,9 @@ insert([{Type, _, Ident}|Tl], CompNode, Siblings, Options = #{use_strict := UseS [] -> [#node{segment = value(Ident, Options), is_binding = Type == binding, is_wildcard = Type == wildcard, value = [CompNode]} | Siblings]; + [{segment, 1, []}] -> + [#node{segment = value(Ident, Options), is_binding = Type == binding, is_wildcard = Type == wildcard, + value = [CompNode]} | Siblings]; _ -> [#node{segment = value(Ident, Options), is_binding = Type == binding, is_wildcard = Type == wildcard, children = insert(Tl, CompNode, [], Options)} | Siblings]