Skip to main content

uv_distribution_types/
any.rs

1use std::hash::Hash;
2
3use uv_cache_key::CanonicalUrl;
4use uv_normalize::PackageName;
5use uv_pep440::Version;
6
7use crate::cached::CachedDist;
8use crate::installed::InstalledDist;
9use crate::{InstalledMetadata, InstalledVersion, Name};
10
11/// A distribution which is either installable, is a wheel in our cache or is already installed.
12///
13/// Note equality and hash operations are only based on the name and canonical version, not the
14/// kind.
15#[derive(Debug, Clone, Eq)]
16pub enum LocalDist {
17    Cached(CachedDist, CanonicalVersion),
18    Installed(InstalledDist, CanonicalVersion),
19}
20
21impl LocalDist {
22    fn canonical_version(&self) -> &CanonicalVersion {
23        match self {
24            Self::Cached(_, version) => version,
25            Self::Installed(_, version) => version,
26        }
27    }
28}
29
30impl Name for LocalDist {
31    fn name(&self) -> &PackageName {
32        match self {
33            Self::Cached(dist, _) => dist.name(),
34            Self::Installed(dist, _) => dist.name(),
35        }
36    }
37}
38
39impl InstalledMetadata for LocalDist {
40    fn installed_version(&self) -> InstalledVersion<'_> {
41        match self {
42            Self::Cached(dist, _) => dist.installed_version(),
43            Self::Installed(dist, _) => dist.installed_version(),
44        }
45    }
46}
47
48impl From<CachedDist> for LocalDist {
49    fn from(dist: CachedDist) -> Self {
50        let version = CanonicalVersion::from(dist.installed_version());
51        Self::Cached(dist, version)
52    }
53}
54
55impl From<InstalledDist> for LocalDist {
56    fn from(dist: InstalledDist) -> Self {
57        let version = CanonicalVersion::from(dist.installed_version());
58        Self::Installed(dist, version)
59    }
60}
61
62impl Hash for LocalDist {
63    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
64        self.name().hash(state);
65        self.canonical_version().hash(state);
66    }
67}
68
69impl PartialEq for LocalDist {
70    fn eq(&self, other: &Self) -> bool {
71        self.name() == other.name() && self.canonical_version() == other.canonical_version()
72    }
73}
74
75/// Like [`InstalledVersion`], but with [`CanonicalUrl`] to ensure robust URL comparisons.
76#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
77pub enum CanonicalVersion {
78    Version(Version),
79    Url(CanonicalUrl, Version),
80}
81
82impl From<InstalledVersion<'_>> for CanonicalVersion {
83    fn from(installed_version: InstalledVersion<'_>) -> Self {
84        match installed_version {
85            InstalledVersion::Version(version) => Self::Version(version.clone()),
86            InstalledVersion::Url(url, version) => {
87                Self::Url(CanonicalUrl::new(url), version.clone())
88            }
89        }
90    }
91}