diff --git a/fuzz/fuzz_targets/int_set_op_processor.rs b/fuzz/fuzz_targets/int_set_op_processor.rs index e4d89255d..2ff70684c 100644 --- a/fuzz/fuzz_targets/int_set_op_processor.rs +++ b/fuzz/fuzz_targets/int_set_op_processor.rs @@ -721,6 +721,61 @@ where } } +/* ### Iter Excluded Ranges ### */ + +struct IterExcludedRangesOp; + +impl IterExcludedRangesOp { + fn parse_args() -> Option>> + where + T: SetMember, + { + Some(Box::new(Self)) + } +} + +impl Operation for IterExcludedRangesOp +where + T: SetMember, +{ + fn operate(&self, input: Input, _: Input) { + let mut btree_ranges: Vec> = vec![]; + let mut cur_range: Option> = 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); @@ -914,14 +969,10 @@ where fn operate(&self, input: Input, _: Input) { input.int_set.invert(); - let mut inverted = BTreeSet::::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); } @@ -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, }; diff --git a/read-fonts/src/collections/int_set/mod.rs b/read-fonts/src/collections/int_set/mod.rs index 3f6a64f13..a67888a06 100644 --- a/read-fonts/src/collections/int_set/mod.rs +++ b/read-fonts/src/collections/int_set/mod.rs @@ -164,26 +164,50 @@ impl IntSet { /// Returns an iterator over all disjoint ranges of values within the set in sorted ascending order. pub fn iter_ranges(&self) -> impl Iterator> + '_ { - 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::, - }, - 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> + '_ { + self.iter_ranges_invertible(true) + } + + fn iter_ranges_invertible( + &self, + inverted: bool, + ) -> impl Iterator> + '_ { + 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::, + } + } + (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()))) @@ -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 { @@ -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 { @@ -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::>(), + inverted.iter_excluded_ranges().collect::>() + ); } #[test] @@ -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::>(), + inverted.iter_excluded_ranges().collect::>() + ); } #[test] @@ -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::>(), + inverted.iter_excluded_ranges().collect::>() + ); + let mut set = IntSet::::all(); set.remove_range(u32::MAX - 10..=u32::MAX); let items: Vec<_> = set.iter_ranges().collect(); @@ -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::>(), + inverted.iter_excluded_ranges().collect::>() + ); + let mut set = IntSet::::all(); set.remove_range(TwoParts(2)..=TwoParts(16)); let items: Vec<_> = set.iter_ranges().collect();