zenoh_keyexpr/key_expr/intersect/
classical.rs1#[cold]
15fn star_dsl_intersect(mut it1: &[u8], mut it2: &[u8]) -> bool {
16 fn next(s: &[u8]) -> (u8, &[u8]) {
17 (s[0], &s[1..])
18 }
19 while !it1.is_empty() && !it2.is_empty() {
20 let (current1, advanced1) = next(it1);
21 let (current2, advanced2) = next(it2);
22 match (current1, current2) {
23 (b'$', b'$') => {
24 if advanced1.len() == 1 || advanced2.len() == 1 {
25 return true;
26 }
27 if star_dsl_intersect(&advanced1[1..], it2) {
28 return true;
29 } else {
30 return star_dsl_intersect(it1, &advanced2[1..]);
31 };
32 }
33 (b'$', _) => {
34 if advanced1.len() == 1 {
35 return true;
36 }
37 if star_dsl_intersect(&advanced1[1..], it2) {
38 return true;
39 }
40 it2 = advanced2;
41 }
42 (_, b'$') => {
43 if advanced2.len() == 1 {
44 return true;
45 }
46 if star_dsl_intersect(it1, &advanced2[1..]) {
47 return true;
48 }
49 it1 = advanced1;
50 }
51 (sub1, sub2) if sub1 == sub2 => {
52 it1 = advanced1;
53 it2 = advanced2;
54 }
55 (_, _) => return false,
56 }
57 }
58 it1.is_empty() && it2.is_empty() || it1 == b"$*" || it2 == b"$*"
59}
60
61fn chunk_it_intersect<const STAR_DSL: bool>(it1: &[u8], it2: &[u8]) -> bool {
62 it1 == b"*" || it2 == b"*" || (STAR_DSL && star_dsl_intersect(it1, it2))
63}
64#[inline(always)]
65fn chunk_intersect<const STAR_DSL: bool>(c1: &[u8], c2: &[u8]) -> bool {
66 if c1 == c2 {
67 return true;
68 }
69 if c1.has_direct_verbatim() || c2.has_direct_verbatim() {
70 return false;
71 }
72 chunk_it_intersect::<STAR_DSL>(c1, c2)
73}
74
75#[inline(always)]
76fn next(s: &[u8]) -> (&[u8], &[u8]) {
77 match s.iter().position(|c| *c == b'/') {
78 Some(i) => (&s[..i], &s[(i + 1)..]),
79 None => (s, b""),
80 }
81}
82
83fn it_intersect<const STAR_DSL: bool>(mut it1: &[u8], mut it2: &[u8]) -> bool {
84 while !it1.is_empty() && !it2.is_empty() {
85 let (current1, advanced1) = next(it1);
86 let (current2, advanced2) = next(it2);
87 match (current1, current2) {
88 (b"**", _) => {
89 if advanced1.is_empty() {
90 return !it2.has_verbatim();
91 }
92 return (!unsafe { current2.has_direct_verbatim_non_empty() }
93 && it_intersect::<STAR_DSL>(it1, advanced2))
94 || it_intersect::<STAR_DSL>(advanced1, it2);
95 }
96 (_, b"**") => {
97 if advanced2.is_empty() {
98 return !it1.has_verbatim();
99 }
100 return (!unsafe { current1.has_direct_verbatim_non_empty() }
101 && it_intersect::<STAR_DSL>(advanced1, it2))
102 || it_intersect::<STAR_DSL>(it1, advanced2);
103 }
104 (sub1, sub2) if chunk_intersect::<STAR_DSL>(sub1, sub2) => {
105 it1 = advanced1;
106 it2 = advanced2;
107 }
108 (_, _) => return false,
109 }
110 }
111 (it1.is_empty() || it1 == b"**") && (it2.is_empty() || it2 == b"**")
112}
113#[inline(always)]
118pub fn intersect<const STAR_DSL: bool>(s1: &[u8], s2: &[u8]) -> bool {
119 it_intersect::<STAR_DSL>(s1, s2)
120}
121
122use super::{restriction::NoSubWilds, Intersector, MayHaveVerbatim};
123
124pub struct ClassicIntersector;
125impl Intersector<NoSubWilds<&[u8]>, NoSubWilds<&[u8]>> for ClassicIntersector {
126 fn intersect(&self, left: NoSubWilds<&[u8]>, right: NoSubWilds<&[u8]>) -> bool {
127 intersect::<false>(left.0, right.0)
128 }
129}
130
131impl Intersector<&[u8], &[u8]> for ClassicIntersector {
132 fn intersect(&self, left: &[u8], right: &[u8]) -> bool {
133 intersect::<true>(left, right)
134 }
135}