Shrink size of platform tag enum (#10546)

## Summary

Reduces it from 56 bytes to 16 bytes.
This commit is contained in:
Charlie Marsh 2025-01-13 22:13:59 -05:00 committed by GitHub
parent 3fd090b373
commit faa4481ccc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 89 additions and 152 deletions

1
Cargo.lock generated
View File

@ -5326,6 +5326,7 @@ dependencies = [
"rustc-hash",
"serde",
"thiserror 2.0.11",
"uv-small-str",
]
[[package]]

View File

@ -92,3 +92,13 @@ impl Display for DistFilename {
}
}
}
#[cfg(test)]
mod tests {
use crate::WheelFilename;
#[test]
fn wheel_filename_size() {
assert_eq!(size_of::<WheelFilename>(), 128);
}
}

View File

@ -1343,10 +1343,10 @@ mod test {
/// Ensure that we don't accidentally grow the `Dist` sizes.
#[test]
fn dist_size() {
assert!(size_of::<Dist>() <= 312, "{}", size_of::<Dist>());
assert!(size_of::<BuiltDist>() <= 312, "{}", size_of::<BuiltDist>());
assert!(size_of::<Dist>() <= 272, "{}", size_of::<Dist>());
assert!(size_of::<BuiltDist>() <= 272, "{}", size_of::<BuiltDist>());
assert!(
size_of::<SourceDist>() <= 264,
size_of::<SourceDist>() <= 248,
"{}",
size_of::<SourceDist>()
);

View File

@ -16,6 +16,8 @@ doctest = false
workspace = true
[dependencies]
uv-small-str = { workspace = true }
memchr = { workspace = true }
rkyv = { workspace = true}
rustc-hash = { workspace = true }

View File

@ -1,12 +1,18 @@
use std::fmt::Formatter;
use std::str::FromStr;
use uv_small_str::SmallString;
use crate::{Arch, BinaryFormat};
/// A tag to represent the platform compatibility of a Python distribution.
///
/// This is the third segment in the wheel filename, following the language and ABI tags. For
/// example, in `cp39-none-manylinux_2_24_x86_64.whl`, the platform tag is `manylinux_2_24_x86_64`.
///
/// For simplicity (and to reduce struct size), the non-Linux, macOS, and Windows variants (like
/// FreeBSD) store an opaque suffix, which combines the release (like `3.14`) and architecture (like
/// `x86_64`) into a single string (like `3_14_x86_64`).
#[derive(
Debug,
Clone,
@ -50,19 +56,19 @@ pub enum PlatformTag {
/// Ex) `android_21_x86_64`
Android { api_level: u16, arch: Arch },
/// Ex) `freebsd_12_x86_64`
FreeBsd { release: String, arch: Arch },
FreeBsd { release_arch: SmallString },
/// Ex) `netbsd_9_x86_64`
NetBsd { release: String, arch: Arch },
NetBsd { release_arch: SmallString },
/// Ex) `openbsd_6_x86_64`
OpenBsd { release: String, arch: Arch },
OpenBsd { release_arch: SmallString },
/// Ex) `dragonfly_6_x86_64`
Dragonfly { release: String, arch: Arch },
Dragonfly { release_arch: SmallString },
/// Ex) `haiku_1_x86_64`
Haiku { release: String, arch: Arch },
Haiku { release_arch: SmallString },
/// Ex) `illumos_5_11_x86_64`
Illumos { release: String, arch: String },
Illumos { release_arch: SmallString },
/// Ex) `solaris_11_4_x86_64`
Solaris { release: String, arch: String },
Solaris { release_arch: SmallString },
}
impl PlatformTag {
@ -124,13 +130,13 @@ impl std::fmt::Display for PlatformTag {
Self::WinAmd64 => write!(f, "win_amd64"),
Self::WinArm64 => write!(f, "win_arm64"),
Self::Android { api_level, arch } => write!(f, "android_{api_level}_{arch}"),
Self::FreeBsd { release, arch } => write!(f, "freebsd_{release}_{arch}"),
Self::NetBsd { release, arch } => write!(f, "netbsd_{release}_{arch}"),
Self::OpenBsd { release, arch } => write!(f, "openbsd_{release}_{arch}"),
Self::Dragonfly { release, arch } => write!(f, "dragonfly_{release}_{arch}"),
Self::Haiku { release, arch } => write!(f, "haiku_{release}_{arch}"),
Self::Illumos { release, arch } => write!(f, "illumos_{release}_{arch}"),
Self::Solaris { release, arch } => write!(f, "solaris_{release}_{arch}_64bit"),
Self::FreeBsd { release_arch } => write!(f, "freebsd_{release_arch}"),
Self::NetBsd { release_arch } => write!(f, "netbsd_{release_arch}"),
Self::OpenBsd { release_arch } => write!(f, "openbsd_{release_arch}"),
Self::Dragonfly { release_arch } => write!(f, "dragonfly_{release_arch}"),
Self::Haiku { release_arch } => write!(f, "haiku_{release_arch}"),
Self::Illumos { release_arch } => write!(f, "illumos_{release_arch}"),
Self::Solaris { release_arch } => write!(f, "solaris_{release_arch}_64bit"),
}
}
}
@ -386,20 +392,8 @@ impl FromStr for PlatformTag {
});
}
// Try each known Arch value as a potential suffix
for arch in Arch::iter() {
if let Some(release) = rest.strip_suffix(arch.name()) {
// Remove trailing underscore from release
let release = release.strip_suffix('_').unwrap_or(release).to_string();
if !release.is_empty() {
return Ok(Self::FreeBsd { release, arch });
}
}
}
return Err(ParsePlatformTagError::InvalidArch {
platform: "freebsd",
tag: s.to_string(),
return Ok(Self::FreeBsd {
release_arch: SmallString::from(rest),
});
}
@ -412,20 +406,8 @@ impl FromStr for PlatformTag {
});
}
// Try each known Arch value as a potential suffix
for arch in Arch::iter() {
if let Some(release) = rest.strip_suffix(arch.name()) {
// Remove trailing underscore from release
let release = release.strip_suffix('_').unwrap_or(release).to_string();
if !release.is_empty() {
return Ok(Self::NetBsd { release, arch });
}
}
}
return Err(ParsePlatformTagError::InvalidArch {
platform: "netbsd",
tag: s.to_string(),
return Ok(Self::NetBsd {
release_arch: SmallString::from(rest),
});
}
@ -438,20 +420,8 @@ impl FromStr for PlatformTag {
});
}
// Try each known Arch value as a potential suffix
for arch in Arch::iter() {
if let Some(release) = rest.strip_suffix(arch.name()) {
// Remove trailing underscore from release
let release = release.strip_suffix('_').unwrap_or(release).to_string();
if !release.is_empty() {
return Ok(Self::OpenBsd { release, arch });
}
}
}
return Err(ParsePlatformTagError::InvalidArch {
platform: "openbsd",
tag: s.to_string(),
return Ok(Self::OpenBsd {
release_arch: SmallString::from(rest),
});
}
@ -464,20 +434,8 @@ impl FromStr for PlatformTag {
});
}
// Try each known Arch value as a potential suffix
for arch in Arch::iter() {
if let Some(release) = rest.strip_suffix(arch.name()) {
// Remove trailing underscore from release
let release = release.strip_suffix('_').unwrap_or(release).to_string();
if !release.is_empty() {
return Ok(Self::Dragonfly { release, arch });
}
}
}
return Err(ParsePlatformTagError::InvalidArch {
platform: "dragonfly",
tag: s.to_string(),
return Ok(Self::Dragonfly {
release_arch: SmallString::from(rest),
});
}
@ -490,20 +448,8 @@ impl FromStr for PlatformTag {
});
}
// Try each known Arch value as a potential suffix
for arch in Arch::iter() {
if let Some(release) = rest.strip_suffix(arch.name()) {
// Remove trailing underscore from release
let release = release.strip_suffix('_').unwrap_or(release).to_string();
if !release.is_empty() {
return Ok(Self::Haiku { release, arch });
}
}
}
return Err(ParsePlatformTagError::InvalidArch {
platform: "haiku",
tag: s.to_string(),
return Ok(Self::Haiku {
release_arch: SmallString::from(rest),
});
}
@ -516,23 +462,8 @@ impl FromStr for PlatformTag {
});
}
// Try each known Arch value as a potential suffix
for arch in Arch::iter() {
if let Some(release) = rest.strip_suffix(arch.name()) {
// Remove trailing underscore from release
let release = release.strip_suffix('_').unwrap_or(release).to_string();
if !release.is_empty() {
return Ok(Self::Illumos {
release,
arch: arch.name().to_string(),
});
}
}
}
return Err(ParsePlatformTagError::InvalidArch {
platform: "illumos",
tag: s.to_string(),
return Ok(Self::Illumos {
release_arch: SmallString::from(rest),
});
}
@ -545,19 +476,11 @@ impl FromStr for PlatformTag {
});
}
// Try each known Arch value as a potential suffix
for arch in Arch::iter() {
if let Some(rest) = rest.strip_suffix("_64bit") {
if let Some(rest) = rest.strip_suffix(&format!("_{}", arch.name())) {
// Remove trailing underscore from release
let release = rest.strip_suffix('_').unwrap_or(rest).to_string();
if !release.is_empty() {
return Ok(Self::Solaris {
release,
arch: arch.name().to_string(),
});
}
}
if let Some(release_arch) = rest.strip_suffix("_64bit") {
if !release_arch.is_empty() {
return Ok(Self::Solaris {
release_arch: SmallString::from(release_arch),
});
}
}
@ -810,50 +733,31 @@ mod tests {
#[test]
fn freebsd_platform() {
let tag = PlatformTag::FreeBsd {
release: "13_14".to_string(),
arch: Arch::X86_64,
release_arch: "13_14_x86_64".into(),
};
assert_eq!(
PlatformTag::from_str("freebsd_13_14_x86_64").as_ref(),
Ok(&tag)
);
assert_eq!(tag.to_string(), "freebsd_13_14_x86_64");
assert_eq!(
PlatformTag::from_str("freebsd_13_14"),
Err(ParsePlatformTagError::InvalidArch {
platform: "freebsd",
tag: "freebsd_13_14".to_string()
})
);
}
#[test]
fn illumos_platform() {
let tag = PlatformTag::Illumos {
release: "5_11".to_string(),
arch: "x86_64".to_string(),
release_arch: "5_11_x86_64".into(),
};
assert_eq!(
PlatformTag::from_str("illumos_5_11_x86_64").as_ref(),
Ok(&tag)
);
assert_eq!(tag.to_string(), "illumos_5_11_x86_64");
assert_eq!(
PlatformTag::from_str("illumos_5_11"),
Err(ParsePlatformTagError::InvalidArch {
platform: "illumos",
tag: "illumos_5_11".to_string()
})
);
}
#[test]
fn solaris_platform() {
let tag = PlatformTag::Solaris {
release: "11_4".to_string(),
arch: "x86_64".to_string(),
release_arch: "11_4_x86_64".into(),
};
assert_eq!(
PlatformTag::from_str("solaris_11_4_x86_64_64bit").as_ref(),

View File

@ -6,6 +6,8 @@ use std::{cmp, num::NonZeroU32};
use rustc_hash::FxHashMap;
use uv_small_str::SmallString;
use crate::{AbiTag, Arch, LanguageTag, Os, Platform, PlatformError, PlatformTag};
#[derive(Debug, thiserror::Error)]
@ -551,25 +553,40 @@ fn compatible_tags(platform: &Platform) -> Result<Vec<PlatformTag>, PlatformErro
vec![PlatformTag::WinAmd64]
}
(Os::Windows, Arch::Aarch64) => vec![PlatformTag::WinArm64],
(Os::FreeBsd { release }, _) => {
(Os::FreeBsd { release }, arch) => {
let release = release.replace(['.', '-'], "_");
vec![PlatformTag::FreeBsd { release, arch }]
let release_arch = format!("{release}_{arch}");
vec![PlatformTag::FreeBsd {
release_arch: SmallString::from(release_arch),
}]
}
(Os::NetBsd { release }, _) => {
(Os::NetBsd { release }, arch) => {
let release = release.replace(['.', '-'], "_");
vec![PlatformTag::NetBsd { release, arch }]
let release_arch = format!("{release}_{arch}");
vec![PlatformTag::NetBsd {
release_arch: SmallString::from(release_arch),
}]
}
(Os::OpenBsd { release }, _) => {
(Os::OpenBsd { release }, arch) => {
let release = release.replace(['.', '-'], "_");
vec![PlatformTag::OpenBsd { release, arch }]
let release_arch = format!("{release}_{arch}");
vec![PlatformTag::OpenBsd {
release_arch: SmallString::from(release_arch),
}]
}
(Os::Dragonfly { release }, _) => {
(Os::Dragonfly { release }, arch) => {
let release = release.replace(['.', '-'], "_");
vec![PlatformTag::Dragonfly { release, arch }]
let release_arch = format!("{release}_{arch}");
vec![PlatformTag::Dragonfly {
release_arch: SmallString::from(release_arch),
}]
}
(Os::Haiku { release }, _) => {
(Os::Haiku { release }, arch) => {
let release = release.replace(['.', '-'], "_");
vec![PlatformTag::Haiku { release, arch }]
let release_arch = format!("{release}_{arch}");
vec![PlatformTag::Haiku {
release_arch: SmallString::from(release_arch),
}]
}
(Os::Illumos { release, arch }, _) => {
// See https://github.com/python/cpython/blob/46c8d915715aa2bd4d697482aa051fe974d440e1/Lib/sysconfig.py#L722-L730
@ -583,13 +600,16 @@ fn compatible_tags(platform: &Platform) -> Result<Vec<PlatformTag>, PlatformErro
// SunOS 5 == Solaris 2
let release = format!("{}_{}", major_ver - 3, other);
let arch = format!("{arch}_64bit");
return Ok(vec![PlatformTag::Solaris { release, arch }]);
let release_arch = format!("{release}_{arch}");
return Ok(vec![PlatformTag::Solaris {
release_arch: SmallString::from(release_arch),
}]);
}
}
let release_arch = format!("{release}_{arch}");
vec![PlatformTag::Illumos {
release: release.to_string(),
arch: arch.to_string(),
release_arch: SmallString::from(release_arch),
}]
}
(Os::Android { api_level }, _) => {