From 7c2f6824a67afd6e066e1dff6a878436d1008b88 Mon Sep 17 00:00:00 2001 From: Yuyi-Oak <1722157266@qq.com> Date: Wed, 15 Jul 2026 10:27:28 -0700 Subject: [PATCH] =?UTF-8?q?fix(adapters):=20=E6=8C=89=E6=95=B0=E5=80=BC?= =?UTF-8?q?=E6=AF=94=E8=BE=83=20Unity=20=E7=89=88=E6=9C=AC=E8=8C=83?= =?UTF-8?q?=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VersionRange::contains 原为字符串字典序比较,2021.3.9f1 等带发布后缀的 正式版本会被 can_handle/parse 误拒,多位补丁号排序也不正确。改为解析 (major, minor, patch) 数值元组比较,补丁号剥离发布后缀,无法解析的版本 一律视为不在范围内,并补充多位补丁号、后缀版本和畸形版本的测试。 对应 issue #18 维护清单 1-1。 Co-Authored-By: Claude Fable 5 --- adapters/src/unity/adapter.rs | 66 +++++++++++++++++++++++++++++- adapters/src/unity/unity_2021_3.rs | 1 + 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/adapters/src/unity/adapter.rs b/adapters/src/unity/adapter.rs index 9c1c253..d3f1c5c 100644 --- a/adapters/src/unity/adapter.rs +++ b/adapters/src/unity/adapter.rs @@ -21,11 +21,41 @@ impl VersionRange { } /// 检查版本是否在范围内 + /// + /// 按 `(major, minor, patch)` 数值比较,补丁号允许携带 Unity 发布后缀 + /// (例如 `2021.3.9f1` 按补丁号 9 参与比较);无法解析的版本一律视为不在范围内。 pub fn contains(&self, version: &str) -> bool { - version >= self.min.as_str() && version <= self.max.as_str() + match ( + parse_version_components(version), + parse_version_components(&self.min), + parse_version_components(&self.max), + ) { + (Some(version), Some(min), Some(max)) => version >= min && version <= max, + _ => false, + } } } +/// 将 Unity 版本字符串解析为 `(major, minor, patch)` 数值元组。 +/// +/// `major`/`minor` 必须是纯数字;`patch` 取第三段的前导数字, +/// 以兼容 `2021.3.9f1` 这类带发布后缀的正式版本号。 +fn parse_version_components(version: &str) -> Option<(u64, u64, u64)> { + let mut parts = version.split('.'); + let major = parts.next()?.parse::().ok()?; + let minor = parts.next()?.parse::().ok()?; + let patch_part = parts.next()?; + let digit_count = patch_part + .chars() + .take_while(|character| character.is_ascii_digit()) + .count(); + if digit_count == 0 { + return None; + } + let patch = patch_part[..digit_count].parse::().ok()?; + Some((major, minor, patch)) +} + /// 原始 AssetBundle 数据 #[derive(Debug)] pub struct RawAssetBundle { @@ -175,6 +205,40 @@ mod tests { assert!(!range.contains("2021.4.0")); } + #[test] + fn test_version_range_compares_patch_numerically() { + let range = VersionRange::new("2021.3.0", "2021.3.99"); + + assert!(!range.contains("2021.3.100")); + assert!(range.contains("2021.3.9")); + + let wide_range = VersionRange::new("2021.3.20", "2021.3.120"); + assert!(wide_range.contains("2021.3.100")); + assert!(!wide_range.contains("2021.3.9")); + } + + #[test] + fn test_version_range_accepts_release_suffix() { + let range = VersionRange::new("2021.3.0", "2021.3.99"); + + assert!(range.contains("2021.3.9f1")); + assert!(range.contains("2021.3.56f2")); + assert!(range.contains("2021.3.99f1")); + assert!(!range.contains("2021.3.100f1")); + } + + #[test] + fn test_version_range_rejects_malformed_versions() { + let range = VersionRange::new("2021.3.0", "2021.3.99"); + + assert!(!range.contains("")); + assert!(!range.contains("unknown")); + assert!(!range.contains("2021")); + assert!(!range.contains("2021.3")); + assert!(!range.contains("2021.x.5")); + assert!(!range.contains("2021.3.f1")); + } + #[test] fn test_raw_assetbundle() { let bundle = RawAssetBundle { diff --git a/adapters/src/unity/unity_2021_3.rs b/adapters/src/unity/unity_2021_3.rs index 415dbb3..70e23b2 100644 --- a/adapters/src/unity/unity_2021_3.rs +++ b/adapters/src/unity/unity_2021_3.rs @@ -436,6 +436,7 @@ mod tests { assert!(range.contains("2021.3.0")); assert!(range.contains("2021.3.56")); + assert!(range.contains("2021.3.9f1")); assert!(!range.contains("2021.2.0")); }