1use std::path::Path;
2
3use uv_cache_info::CacheInfo;
4use uv_distribution_filename::WheelFilename;
5use uv_normalize::PackageName;
6use uv_pypi_types::{HashDigest, HashDigests, VerbatimParsedUrl};
7
8use crate::{
9 BuildInfo, BuiltDist, Dist, DistributionMetadata, Hashed, InstalledMetadata, InstalledVersion,
10 Name, ParsedUrl, SourceDist, VersionId, VersionOrUrlRef,
11};
12
13#[derive(Debug, Clone, Hash, PartialEq, Eq)]
15#[expect(clippy::large_enum_variant)]
16pub enum CachedDist {
17 Registry(CachedRegistryDist),
19 Url(CachedDirectUrlDist),
21}
22
23#[derive(Debug, Clone, Hash, PartialEq, Eq)]
24pub struct CachedRegistryDist {
25 pub filename: WheelFilename,
26 pub path: Box<Path>,
27 pub hashes: HashDigests,
28 pub cache_info: CacheInfo,
29 pub build_info: Option<BuildInfo>,
30}
31
32#[derive(Debug, Clone, Hash, PartialEq, Eq)]
33pub struct CachedDirectUrlDist {
34 pub filename: WheelFilename,
35 pub url: VerbatimParsedUrl,
36 pub path: Box<Path>,
37 pub hashes: HashDigests,
38 pub cache_info: CacheInfo,
39 pub build_info: Option<BuildInfo>,
40}
41
42impl CachedDist {
43 pub fn from_remote(
45 remote: Dist,
46 filename: WheelFilename,
47 hashes: HashDigests,
48 cache_info: CacheInfo,
49 build_info: Option<BuildInfo>,
50 path: Box<Path>,
51 ) -> Self {
52 match remote {
53 Dist::Built(BuiltDist::Registry(_dist)) => Self::Registry(CachedRegistryDist {
54 filename,
55 path,
56 hashes,
57 cache_info,
58 build_info,
59 }),
60 Dist::Built(BuiltDist::DirectUrl(dist)) => Self::Url(CachedDirectUrlDist {
61 filename,
62 url: VerbatimParsedUrl {
63 parsed_url: dist.parsed_url(),
64 verbatim: dist.url,
65 },
66 hashes,
67 cache_info,
68 build_info,
69 path,
70 }),
71 Dist::Built(BuiltDist::Path(dist)) => Self::Url(CachedDirectUrlDist {
72 filename,
73 url: VerbatimParsedUrl {
74 parsed_url: dist.parsed_url(),
75 verbatim: dist.url,
76 },
77 hashes,
78 cache_info,
79 build_info,
80 path,
81 }),
82 Dist::Source(SourceDist::Registry(_dist)) => Self::Registry(CachedRegistryDist {
83 filename,
84 path,
85 hashes,
86 cache_info,
87 build_info,
88 }),
89 Dist::Source(SourceDist::DirectUrl(dist)) => Self::Url(CachedDirectUrlDist {
90 filename,
91 url: VerbatimParsedUrl {
92 parsed_url: dist.parsed_url(),
93 verbatim: dist.url,
94 },
95 hashes,
96 cache_info,
97 build_info,
98 path,
99 }),
100 Dist::Source(SourceDist::Git(dist)) => Self::Url(CachedDirectUrlDist {
101 filename,
102 url: VerbatimParsedUrl {
103 parsed_url: dist.parsed_url(),
104 verbatim: dist.url,
105 },
106 hashes,
107 cache_info,
108 build_info,
109 path,
110 }),
111 Dist::Source(SourceDist::Path(dist)) => Self::Url(CachedDirectUrlDist {
112 filename,
113 url: VerbatimParsedUrl {
114 parsed_url: dist.parsed_url(),
115 verbatim: dist.url,
116 },
117 hashes,
118 cache_info,
119 build_info,
120 path,
121 }),
122 Dist::Source(SourceDist::Directory(dist)) => Self::Url(CachedDirectUrlDist {
123 filename,
124 url: VerbatimParsedUrl {
125 parsed_url: dist.parsed_url(),
126 verbatim: dist.url,
127 },
128 hashes,
129 cache_info,
130 build_info,
131 path,
132 }),
133 }
134 }
135
136 pub fn path(&self) -> &Path {
138 match self {
139 Self::Registry(dist) => &dist.path,
140 Self::Url(dist) => &dist.path,
141 }
142 }
143
144 pub fn cache_info(&self) -> &CacheInfo {
146 match self {
147 Self::Registry(dist) => &dist.cache_info,
148 Self::Url(dist) => &dist.cache_info,
149 }
150 }
151
152 pub fn build_info(&self) -> Option<&BuildInfo> {
154 match self {
155 Self::Registry(dist) => dist.build_info.as_ref(),
156 Self::Url(dist) => dist.build_info.as_ref(),
157 }
158 }
159
160 pub fn parsed_url(&self) -> Option<&ParsedUrl> {
162 match self {
163 Self::Registry(_) => None,
164 Self::Url(dist) => Some(&dist.url.parsed_url),
165 }
166 }
167
168 pub fn filename(&self) -> &WheelFilename {
170 match self {
171 Self::Registry(dist) => &dist.filename,
172 Self::Url(dist) => &dist.filename,
173 }
174 }
175}
176
177impl Hashed for CachedRegistryDist {
178 fn hashes(&self) -> &[HashDigest] {
179 self.hashes.as_slice()
180 }
181}
182
183impl Name for CachedRegistryDist {
184 fn name(&self) -> &PackageName {
185 &self.filename.name
186 }
187}
188
189impl Name for CachedDirectUrlDist {
190 fn name(&self) -> &PackageName {
191 &self.filename.name
192 }
193}
194
195impl Name for CachedDist {
196 fn name(&self) -> &PackageName {
197 match self {
198 Self::Registry(dist) => dist.name(),
199 Self::Url(dist) => dist.name(),
200 }
201 }
202}
203
204impl DistributionMetadata for CachedRegistryDist {
205 fn version_or_url(&self) -> VersionOrUrlRef<'_> {
206 VersionOrUrlRef::Version(&self.filename.version)
207 }
208}
209
210impl DistributionMetadata for CachedDirectUrlDist {
211 fn version_or_url(&self) -> VersionOrUrlRef<'_> {
212 VersionOrUrlRef::Url(&self.url.verbatim)
213 }
214
215 fn version_id(&self) -> VersionId {
216 VersionId::from_parsed_url(&self.url.parsed_url)
217 }
218}
219
220impl DistributionMetadata for CachedDist {
221 fn version_or_url(&self) -> VersionOrUrlRef<'_> {
222 match self {
223 Self::Registry(dist) => dist.version_or_url(),
224 Self::Url(dist) => dist.version_or_url(),
225 }
226 }
227
228 fn version_id(&self) -> VersionId {
229 match self {
230 Self::Registry(dist) => dist.version_id(),
231 Self::Url(dist) => dist.version_id(),
232 }
233 }
234}
235
236impl InstalledMetadata for CachedRegistryDist {
237 fn installed_version(&self) -> InstalledVersion<'_> {
238 InstalledVersion::Version(&self.filename.version)
239 }
240}
241
242impl InstalledMetadata for CachedDirectUrlDist {
243 fn installed_version(&self) -> InstalledVersion<'_> {
244 InstalledVersion::Url(&self.url.verbatim, &self.filename.version)
245 }
246}
247
248impl InstalledMetadata for CachedDist {
249 fn installed_version(&self) -> InstalledVersion<'_> {
250 match self {
251 Self::Registry(dist) => dist.installed_version(),
252 Self::Url(dist) => dist.installed_version(),
253 }
254 }
255}