Skip to content

Commit

Permalink
implement verbatim chunks
Browse files Browse the repository at this point in the history
  • Loading branch information
Pierre Avital committed Jan 19, 2024
1 parent 3fc5d18 commit 1d109ad
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 64 deletions.
43 changes: 14 additions & 29 deletions commons/zenoh-keyexpr/src/key_expr/include.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// Contributors:
// ZettaScale Zenoh Team, <[email protected]>
//
use super::{keyexpr, utils::Split, DELIMITER, DOUBLE_WILD, STAR_DSL};
use super::{intersect::MayHaveVerbatim, keyexpr, utils::Split, DELIMITER, DOUBLE_WILD, STAR_DSL};

pub const DEFAULT_INCLUDER: LTRIncluder = LTRIncluder;

Expand All @@ -22,35 +22,11 @@ pub trait Includer<Left, Right> {

impl<T: for<'a> Includer<&'a [u8], &'a [u8]>> Includer<&keyexpr, &keyexpr> for T {
fn includes(&self, left: &keyexpr, right: &keyexpr) -> bool {
let mut left = left.as_bytes();
let mut right = right.as_bytes();
let left = left.as_bytes();
let right = right.as_bytes();
if left == right {
return true;
}

if unsafe { *left.get_unchecked(0) == b'@' || *right.get_unchecked(0) == b'@' } {
let mut end = left.len().min(right.len());
for i in 0..end {
if left[i] != right[i] {
return false;
}
if left[i] == DELIMITER {
end = i;
break;
}
}
if left.len() == end {
return false;
}
if right.len() == end {
return left.get(end..) == Some(b"/**");
}
left = &left[(end + 1)..];
right = &right[(end + 1)..];
}
if left == b"**" {
return true;
}
self.includes(left, right)
}
}
Expand All @@ -62,9 +38,12 @@ impl Includer<&[u8], &[u8]> for LTRIncluder {
let (lchunk, lrest) = left.split_once(&DELIMITER);
let lempty = lrest.is_empty();
if lchunk == DOUBLE_WILD {
if lempty || self.includes(lrest, right) {
if (lempty && !right.has_verbatim()) || self.includes(lrest, right) {
return true;
}
if unsafe { right.has_direct_verbatim_non_empty() } {
return false;
}
right = right.split_once(&DELIMITER).1;
if right.is_empty() {
return false;
Expand All @@ -90,7 +69,13 @@ impl Includer<&[u8], &[u8]> for LTRIncluder {

impl LTRIncluder {
fn non_double_wild_chunk_includes(&self, lchunk: &[u8], rchunk: &[u8]) -> bool {
if lchunk == b"*" || lchunk == rchunk {
if lchunk == rchunk {
true
} else if unsafe {
lchunk.has_direct_verbatim_non_empty() || rchunk.has_direct_verbatim_non_empty()
} {
false
} else if lchunk == b"*" {
true
} else if lchunk.contains(&b'$') {
let mut spleft = lchunk.splitter(STAR_DSL);
Expand Down
23 changes: 16 additions & 7 deletions commons/zenoh-keyexpr/src/key_expr/intersect/classical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ fn chunk_intersect<const STAR_DSL: bool>(c1: &[u8], c2: &[u8]) -> bool {
if c1 == c2 {
return true;
}
if c1.has_direct_verbatim() || c2.has_direct_verbatim() {
return false;
}
chunk_it_intersect::<STAR_DSL>(c1, c2)
}

Expand All @@ -83,14 +86,20 @@ fn it_intersect<const STAR_DSL: bool>(mut it1: &[u8], mut it2: &[u8]) -> bool {
let (current2, advanced2) = next(it2);
match (current1, current2) {
(b"**", _) => {
return advanced1.is_empty()
|| it_intersect::<STAR_DSL>(advanced1, it2)
|| it_intersect::<STAR_DSL>(it1, advanced2);
if advanced1.is_empty() {
return !it2.has_verbatim();
}
return (!unsafe { current2.has_direct_verbatim_non_empty() }
&& it_intersect::<STAR_DSL>(it1, advanced2))
|| it_intersect::<STAR_DSL>(advanced1, it2);
}
(_, b"**") => {
return advanced2.is_empty()
|| it_intersect::<STAR_DSL>(it1, advanced2)
|| it_intersect::<STAR_DSL>(advanced1, it2);
if advanced2.is_empty() {
return !it1.has_verbatim();
}
return (!unsafe { current1.has_direct_verbatim_non_empty() }
&& it_intersect::<STAR_DSL>(advanced1, it2))
|| it_intersect::<STAR_DSL>(it1, advanced2);
}
(sub1, sub2) if chunk_intersect::<STAR_DSL>(sub1, sub2) => {
it1 = advanced1;
Expand All @@ -111,7 +120,7 @@ pub fn intersect<const STAR_DSL: bool>(s1: &[u8], s2: &[u8]) -> bool {
}

use super::restiction::NoSubWilds;
use super::Intersector;
use super::{Intersector, MayHaveVerbatim};

pub struct ClassicIntersector;
impl Intersector<NoSubWilds<&[u8]>, NoSubWilds<&[u8]>> for ClassicIntersector {
Expand Down
53 changes: 25 additions & 28 deletions commons/zenoh-keyexpr/src/key_expr/intersect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,39 +90,36 @@ impl<
> Intersector<&keyexpr, &keyexpr> for T
{
fn intersect(&self, left: &keyexpr, right: &keyexpr) -> bool {
let mut left_bytes = left.as_bytes();
let mut right_bytes = right.as_bytes();
let left_bytes = left.as_bytes();
let right_bytes = right.as_bytes();
if left_bytes == right_bytes {
return true;
}
let complexity = left.match_complexity() as u8 | right.match_complexity() as u8;
if complexity == 0 {
return false;
}
if unsafe { *left_bytes.get_unchecked(0) == b'@' || *right_bytes.get_unchecked(0) == b'@' }
{
let mut end = left_bytes.len().min(right_bytes.len());
for i in 0..end {
if left_bytes[i] != right_bytes[i] {
return false;
}
if left_bytes[i] == DELIMITER {
end = i;
break;
}
}
if left_bytes.len() == end {
return right_bytes.get(end..) == Some(b"/**");
}
if right_bytes.len() == end {
return left_bytes.get(end..) == Some(b"/**");
}
left_bytes = &left_bytes[(end + 1)..];
right_bytes = &right_bytes[(end + 1)..];
}
match complexity {
match left.match_complexity() as u8 | right.match_complexity() as u8 {
0 => false,
1 => self.intersect(NoSubWilds(left_bytes), NoSubWilds(right_bytes)),
_ => self.intersect(left_bytes, right_bytes),
}
}
}

pub(crate) trait MayHaveVerbatim {
fn has_verbatim(&self) -> bool;
fn has_direct_verbatim(&self) -> bool;
unsafe fn has_direct_verbatim_non_empty(&self) -> bool {
self.has_direct_verbatim()
}
}

impl MayHaveVerbatim for [u8] {
fn has_direct_verbatim(&self) -> bool {
matches!(self, [b'@', ..])
}
fn has_verbatim(&self) -> bool {
self.split(|c| *c == DELIMITER)
.any(MayHaveVerbatim::has_direct_verbatim)
}
unsafe fn has_direct_verbatim_non_empty(&self) -> bool {
unsafe { *self.get_unchecked(0) == b'@' }
}
}
14 changes: 14 additions & 0 deletions commons/zenoh-keyexpr/src/key_expr/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ fn intersections() {
assert!(intersect("@a", "@a/**"));
assert!(!intersect("**/xyz$*xyz", "@a/b/xyzdefxyz"));
assert!(intersect("@a/**/c/**/e", "@a/b/b/b/c/d/d/d/e"));
assert!(!intersect("@a/**/c/**/e", "@a/@b/b/b/c/d/d/d/e"));
assert!(intersect("@a/**/@c/**/e", "@a/b/b/b/@c/d/d/d/e"));
assert!(intersect("@a/**/e", "@a/b/b/d/d/d/e"));
assert!(intersect("@a/**/e", "@a/b/b/b/d/d/d/e"));
assert!(intersect("@a/**/e", "@a/b/b/c/d/d/d/e"));
assert!(!intersect("@a/**/e", "@a/b/b/@c/b/d/d/d/e"));
assert!(!intersect("@a/*", "@a/@b"));
assert!(!intersect("@a/**", "@a/@b"));
assert!(intersect("@a/**/@b", "@a/@b"));
assert!(intersect("@a/@b/**", "@a/@b"));
}

fn includes<
Expand Down Expand Up @@ -167,6 +177,10 @@ fn inclusions() {
assert!(includes("@a/**", "@a"));
assert!(!includes("**/xyz$*xyz", "@a/b/xyzdefxyz"));
assert!(includes("@a/**/c/**/e", "@a/b/b/b/c/d/d/d/e"));
assert!(!includes("@a/*", "@a/@b"));
assert!(!includes("@a/**", "@a/@b"));
assert!(includes("@a/**/@b", "@a/@b"));
assert!(includes("@a/@b/**", "@a/@b"));
}

#[test]
Expand Down

0 comments on commit 1d109ad

Please sign in to comment.