Skip to content

Commit a23e746

Browse files
authored
feat: contains_many and simplify works with iter of V not just &V (pubgrub-rs#179)
* feat: contains_many works with iter of V not just &V * feat: simplify works with iter of V not just &V
1 parent b5eab1d commit a23e746

File tree

1 file changed

+65
-20
lines changed

1 file changed

+65
-20
lines changed

src/range.rs

Lines changed: 65 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
//! If we do not see practical bugs, or we get a formal proof that the code cannot lead to error states, then we may remove this warning.
5252
5353
use crate::{internal::small_vec::SmallVec, version_set::VersionSet};
54+
use std::borrow::Borrow;
5455
use std::cmp::Ordering;
5556
use std::ops::RangeBounds;
5657
use std::{
@@ -217,29 +218,34 @@ impl<V: Ord> Range<V> {
217218
/// The `versions` iterator must be sorted.
218219
/// Functionally equivalent to `versions.map(|v| self.contains(v))`.
219220
/// Except it runs in `O(size_of_range + len_of_versions)` not `O(size_of_range * len_of_versions)`
220-
pub fn contains_many<'s, I>(&'s self, versions: I) -> impl Iterator<Item = bool> + 's
221+
pub fn contains_many<'s, I, BV>(&'s self, versions: I) -> impl Iterator<Item = bool> + 's
221222
where
222-
I: Iterator<Item = &'s V> + 's,
223-
V: 's,
223+
I: Iterator<Item = BV> + 's,
224+
BV: Borrow<V> + 's,
224225
{
225226
#[cfg(debug_assertions)]
226-
let mut last: Option<&V> = None;
227+
let mut last: Option<BV> = None;
227228
versions.scan(0, move |i, v| {
228229
#[cfg(debug_assertions)]
229230
{
230-
assert!(
231-
last <= Some(v),
232-
"`contains_many` `versions` argument incorrectly sorted"
233-
);
234-
last = Some(v);
231+
if let Some(l) = last.as_ref() {
232+
assert!(
233+
l.borrow() <= v.borrow(),
234+
"`contains_many` `versions` argument incorrectly sorted"
235+
);
236+
}
235237
}
236238
while let Some(segment) = self.segments.get(*i) {
237-
match within_bounds(v, segment) {
239+
match within_bounds(v.borrow(), segment) {
238240
Ordering::Less => return Some(false),
239241
Ordering::Equal => return Some(true),
240242
Ordering::Greater => *i += 1,
241243
}
242244
}
245+
#[cfg(debug_assertions)]
246+
{
247+
last = Some(v);
248+
}
243249
Some(false)
244250
})
245251
}
@@ -435,30 +441,35 @@ impl<V: Ord + Clone> Range<V> {
435441
/// - If none of the versions are contained in the original than the range will be simplified to `empty`.
436442
///
437443
/// If versions are not sorted the correctness of this function is not guaranteed.
438-
pub fn simplify<'v, I>(&self, versions: I) -> Self
444+
pub fn simplify<'s, I, BV>(&self, versions: I) -> Self
439445
where
440-
I: Iterator<Item = &'v V> + 'v,
441-
V: 'v,
446+
I: Iterator<Item = BV> + 's,
447+
BV: Borrow<V> + 's,
442448
{
443449
#[cfg(debug_assertions)]
444-
let mut last: Option<&V> = None;
450+
let mut last: Option<BV> = None;
445451
// Return the segment index in the range for each version in the range, None otherwise
446452
let version_locations = versions.scan(0, move |i, v| {
447453
#[cfg(debug_assertions)]
448454
{
449-
assert!(
450-
last <= Some(v),
451-
"`simplify` `versions` argument incorrectly sorted"
452-
);
453-
last = Some(v);
455+
if let Some(l) = last.as_ref() {
456+
assert!(
457+
l.borrow() <= v.borrow(),
458+
"`simplify` `versions` argument incorrectly sorted"
459+
);
460+
}
454461
}
455462
while let Some(segment) = self.segments.get(*i) {
456-
match within_bounds(v, segment) {
463+
match within_bounds(v.borrow(), segment) {
457464
Ordering::Less => return Some(None),
458465
Ordering::Equal => return Some(Some(*i)),
459466
Ordering::Greater => *i += 1,
460467
}
461468
}
469+
#[cfg(debug_assertions)]
470+
{
471+
last = Some(v);
472+
}
462473
Some(None)
463474
});
464475
let kept_segments = group_adjacent_locations(version_locations);
@@ -789,4 +800,38 @@ pub mod tests {
789800
assert!(simp.segments.len() <= range.segments.len())
790801
}
791802
}
803+
804+
#[test]
805+
fn contains_many_can_take_owned() {
806+
let range: Range<u8> = Range::singleton(1);
807+
let versions = vec![1, 2, 3];
808+
// Check that iter can be a Cow
809+
assert_eq!(
810+
range.contains_many(versions.iter()).count(),
811+
range
812+
.contains_many(versions.iter().map(std::borrow::Cow::Borrowed))
813+
.count()
814+
);
815+
// Check that iter can be a V
816+
assert_eq!(
817+
range.contains_many(versions.iter()).count(),
818+
range.contains_many(versions.into_iter()).count()
819+
);
820+
}
821+
822+
#[test]
823+
fn simplify_can_take_owned() {
824+
let range: Range<u8> = Range::singleton(1);
825+
let versions = vec![1, 2, 3];
826+
// Check that iter can be a Cow
827+
assert_eq!(
828+
range.simplify(versions.iter()),
829+
range.simplify(versions.iter().map(std::borrow::Cow::Borrowed))
830+
);
831+
// Check that iter can be a V
832+
assert_eq!(
833+
range.simplify(versions.iter()),
834+
range.simplify(versions.into_iter())
835+
);
836+
}
792837
}

0 commit comments

Comments
 (0)