From 4172519d22976c51f3106a0391b5c5c8f5f89a55 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sun, 2 Aug 2026 14:30:05 +0000 Subject: [PATCH 1/3] Avoid flattened source-distribution deserialization in lockfiles --- crates/uv-resolver/src/lock/mod.rs | 41 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/crates/uv-resolver/src/lock/mod.rs b/crates/uv-resolver/src/lock/mod.rs index 8772f64fb9a..2e90d7a94c8 100644 --- a/crates/uv-resolver/src/lock/mod.rs +++ b/crates/uv-resolver/src/lock/mod.rs @@ -5742,33 +5742,32 @@ impl SourceDist { } #[derive(Clone, Debug, serde::Deserialize)] -#[serde(untagged, rename_all = "kebab-case")] -enum SourceDistWire { - Url { - url: UrlString, - #[serde(flatten)] - metadata: SourceDistMetadata, - }, - Path { - path: PortablePathBuf, - #[serde(flatten)] - metadata: SourceDistMetadata, - }, - Metadata { - #[serde(flatten)] - metadata: SourceDistMetadata, - }, +#[serde(rename_all = "kebab-case")] +struct SourceDistWire { + url: Option, + path: Option, + hash: Option, + size: Option, + #[serde(alias = "upload_time")] + upload_time: Option, } impl From for SourceDist { fn from(wire: SourceDistWire) -> Self { - match wire { - SourceDistWire::Url { url, metadata } => Self::Url { url, metadata }, - SourceDistWire::Path { path, metadata } => Self::Path { + let metadata = SourceDistMetadata { + hash: wire.hash, + size: wire.size, + upload_time: wire.upload_time, + }; + if let Some(url) = wire.url { + Self::Url { url, metadata } + } else if let Some(path) = wire.path { + Self::Path { path: path.into(), metadata, - }, - SourceDistWire::Metadata { metadata } => Self::Metadata { metadata }, + } + } else { + Self::Metadata { metadata } } } } From caa94516dcc7276dd0f6e55d6420435013b53588 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 3 Aug 2026 10:50:18 -0400 Subject: [PATCH 2/3] Deserialize source distributions directly --- crates/uv-resolver/src/lock/mod.rs | 78 ++++++++++++++++-------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/crates/uv-resolver/src/lock/mod.rs b/crates/uv-resolver/src/lock/mod.rs index 2e90d7a94c8..4f3c61706e6 100644 --- a/crates/uv-resolver/src/lock/mod.rs +++ b/crates/uv-resolver/src/lock/mod.rs @@ -5464,25 +5464,62 @@ struct SourceDistMetadata { /// locked against was found. The location does not need to exist in the /// future, so this should be treated as only a hint to where to look /// and/or recording where the source dist file originally came from. -#[derive(Clone, Debug, serde::Deserialize, PartialEq, Eq)] -#[serde(from = "SourceDistWire")] +#[derive(Clone, Debug, PartialEq, Eq)] enum SourceDist { Url { url: UrlString, - #[serde(flatten)] metadata: SourceDistMetadata, }, Path { path: Box, - #[serde(flatten)] metadata: SourceDistMetadata, }, Metadata { - #[serde(flatten)] metadata: SourceDistMetadata, }, } +impl<'de> serde::Deserialize<'de> for SourceDist { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + #[derive(serde::Deserialize)] + #[serde(rename_all = "kebab-case")] + struct Fields { + url: Option, + path: Option, + hash: Option, + size: Option, + #[serde(alias = "upload_time")] + upload_time: Option, + } + + let Fields { + url, + path, + hash, + size, + upload_time, + } = serde::Deserialize::deserialize(deserializer)?; + + let metadata = SourceDistMetadata { + hash, + size, + upload_time, + }; + + Ok(match (url, path) { + (Some(url), _) => Self::Url { url, metadata }, + (None, Some(path)) => Self::Path { + path: path.into(), + metadata, + }, + (None, None) => Self::Metadata { metadata }, + }) + } +} + impl SourceDist { fn filename(&self) -> Option> { match self { @@ -5741,37 +5778,6 @@ impl SourceDist { } } -#[derive(Clone, Debug, serde::Deserialize)] -#[serde(rename_all = "kebab-case")] -struct SourceDistWire { - url: Option, - path: Option, - hash: Option, - size: Option, - #[serde(alias = "upload_time")] - upload_time: Option, -} - -impl From for SourceDist { - fn from(wire: SourceDistWire) -> Self { - let metadata = SourceDistMetadata { - hash: wire.hash, - size: wire.size, - upload_time: wire.upload_time, - }; - if let Some(url) = wire.url { - Self::Url { url, metadata } - } else if let Some(path) = wire.path { - Self::Path { - path: path.into(), - metadata, - } - } else { - Self::Metadata { metadata } - } - } -} - impl From for GitSourceKind { fn from(value: GitReference) -> Self { match value { From bb6bdbb59a844168554a7945931a6396e3e751e5 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 3 Aug 2026 10:57:28 -0400 Subject: [PATCH 3/3] Remove unused deserialize --- crates/uv-resolver/src/lock/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/uv-resolver/src/lock/mod.rs b/crates/uv-resolver/src/lock/mod.rs index 4f3c61706e6..224f0cdf8cb 100644 --- a/crates/uv-resolver/src/lock/mod.rs +++ b/crates/uv-resolver/src/lock/mod.rs @@ -5446,8 +5446,7 @@ enum GitSourceKind { } /// Inspired by: -#[derive(Clone, Debug, serde::Deserialize, PartialEq, Eq)] -#[serde(rename_all = "kebab-case")] +#[derive(Clone, Debug, PartialEq, Eq)] struct SourceDistMetadata { /// A hash of the source distribution. hash: Option, @@ -5456,7 +5455,6 @@ struct SourceDistMetadata { /// This is only present for source distributions that come from registries. size: Option, /// The upload time of the source distribution. - #[serde(alias = "upload_time")] upload_time: Option, }