|
51 | 51 | //! 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.
|
52 | 52 |
|
53 | 53 | use crate::{internal::small_vec::SmallVec, version_set::VersionSet};
|
| 54 | +use std::borrow::Borrow; |
54 | 55 | use std::cmp::Ordering;
|
55 | 56 | use std::ops::RangeBounds;
|
56 | 57 | use std::{
|
@@ -217,29 +218,34 @@ impl<V: Ord> Range<V> {
|
217 | 218 | /// The `versions` iterator must be sorted.
|
218 | 219 | /// Functionally equivalent to `versions.map(|v| self.contains(v))`.
|
219 | 220 | /// 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 |
221 | 222 | where
|
222 |
| - I: Iterator<Item = &'s V> + 's, |
223 |
| - V: 's, |
| 223 | + I: Iterator<Item = BV> + 's, |
| 224 | + BV: Borrow<V> + 's, |
224 | 225 | {
|
225 | 226 | #[cfg(debug_assertions)]
|
226 |
| - let mut last: Option<&V> = None; |
| 227 | + let mut last: Option<BV> = None; |
227 | 228 | versions.scan(0, move |i, v| {
|
228 | 229 | #[cfg(debug_assertions)]
|
229 | 230 | {
|
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 | + } |
235 | 237 | }
|
236 | 238 | while let Some(segment) = self.segments.get(*i) {
|
237 |
| - match within_bounds(v, segment) { |
| 239 | + match within_bounds(v.borrow(), segment) { |
238 | 240 | Ordering::Less => return Some(false),
|
239 | 241 | Ordering::Equal => return Some(true),
|
240 | 242 | Ordering::Greater => *i += 1,
|
241 | 243 | }
|
242 | 244 | }
|
| 245 | + #[cfg(debug_assertions)] |
| 246 | + { |
| 247 | + last = Some(v); |
| 248 | + } |
243 | 249 | Some(false)
|
244 | 250 | })
|
245 | 251 | }
|
@@ -435,30 +441,35 @@ impl<V: Ord + Clone> Range<V> {
|
435 | 441 | /// - If none of the versions are contained in the original than the range will be simplified to `empty`.
|
436 | 442 | ///
|
437 | 443 | /// 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 |
439 | 445 | where
|
440 |
| - I: Iterator<Item = &'v V> + 'v, |
441 |
| - V: 'v, |
| 446 | + I: Iterator<Item = BV> + 's, |
| 447 | + BV: Borrow<V> + 's, |
442 | 448 | {
|
443 | 449 | #[cfg(debug_assertions)]
|
444 |
| - let mut last: Option<&V> = None; |
| 450 | + let mut last: Option<BV> = None; |
445 | 451 | // Return the segment index in the range for each version in the range, None otherwise
|
446 | 452 | let version_locations = versions.scan(0, move |i, v| {
|
447 | 453 | #[cfg(debug_assertions)]
|
448 | 454 | {
|
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 | + } |
454 | 461 | }
|
455 | 462 | while let Some(segment) = self.segments.get(*i) {
|
456 |
| - match within_bounds(v, segment) { |
| 463 | + match within_bounds(v.borrow(), segment) { |
457 | 464 | Ordering::Less => return Some(None),
|
458 | 465 | Ordering::Equal => return Some(Some(*i)),
|
459 | 466 | Ordering::Greater => *i += 1,
|
460 | 467 | }
|
461 | 468 | }
|
| 469 | + #[cfg(debug_assertions)] |
| 470 | + { |
| 471 | + last = Some(v); |
| 472 | + } |
462 | 473 | Some(None)
|
463 | 474 | });
|
464 | 475 | let kept_segments = group_adjacent_locations(version_locations);
|
@@ -789,4 +800,38 @@ pub mod tests {
|
789 | 800 | assert!(simp.segments.len() <= range.segments.len())
|
790 | 801 | }
|
791 | 802 | }
|
| 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 | + } |
792 | 837 | }
|
0 commit comments