|
1 |
| -use pubgrub::Range; |
2 | 1 | use std::collections::btree_map::{BTreeMap, Entry};
|
| 2 | +use std::collections::Bound; |
| 3 | +use std::ops::RangeBounds; |
3 | 4 | use std::sync::OnceLock;
|
| 5 | + |
| 6 | +use pubgrub::Ranges; |
4 | 7 | use tracing::instrument;
|
5 | 8 |
|
6 | 9 | use uv_client::{OwnedArchive, SimpleMetadata, VersionFiles};
|
@@ -156,8 +159,8 @@ impl VersionMap {
|
156 | 159 | /// for each version.
|
157 | 160 | pub(crate) fn iter(
|
158 | 161 | &self,
|
159 |
| - range: &Range<Version>, |
160 |
| - ) -> impl DoubleEndedIterator<Item = (&Version, VersionMapDistHandle)> + ExactSizeIterator { |
| 162 | + range: &Ranges<Version>, |
| 163 | + ) -> impl DoubleEndedIterator<Item = (&Version, VersionMapDistHandle)> { |
161 | 164 | // Performance optimization: If we only have a single version, return that version directly.
|
162 | 165 | if let Some(version) = range.as_singleton() {
|
163 | 166 | either::Either::Left(match self.inner {
|
@@ -185,20 +188,24 @@ impl VersionMap {
|
185 | 188 | } else {
|
186 | 189 | either::Either::Right(match self.inner {
|
187 | 190 | VersionMapInner::Eager(ref eager) => {
|
188 |
| - either::Either::Left(eager.map.iter().map(|(version, dist)| { |
189 |
| - let version_map_dist = VersionMapDistHandle { |
190 |
| - inner: VersionMapDistHandleInner::Eager(dist), |
191 |
| - }; |
192 |
| - (version, version_map_dist) |
193 |
| - })) |
| 191 | + either::Either::Left(eager.map.range(BoundingRange::from(range)).map( |
| 192 | + |(version, dist)| { |
| 193 | + let version_map_dist = VersionMapDistHandle { |
| 194 | + inner: VersionMapDistHandleInner::Eager(dist), |
| 195 | + }; |
| 196 | + (version, version_map_dist) |
| 197 | + }, |
| 198 | + )) |
194 | 199 | }
|
195 | 200 | VersionMapInner::Lazy(ref lazy) => {
|
196 |
| - either::Either::Right(lazy.map.iter().map(|(version, dist)| { |
197 |
| - let version_map_dist = VersionMapDistHandle { |
198 |
| - inner: VersionMapDistHandleInner::Lazy { lazy, dist }, |
199 |
| - }; |
200 |
| - (version, version_map_dist) |
201 |
| - })) |
| 201 | + either::Either::Right(lazy.map.range(BoundingRange::from(range)).map( |
| 202 | + |(version, dist)| { |
| 203 | + let version_map_dist = VersionMapDistHandle { |
| 204 | + inner: VersionMapDistHandleInner::Lazy { lazy, dist }, |
| 205 | + }; |
| 206 | + (version, version_map_dist) |
| 207 | + }, |
| 208 | + )) |
202 | 209 | }
|
203 | 210 | })
|
204 | 211 | }
|
@@ -609,3 +616,29 @@ struct SimplePrioritizedDist {
|
609 | 616 | /// of writing, is to use `--exclude-newer 1900-01-01`.)
|
610 | 617 | dist: OnceLock<Option<PrioritizedDist>>,
|
611 | 618 | }
|
| 619 | + |
| 620 | +/// A range that can be used to iterate over a subset of a [`BTreeMap`]. |
| 621 | +#[derive(Debug)] |
| 622 | +struct BoundingRange<'a> { |
| 623 | + min: Bound<&'a Version>, |
| 624 | + max: Bound<&'a Version>, |
| 625 | +} |
| 626 | + |
| 627 | +impl<'a> From<&'a Ranges<Version>> for BoundingRange<'a> { |
| 628 | + fn from(value: &'a Ranges<Version>) -> Self { |
| 629 | + let (min, max) = value |
| 630 | + .bounding_range() |
| 631 | + .unwrap_or((Bound::Unbounded, Bound::Unbounded)); |
| 632 | + Self { min, max } |
| 633 | + } |
| 634 | +} |
| 635 | + |
| 636 | +impl<'a> RangeBounds<Version> for BoundingRange<'a> { |
| 637 | + fn start_bound(&self) -> Bound<&'a Version> { |
| 638 | + self.min |
| 639 | + } |
| 640 | + |
| 641 | + fn end_bound(&self) -> Bound<&'a Version> { |
| 642 | + self.max |
| 643 | + } |
| 644 | +} |
0 commit comments