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::Built(BuiltDist::GitPath(dist)) => Self::Url(CachedDirectUrlDist {
83 filename,
84 url: VerbatimParsedUrl {
85 parsed_url: dist.parsed_url(),
86 verbatim: dist.url,
87 },
88 hashes,
89 cache_info,
90 build_info,
91 path,
92 }),
93 Dist::Source(SourceDist::Registry(_dist)) => Self::Registry(CachedRegistryDist {
94 filename,
95 path,
96 hashes,
97 cache_info,
98 build_info,
99 }),
100 Dist::Source(SourceDist::DirectUrl(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::GitDirectory(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::GitPath(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 Dist::Source(SourceDist::Path(dist)) => Self::Url(CachedDirectUrlDist {
134 filename,
135 url: VerbatimParsedUrl {
136 parsed_url: dist.parsed_url(),
137 verbatim: dist.url,
138 },
139 hashes,
140 cache_info,
141 build_info,
142 path,
143 }),
144 Dist::Source(SourceDist::Directory(dist)) => Self::Url(CachedDirectUrlDist {
145 filename,
146 url: VerbatimParsedUrl {
147 parsed_url: dist.parsed_url(),
148 verbatim: dist.url,
149 },
150 hashes,
151 cache_info,
152 build_info,
153 path,
154 }),
155 }
156 }
157
158 pub fn path(&self) -> &Path {
160 match self {
161 Self::Registry(dist) => &dist.path,
162 Self::Url(dist) => &dist.path,
163 }
164 }
165
166 pub fn cache_info(&self) -> &CacheInfo {
168 match self {
169 Self::Registry(dist) => &dist.cache_info,
170 Self::Url(dist) => &dist.cache_info,
171 }
172 }
173
174 pub fn build_info(&self) -> Option<&BuildInfo> {
176 match self {
177 Self::Registry(dist) => dist.build_info.as_ref(),
178 Self::Url(dist) => dist.build_info.as_ref(),
179 }
180 }
181
182 pub fn parsed_url(&self) -> Option<&ParsedUrl> {
184 match self {
185 Self::Registry(_) => None,
186 Self::Url(dist) => Some(&dist.url.parsed_url),
187 }
188 }
189
190 pub fn filename(&self) -> &WheelFilename {
192 match self {
193 Self::Registry(dist) => &dist.filename,
194 Self::Url(dist) => &dist.filename,
195 }
196 }
197}
198
199impl Hashed for CachedRegistryDist {
200 fn hashes(&self) -> &[HashDigest] {
201 self.hashes.as_slice()
202 }
203}
204
205impl Name for CachedRegistryDist {
206 fn name(&self) -> &PackageName {
207 &self.filename.name
208 }
209}
210
211impl Name for CachedDirectUrlDist {
212 fn name(&self) -> &PackageName {
213 &self.filename.name
214 }
215}
216
217impl Name for CachedDist {
218 fn name(&self) -> &PackageName {
219 match self {
220 Self::Registry(dist) => dist.name(),
221 Self::Url(dist) => dist.name(),
222 }
223 }
224}
225
226impl DistributionMetadata for CachedRegistryDist {
227 fn version_or_url(&self) -> VersionOrUrlRef<'_> {
228 VersionOrUrlRef::Version(&self.filename.version)
229 }
230}
231
232impl DistributionMetadata for CachedDirectUrlDist {
233 fn version_or_url(&self) -> VersionOrUrlRef<'_> {
234 VersionOrUrlRef::Url(&self.url.verbatim)
235 }
236
237 fn version_id(&self) -> VersionId {
238 VersionId::from_parsed_url(&self.url.parsed_url)
239 }
240}
241
242impl DistributionMetadata for CachedDist {
243 fn version_or_url(&self) -> VersionOrUrlRef<'_> {
244 match self {
245 Self::Registry(dist) => dist.version_or_url(),
246 Self::Url(dist) => dist.version_or_url(),
247 }
248 }
249
250 fn version_id(&self) -> VersionId {
251 match self {
252 Self::Registry(dist) => dist.version_id(),
253 Self::Url(dist) => dist.version_id(),
254 }
255 }
256}
257
258impl InstalledMetadata for CachedRegistryDist {
259 fn installed_version(&self) -> InstalledVersion<'_> {
260 InstalledVersion::Version(&self.filename.version)
261 }
262}
263
264impl InstalledMetadata for CachedDirectUrlDist {
265 fn installed_version(&self) -> InstalledVersion<'_> {
266 InstalledVersion::Url(&self.url.verbatim, &self.filename.version)
267 }
268}
269
270impl InstalledMetadata for CachedDist {
271 fn installed_version(&self) -> InstalledVersion<'_> {
272 match self {
273 Self::Registry(dist) => dist.installed_version(),
274 Self::Url(dist) => dist.installed_version(),
275 }
276 }
277}