Skip to content

Commit

Permalink
feat(utils): additional set operations (#39)
Browse files Browse the repository at this point in the history
* rename traits

* subset

* intersection

* prove set intersection

* assert invariants

* fix doctest
  • Loading branch information
sinui0 authored Sep 5, 2024
1 parent 45370cc commit e7b2db6
Show file tree
Hide file tree
Showing 13 changed files with 524 additions and 105 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["utils", "utils-aio", "spansy", "serio", "uid-mux"]
members = ["utils", "utils-aio", "spansy", "serio", "uid-mux", "utils/fuzz"]

[workspace.dependencies]
tlsn-utils = { path = "utils" }
Expand Down
2 changes: 1 addition & 1 deletion spansy/src/http/types.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use utils::range::{RangeDifference, RangeSet, ToRangeSet};
use utils::range::{Difference, RangeSet, ToRangeSet};

use crate::{json::JsonValue, Span, Spanned};

Expand Down
2 changes: 1 addition & 1 deletion spansy/src/json/types.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::ops::{Index, Range};

use utils::range::{RangeDifference, RangeSet, ToRangeSet};
use utils::range::{Difference, RangeSet, ToRangeSet};

use crate::{Span, Spanned};

Expand Down
28 changes: 24 additions & 4 deletions utils/fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ libfuzzer-sys = { version = "0.4", features = ["arbitrary-derive"] }
[dependencies.tlsn-utils]
path = ".."

# Prevent this from interfering with workspaces
[workspace]
members = ["."]

[profile.release]
debug = 1

Expand Down Expand Up @@ -44,6 +40,18 @@ path = "fuzz_targets/range_diff_set.rs"
test = false
doc = false

[[bin]]
name = "range_intersection_set"
path = "fuzz_targets/range_intersection_set.rs"
test = false
doc = false

[[bin]]
name = "range_subset_set"
path = "fuzz_targets/range_subset_set.rs"
test = false
doc = false

[[bin]]
name = "set_union_range"
path = "fuzz_targets/set_union_range.rs"
Expand All @@ -62,6 +70,18 @@ path = "fuzz_targets/set_diff_set.rs"
test = false
doc = false

[[bin]]
name = "set_intersection_set"
path = "fuzz_targets/set_intersection_set.rs"
test = false
doc = false

[[bin]]
name = "set_subset_set"
path = "fuzz_targets/set_subset_set.rs"
test = false
doc = false

[[bin]]
name = "set_diff_range"
path = "fuzz_targets/set_diff_range.rs"
Expand Down
25 changes: 25 additions & 0 deletions utils/fuzz/fuzz_targets/range_intersection_set.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#![no_main]

use std::collections::HashSet;
use std::ops::Range;

use libfuzzer_sys::fuzz_target;

use tlsn_utils_fuzz::{assert_invariants, SmallSet};

use utils::range::*;

fuzz_target!(|r: (Range<u8>, SmallSet)| {
let s1 = r.0;
let s2: RangeSet<u8> = r.1.into();

let h1: HashSet<u8> = HashSet::from_iter(s1.clone());
let h2: HashSet<u8> = HashSet::from_iter(s2.iter());

let intersection = s1.intersection(&s2);
let h3: HashSet<u8> = HashSet::from_iter(intersection.iter());

assert_eq!(h3, h1.intersection(&h2).copied().collect::<HashSet<_>>());

assert_invariants(intersection);
});
20 changes: 20 additions & 0 deletions utils/fuzz/fuzz_targets/range_subset_set.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#![no_main]

use std::collections::HashSet;
use std::ops::Range;

use libfuzzer_sys::fuzz_target;

use tlsn_utils_fuzz::SmallSet;

use utils::range::*;

fuzz_target!(|r: (Range<u8>, SmallSet)| {
let s1 = r.0;
let s2: RangeSet<u8> = r.1.into();

let h1: HashSet<u8> = HashSet::from_iter(s1.clone());
let h2: HashSet<u8> = HashSet::from_iter(s2.iter());

assert_eq!(s1.is_subset(&s2), h1.is_subset(&h2));
});
24 changes: 24 additions & 0 deletions utils/fuzz/fuzz_targets/set_intersection_set.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#![no_main]

use std::collections::HashSet;

use libfuzzer_sys::fuzz_target;

use tlsn_utils_fuzz::{assert_invariants, SmallSet};

use utils::range::*;

fuzz_target!(|r: (SmallSet, SmallSet)| {
let s1: RangeSet<u8> = r.0.into();
let s2: RangeSet<u8> = r.1.into();

let h1: HashSet<u8> = HashSet::from_iter(s1.iter());
let h2: HashSet<u8> = HashSet::from_iter(s2.iter());

let intersection = s1.intersection(&s2);
let h3: HashSet<u8> = HashSet::from_iter(intersection.iter());

assert_eq!(h3, h1.intersection(&h2).copied().collect::<HashSet<_>>());

assert_invariants(intersection);
});
19 changes: 19 additions & 0 deletions utils/fuzz/fuzz_targets/set_subset_set.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#![no_main]

use std::collections::HashSet;

use libfuzzer_sys::fuzz_target;

use tlsn_utils_fuzz::SmallSet;

use utils::range::*;

fuzz_target!(|r: (SmallSet, SmallSet)| {
let s1: RangeSet<u8> = r.0.into();
let s2: RangeSet<u8> = r.1.into();

let h1: HashSet<u8> = HashSet::from_iter(s1.iter());
let h2: HashSet<u8> = HashSet::from_iter(s2.iter());

assert_eq!(s1.is_subset(&s2), h1.is_subset(&h2));
});
20 changes: 9 additions & 11 deletions utils/src/range/difference.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use std::ops::Range;

use crate::range::{
RangeDifference, RangeDisjoint, RangeSet, RangeSubset, RangeSuperset, RangeUnion,
};
use crate::range::{Difference, Disjoint, RangeSet, Subset, Union};

impl<T: Copy + Ord> RangeDifference<Range<T>> for Range<T> {
impl<T: Copy + Ord> Difference<Range<T>> for Range<T> {
type Output = RangeSet<T>;

fn difference(&self, other: &Range<T>) -> Self::Output {
Expand All @@ -14,8 +12,8 @@ impl<T: Copy + Ord> RangeDifference<Range<T>> for Range<T> {
return RangeSet::from(self.clone());
}

// If other is a superset of self, return an empty set.
if other.is_superset(self) {
// If other contains self, return an empty set.
if self.is_subset(other) {
return RangeSet::default();
}

Expand All @@ -38,9 +36,9 @@ impl<T: Copy + Ord> RangeDifference<Range<T>> for Range<T> {
}
}

impl<T: Copy + Ord> RangeDifference<RangeSet<T>> for Range<T>
impl<T: Copy + Ord> Difference<RangeSet<T>> for Range<T>
where
RangeSet<T>: RangeDifference<Range<T>, Output = RangeSet<T>>,
RangeSet<T>: Difference<Range<T>, Output = RangeSet<T>>,
{
type Output = RangeSet<T>;

Expand All @@ -59,7 +57,7 @@ where
}
}

impl<T: Copy + Ord> RangeDifference<Range<T>> for RangeSet<T> {
impl<T: Copy + Ord> Difference<Range<T>> for RangeSet<T> {
type Output = RangeSet<T>;

fn difference(&self, other: &Range<T>) -> Self::Output {
Expand All @@ -80,7 +78,7 @@ impl<T: Copy + Ord> RangeDifference<Range<T>> for RangeSet<T> {
break;
}
// If the current range is entirely contained within other
else if other.is_superset(&ranges[i]) {
else if ranges[i].is_subset(other) {
ranges.remove(i);
continue;
}
Expand Down Expand Up @@ -113,7 +111,7 @@ impl<T: Copy + Ord> RangeDifference<Range<T>> for RangeSet<T> {
}
}

impl<T: Copy + Ord> RangeDifference<RangeSet<T>> for RangeSet<T> {
impl<T: Copy + Ord> Difference<RangeSet<T>> for RangeSet<T> {
type Output = RangeSet<T>;

fn difference(&self, other: &RangeSet<T>) -> Self::Output {
Expand Down
Loading

0 comments on commit e7b2db6

Please sign in to comment.