Skip to content

Commit 21f4b08

Browse files
Use boxed slices for hash vector (#11714)
## Summary We never resize these, and they're stored everywhere (on `File`, etc.). Seems useful to use a more efficient structure for them.
1 parent d4a0096 commit 21f4b08

File tree

23 files changed

+264
-139
lines changed

23 files changed

+264
-139
lines changed

crates/uv-client/src/flat_index.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use uv_cache::{Cache, CacheBucket};
99
use uv_cache_key::cache_digest;
1010
use uv_distribution_filename::DistFilename;
1111
use uv_distribution_types::{File, FileLocation, IndexUrl, UrlString};
12+
use uv_pypi_types::HashDigests;
1213

1314
use crate::cached_client::{CacheControl, CachedClientError};
1415
use crate::html::SimpleHtml;
@@ -283,7 +284,7 @@ impl<'a> FlatIndexClient<'a> {
283284
let file = File {
284285
dist_info_metadata: false,
285286
filename: filename.to_string(),
286-
hashes: Vec::new(),
287+
hashes: HashDigests::empty(),
287288
requires_python: None,
288289
size: None,
289290
upload_time_utc_ms: None,

crates/uv-distribution-types/src/cached.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::path::{Path, PathBuf};
33
use uv_cache_info::CacheInfo;
44
use uv_distribution_filename::WheelFilename;
55
use uv_normalize::PackageName;
6-
use uv_pypi_types::{HashDigest, VerbatimParsedUrl};
6+
use uv_pypi_types::{HashDigest, HashDigests, VerbatimParsedUrl};
77

88
use crate::{
99
BuiltDist, Dist, DistributionMetadata, Hashed, InstalledMetadata, InstalledVersion, Name,
@@ -23,7 +23,7 @@ pub enum CachedDist {
2323
pub struct CachedRegistryDist {
2424
pub filename: WheelFilename,
2525
pub path: PathBuf,
26-
pub hashes: Vec<HashDigest>,
26+
pub hashes: HashDigests,
2727
pub cache_info: CacheInfo,
2828
}
2929

@@ -32,7 +32,7 @@ pub struct CachedDirectUrlDist {
3232
pub filename: WheelFilename,
3333
pub url: VerbatimParsedUrl,
3434
pub path: PathBuf,
35-
pub hashes: Vec<HashDigest>,
35+
pub hashes: HashDigests,
3636
pub cache_info: CacheInfo,
3737
}
3838

@@ -41,7 +41,7 @@ impl CachedDist {
4141
pub fn from_remote(
4242
remote: Dist,
4343
filename: WheelFilename,
44-
hashes: Vec<HashDigest>,
44+
hashes: HashDigests,
4545
cache_info: CacheInfo,
4646
path: PathBuf,
4747
) -> Self {
@@ -156,7 +156,7 @@ impl CachedDist {
156156

157157
impl Hashed for CachedRegistryDist {
158158
fn hashes(&self) -> &[HashDigest] {
159-
&self.hashes
159+
self.hashes.as_slice()
160160
}
161161
}
162162

crates/uv-distribution-types/src/file.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use url::Url;
77

88
use uv_pep440::{VersionSpecifiers, VersionSpecifiersParseError};
99
use uv_pep508::split_scheme;
10-
use uv_pypi_types::{CoreMetadata, HashDigest, Yanked};
10+
use uv_pypi_types::{CoreMetadata, HashDigests, Yanked};
1111

1212
/// Error converting [`uv_pypi_types::File`] to [`distribution_type::File`].
1313
#[derive(Debug, thiserror::Error)]
@@ -24,7 +24,7 @@ pub enum FileConversionError {
2424
pub struct File {
2525
pub dist_info_metadata: bool,
2626
pub filename: String,
27-
pub hashes: Vec<HashDigest>,
27+
pub hashes: HashDigests,
2828
pub requires_python: Option<VersionSpecifiers>,
2929
pub size: Option<u64>,
3030
// N.B. We don't use a Jiff timestamp here because it's a little
@@ -47,7 +47,7 @@ impl File {
4747
.or(file.data_dist_info_metadata.as_ref())
4848
.is_some_and(CoreMetadata::is_available),
4949
filename: file.filename,
50-
hashes: file.hashes.into_digests(),
50+
hashes: HashDigests::from(file.hashes),
5151
requires_python: file
5252
.requires_python
5353
.transpose()

crates/uv-distribution-types/src/lib.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,19 +1127,19 @@ impl Identifier for Url {
11271127

11281128
impl Identifier for File {
11291129
fn distribution_id(&self) -> DistributionId {
1130-
if let Some(hash) = self.hashes.first() {
1131-
DistributionId::Digest(hash.clone())
1132-
} else {
1133-
self.url.distribution_id()
1134-
}
1130+
self.hashes
1131+
.first()
1132+
.cloned()
1133+
.map(DistributionId::Digest)
1134+
.unwrap_or_else(|| self.url.distribution_id())
11351135
}
11361136

11371137
fn resource_id(&self) -> ResourceId {
1138-
if let Some(hash) = self.hashes.first() {
1139-
ResourceId::Digest(hash.clone())
1140-
} else {
1141-
self.url.resource_id()
1142-
}
1138+
self.hashes
1139+
.first()
1140+
.cloned()
1141+
.map(ResourceId::Digest)
1142+
.unwrap_or_else(|| self.url.resource_id())
11431143
}
11441144
}
11451145

crates/uv-distribution-types/src/resolution.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use uv_distribution_filename::DistExtension;
22
use uv_normalize::{ExtraName, GroupName, PackageName};
33
use uv_pep508::MarkerTree;
4-
use uv_pypi_types::{HashDigest, RequirementSource};
4+
use uv_pypi_types::{HashDigest, HashDigests, RequirementSource};
55

66
use crate::{BuiltDist, Diagnostic, Dist, Name, ResolvedDist, SourceDist};
77

@@ -183,7 +183,7 @@ pub enum Node {
183183
Root,
184184
Dist {
185185
dist: ResolvedDist,
186-
hashes: Vec<HashDigest>,
186+
hashes: HashDigests,
187187
install: bool,
188188
},
189189
}

crates/uv-distribution/src/archive.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
use uv_cache::{ArchiveId, Cache, ARCHIVE_VERSION};
22
use uv_distribution_types::Hashed;
3-
use uv_pypi_types::HashDigest;
3+
use uv_pypi_types::{HashDigest, HashDigests};
44

55
/// An archive (unzipped wheel) that exists in the local cache.
66
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
77
pub struct Archive {
88
/// The unique ID of the entry in the wheel's archive bucket.
99
pub id: ArchiveId,
1010
/// The computed hashes of the archive.
11-
pub hashes: Vec<HashDigest>,
11+
pub hashes: HashDigests,
1212
/// The version of the archive bucket.
1313
pub version: u8,
1414
}
1515

1616
impl Archive {
1717
/// Create a new [`Archive`] with the given ID and hashes.
18-
pub(crate) fn new(id: ArchiveId, hashes: Vec<HashDigest>) -> Self {
18+
pub(crate) fn new(id: ArchiveId, hashes: HashDigests) -> Self {
1919
Self {
2020
id,
2121
hashes,
@@ -31,6 +31,6 @@ impl Archive {
3131

3232
impl Hashed for Archive {
3333
fn hashes(&self) -> &[HashDigest] {
34-
&self.hashes
34+
self.hashes.as_slice()
3535
}
3636
}

crates/uv-distribution/src/distribution_database.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use uv_distribution_types::{
2626
use uv_extract::hash::Hasher;
2727
use uv_fs::write_atomic;
2828
use uv_platform_tags::Tags;
29-
use uv_pypi_types::HashDigest;
29+
use uv_pypi_types::{HashDigest, HashDigests};
3030
use uv_types::{BuildContext, BuildStack};
3131

3232
use crate::archive::Archive;
@@ -719,7 +719,7 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
719719
})
720720
.await??;
721721

722-
vec![]
722+
HashDigests::empty()
723723
} else {
724724
// Create a hasher for each hash algorithm.
725725
let algorithms = hashes.algorithms();
@@ -843,7 +843,10 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> {
843843
})
844844
} else if hashes.is_none() {
845845
// Otherwise, unzip the wheel.
846-
let archive = Archive::new(self.unzip_wheel(path, wheel_entry.path()).await?, vec![]);
846+
let archive = Archive::new(
847+
self.unzip_wheel(path, wheel_entry.path()).await?,
848+
HashDigests::empty(),
849+
);
847850

848851
// Write the archive pointer to the cache.
849852
let pointer = LocalArchivePointer {

crates/uv-distribution/src/download.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::Error;
44
use uv_distribution_filename::WheelFilename;
55
use uv_distribution_types::{CachedDist, Dist, Hashed};
66
use uv_metadata::read_flat_wheel_metadata;
7-
use uv_pypi_types::{HashDigest, ResolutionMetadata};
7+
use uv_pypi_types::{HashDigest, HashDigests, ResolutionMetadata};
88

99
use uv_cache_info::CacheInfo;
1010

@@ -21,7 +21,7 @@ pub struct LocalWheel {
2121
/// The cache index of the wheel.
2222
pub(crate) cache: CacheInfo,
2323
/// The computed hashes of the wheel.
24-
pub(crate) hashes: Vec<HashDigest>,
24+
pub(crate) hashes: HashDigests,
2525
}
2626

2727
impl LocalWheel {
@@ -49,7 +49,7 @@ impl LocalWheel {
4949

5050
impl Hashed for LocalWheel {
5151
fn hashes(&self) -> &[HashDigest] {
52-
&self.hashes
52+
self.hashes.as_slice()
5353
}
5454
}
5555

crates/uv-distribution/src/index/cached_wheel.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use uv_distribution_types::{
77
CachedDirectUrlDist, CachedRegistryDist, DirectUrlSourceDist, DirectorySourceDist,
88
GitSourceDist, Hashed, PathSourceDist,
99
};
10-
use uv_pypi_types::{HashDigest, VerbatimParsedUrl};
10+
use uv_pypi_types::{HashDigest, HashDigests, VerbatimParsedUrl};
1111

1212
use crate::archive::Archive;
1313
use crate::{HttpArchivePointer, LocalArchivePointer};
@@ -19,7 +19,7 @@ pub struct CachedWheel {
1919
/// The [`CacheEntry`] for the wheel.
2020
pub entry: CacheEntry,
2121
/// The [`HashDigest`]s for the wheel.
22-
pub hashes: Vec<HashDigest>,
22+
pub hashes: HashDigests,
2323
/// The [`CacheInfo`] for the wheel.
2424
pub cache_info: CacheInfo,
2525
}
@@ -36,7 +36,7 @@ impl CachedWheel {
3636
// Convert to a cached wheel.
3737
let archive = cache.resolve_link(path).ok()?;
3838
let entry = CacheEntry::from_path(archive);
39-
let hashes = Vec::new();
39+
let hashes = HashDigests::empty();
4040
let cache_info = CacheInfo::default();
4141
Some(Self {
4242
filename,
@@ -186,6 +186,6 @@ impl CachedWheel {
186186

187187
impl Hashed for CachedWheel {
188188
fn hashes(&self) -> &[HashDigest] {
189-
&self.hashes
189+
self.hashes.as_slice()
190190
}
191191
}

crates/uv-distribution/src/metadata/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use uv_configuration::SourceStrategy;
77
use uv_distribution_types::{GitSourceUrl, IndexLocations};
88
use uv_normalize::{ExtraName, GroupName, PackageName};
99
use uv_pep440::{Version, VersionSpecifiers};
10-
use uv_pypi_types::{HashDigest, ResolutionMetadata};
10+
use uv_pypi_types::{HashDigests, ResolutionMetadata};
1111
use uv_workspace::dependency_groups::DependencyGroupError;
1212
use uv_workspace::WorkspaceError;
1313

@@ -122,7 +122,7 @@ pub struct ArchiveMetadata {
122122
/// The [`Metadata`] for the underlying distribution.
123123
pub metadata: Metadata,
124124
/// The hashes of the source or built archive.
125-
pub hashes: Vec<HashDigest>,
125+
pub hashes: HashDigests,
126126
}
127127

128128
impl ArchiveMetadata {
@@ -131,12 +131,12 @@ impl ArchiveMetadata {
131131
pub fn from_metadata23(metadata: ResolutionMetadata) -> Self {
132132
Self {
133133
metadata: Metadata::from_metadata23(metadata),
134-
hashes: vec![],
134+
hashes: HashDigests::empty(),
135135
}
136136
}
137137

138138
/// Create an [`ArchiveMetadata`] with the given metadata and hashes.
139-
pub fn with_hashes(metadata: Metadata, hashes: Vec<HashDigest>) -> Self {
139+
pub fn with_hashes(metadata: Metadata, hashes: HashDigests) -> Self {
140140
Self { metadata, hashes }
141141
}
142142
}
@@ -145,7 +145,7 @@ impl From<Metadata> for ArchiveMetadata {
145145
fn from(metadata: Metadata) -> Self {
146146
Self {
147147
metadata,
148-
hashes: vec![],
148+
hashes: HashDigests::empty(),
149149
}
150150
}
151151
}

0 commit comments

Comments
 (0)