Skip to content

Commit

Permalink
[int-set] Add iter_excluded_ranges()
Browse files Browse the repository at this point in the history
This iterates over all ranges of values not contained in the set.
  • Loading branch information
garretrieger committed Oct 9, 2024
1 parent a9377e3 commit 1dbd698
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 37 deletions.
77 changes: 62 additions & 15 deletions fuzz/fuzz_targets/int_set_op_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,61 @@ where
}
}

/* ### Iter Excluded Ranges ### */

struct IterExcludedRangesOp;

impl IterExcludedRangesOp {
fn parse_args<T>() -> Option<Box<dyn Operation<T>>>
where
T: SetMember,
{
Some(Box::new(Self))
}
}

impl<T> Operation<T> for IterExcludedRangesOp
where
T: SetMember,
{
fn operate(&self, input: Input<T>, _: Input<T>) {
let mut btree_ranges: Vec<RangeInclusive<T>> = vec![];
let mut cur_range: Option<RangeInclusive<T>> = None;

let inverted: BTreeSet<_> = T::ordered_values()
.map(|v| T::create(v).unwrap())
.filter(|v| !input.btree_set.contains(v))
.collect();

for v in inverted.iter().copied() {
if let Some(range) = cur_range {
let mut end = *range.end();
end.increment();
if end == v {
cur_range = Some(*range.start()..=v);
continue;
}
btree_ranges.push(range);
}

cur_range = Some(v..=v);
}

if let Some(range) = cur_range {
btree_ranges.push(range);
}

assert!(input
.int_set
.iter_excluded_ranges()
.eq(btree_ranges.iter().cloned()));
}

fn size(&self, length: u64) -> u64 {
length
}
}

/* ### Iter After ### */

struct IterAfterOp<T>(T);
Expand Down Expand Up @@ -914,14 +969,10 @@ where
fn operate(&self, input: Input<T>, _: Input<T>) {
input.int_set.invert();

let mut inverted = BTreeSet::<T>::new();

for v in T::ordered_values() {
let v = T::create(v).unwrap();
if !input.btree_set.contains(&v) {
inverted.insert(v);
}
}
let mut inverted: BTreeSet<_> = T::ordered_values()
.map(|v| T::create(v).unwrap())
.filter(|v| !input.btree_set.contains(v))
.collect();
std::mem::swap(input.btree_set, &mut inverted);
}

Expand Down Expand Up @@ -1114,17 +1165,13 @@ where
19 if is_standard => UnionOp::parse_args(),
20 if is_standard => IntersectOp::parse_args(),
21 if is_standard => IsInvertedOp::parse_args(),
22 if is_standard => {
if T::can_be_inverted() {
InvertOp::parse_args()
} else {
None
}
}
22 if is_standard && T::can_be_inverted() => InvertOp::parse_args(),
23 if is_standard => HashOp::parse_args(),
24 if is_standard => EqualOp::parse_args(),
25 if is_standard => CmpOp::parse_args(),
26 if is_standard => IntersectsSetOp::parse_args(),
27 if is_standard && T::can_be_inverted() => IterExcludedRangesOp::parse_args(),

_ => None,
};

Expand Down
96 changes: 74 additions & 22 deletions read-fonts/src/collections/int_set/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,26 +164,50 @@ impl<T: Domain> IntSet<T> {

/// Returns an iterator over all disjoint ranges of values within the set in sorted ascending order.
pub fn iter_ranges(&self) -> impl Iterator<Item = RangeInclusive<T>> + '_ {
let u32_iter = match &self.0 {
Membership::Inclusive(s) if T::is_continuous() => RangeIter::Inclusive::<_, _, T> {
ranges: s.iter_ranges(),
},
Membership::Inclusive(s) => RangeIter::InclusiveDiscontinuous::<_, _, T> {
ranges: s.iter_ranges(),
current_range: None,
phantom: PhantomData::<T>,
},
Membership::Exclusive(s) if T::is_continuous() => RangeIter::Exclusive::<_, _, T> {
ranges: s.iter_ranges(),
min: T::ordered_values().next().unwrap(),
max: T::ordered_values().next_back().unwrap(),
done: false,
},
Membership::Exclusive(s) => RangeIter::ExclusiveDiscontinuous::<_, _, T> {
all_values: Some(T::ordered_values()),
set: s,
next_value: None,
},
self.iter_ranges_invertible(false)
}

/// Returns an iterator over all disjoint ranges of values not within the set in sorted ascending order.
pub fn iter_excluded_ranges(&self) -> impl Iterator<Item = RangeInclusive<T>> + '_ {
self.iter_ranges_invertible(true)
}

fn iter_ranges_invertible(
&self,
inverted: bool,
) -> impl Iterator<Item = RangeInclusive<T>> + '_ {
let u32_iter = match (&self.0, inverted) {
(Membership::Inclusive(s), false) | (Membership::Exclusive(s), true)
if T::is_continuous() =>
{
RangeIter::Inclusive::<_, _, T> {
ranges: s.iter_ranges(),
}
}
(Membership::Inclusive(s), false) | (Membership::Exclusive(s), true) => {
RangeIter::InclusiveDiscontinuous::<_, _, T> {
ranges: s.iter_ranges(),
current_range: None,
phantom: PhantomData::<T>,
}
}
(Membership::Exclusive(s), false) | (Membership::Inclusive(s), true)
if T::is_continuous() =>
{
RangeIter::Exclusive::<_, _, T> {
ranges: s.iter_ranges(),
min: T::ordered_values().next().unwrap(),
max: T::ordered_values().next_back().unwrap(),
done: false,
}
}
(Membership::Exclusive(s), false) | (Membership::Inclusive(s), true) => {
RangeIter::ExclusiveDiscontinuous::<_, _, T> {
all_values: Some(T::ordered_values()),
set: s,
next_value: None,
}
}
};

u32_iter.map(|r| T::from_u32(InDomain(*r.start()))..=T::from_u32(InDomain(*r.end())))
Expand Down Expand Up @@ -1095,7 +1119,7 @@ mod test {

use super::*;

#[derive(PartialEq, Eq, Debug, PartialOrd, Ord)]
#[derive(PartialEq, Eq, Debug, PartialOrd, Ord, Clone)]
struct EvenInts(u16);

impl Domain for EvenInts {
Expand Down Expand Up @@ -1129,7 +1153,7 @@ mod test {
}
}

#[derive(PartialEq, Eq, Debug, PartialOrd, Ord, Hash)]
#[derive(PartialEq, Eq, Debug, PartialOrd, Ord, Hash, Clone)]
struct TwoParts(u16);

impl Domain for TwoParts {
Expand Down Expand Up @@ -1526,6 +1550,13 @@ mod test {
set.insert_range(u32::MAX - 5..=u32::MAX);
let items: Vec<_> = set.iter_ranges().collect();
assert_eq!(items, vec![0..=5, u32::MAX - 5..=u32::MAX]);

let mut inverted = set.clone();
inverted.invert();
assert_eq!(
set.iter_ranges().collect::<Vec<_>>(),
inverted.iter_excluded_ranges().collect::<Vec<_>>()
);
}

#[test]
Expand All @@ -1542,6 +1573,13 @@ mod test {
items,
vec![EvenInts(4)..=EvenInts(12), EvenInts(16)..=EvenInts(16)]
);

let mut inverted = set.clone();
inverted.invert();
assert_eq!(
set.iter_ranges().collect::<Vec<_>>(),
inverted.iter_excluded_ranges().collect::<Vec<_>>()
);
}

#[test]
Expand All @@ -1557,6 +1595,13 @@ mod test {
let items: Vec<_> = set.iter_ranges().collect();
assert_eq!(items, vec![701..=u32::MAX]);

let mut inverted = set.clone();
inverted.invert();
assert_eq!(
set.iter_ranges().collect::<Vec<_>>(),
inverted.iter_excluded_ranges().collect::<Vec<_>>()
);

let mut set = IntSet::<u32>::all();
set.remove_range(u32::MAX - 10..=u32::MAX);
let items: Vec<_> = set.iter_ranges().collect();
Expand Down Expand Up @@ -1598,6 +1643,13 @@ mod test {
vec![TwoParts(2)..=TwoParts(10), TwoParts(14)..=TwoParts(16),]
);

let mut inverted = set.clone();
inverted.invert();
assert_eq!(
set.iter_ranges().collect::<Vec<_>>(),
inverted.iter_excluded_ranges().collect::<Vec<_>>()
);

let mut set = IntSet::<TwoParts>::all();
set.remove_range(TwoParts(2)..=TwoParts(16));
let items: Vec<_> = set.iter_ranges().collect();
Expand Down

0 comments on commit 1dbd698

Please sign in to comment.