chore: establish development baseline

This commit is contained in:
2026-06-28 01:27:09 +08:00
commit dd53e3054e
131 changed files with 19327 additions and 0 deletions
+122
View File
@@ -0,0 +1,122 @@
//! Unity Adapter 接口定义
use async_trait::async_trait;
/// Unity 版本范围
#[derive(Debug, Clone)]
pub struct VersionRange {
/// 最小版本(包含)
pub min: String,
/// 最大版本(包含)
pub max: String,
}
impl VersionRange {
/// 创建新的版本范围
pub fn new(min: impl Into<String>, max: impl Into<String>) -> Self {
Self {
min: min.into(),
max: max.into(),
}
}
/// 检查版本是否在范围内
pub fn contains(&self, version: &str) -> bool {
version >= self.min.as_str() && version <= self.max.as_str()
}
}
/// 原始 AssetBundle 数据
#[derive(Debug)]
pub struct RawAssetBundle {
/// 文件数据
pub data: Vec<u8>,
/// 文件路径(可选)
pub path: Option<String>,
}
/// 解析后的 AssetBundle
#[derive(Debug)]
pub struct ParsedAssetBundle {
/// Unity 版本
pub unity_version: String,
/// 资源列表(简化表示)
pub assets: Vec<String>,
/// 原始数据(保留用于序列化)
pub raw_data: Vec<u8>,
}
/// Unity Adapter 接口
///
/// 用于解析不同 Unity 版本的 AssetBundle
#[async_trait]
pub trait UnityAdapter: Send + Sync {
/// 适配器名称(例如 "Unity-2021.3"
fn name(&self) -> &str;
/// 支持的 Unity 版本范围
fn supported_versions(&self) -> VersionRange;
/// 检测是否可以处理这个 AssetBundle
///
/// # 参数
/// - `bundle`: 原始 AssetBundle
///
/// # 返回
/// - true: 可以处理
/// - false: 不能处理
fn can_handle(&self, bundle: &RawAssetBundle) -> bool;
/// 解析 AssetBundle
///
/// # 参数
/// - `bundle`: 原始 AssetBundle
///
/// # 返回
/// - 成功:返回解析后的 AssetBundle
/// - 失败:返回错误
///
/// # 注意
/// Phase 1 中标记为 TODOPhase 2 实现
async fn parse(&self, bundle: &RawAssetBundle) -> Result<ParsedAssetBundle, String>;
/// 序列化 AssetBundle
///
/// # 参数
/// - `parsed`: 解析后的 AssetBundle
///
/// # 返回
/// - 成功:返回序列化后的数据
/// - 失败:返回错误
///
/// # 注意
/// Phase 1 中标记为 TODOPhase 2 实现
async fn serialize(&self, parsed: &ParsedAssetBundle) -> Result<Vec<u8>, String>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_version_range() {
let range = VersionRange::new("2021.3.0", "2021.3.99");
assert!(range.contains("2021.3.0"));
assert!(range.contains("2021.3.56"));
assert!(range.contains("2021.3.99"));
assert!(!range.contains("2021.2.0"));
assert!(!range.contains("2021.4.0"));
}
#[test]
fn test_raw_assetbundle() {
let bundle = RawAssetBundle {
data: vec![0x55, 0x6e, 0x69, 0x74, 0x79, 0x46, 0x53], // "UnityFS"
path: Some("test.bundle".to_string()),
};
assert_eq!(bundle.data.len(), 7);
assert_eq!(bundle.path, Some("test.bundle".to_string()));
}
}
+114
View File
@@ -0,0 +1,114 @@
//! Unity Adapter 注册表
//!
//! 管理所有 Unity Adapter 并自动选择合适的适配器
use super::adapter::{RawAssetBundle, UnityAdapter};
use std::sync::Arc;
/// Unity Adapter 注册表
pub struct UnityAdapterRegistry {
adapters: Vec<Arc<dyn UnityAdapter>>,
}
impl UnityAdapterRegistry {
/// 创建新的注册表
pub fn new() -> Self {
Self {
adapters: Vec::new(),
}
}
/// 注册一个适配器
pub fn register(&mut self, adapter: Arc<dyn UnityAdapter>) {
self.adapters.push(adapter);
}
/// 自动选择合适的适配器
///
/// # 参数
/// - `bundle`: 原始 AssetBundle
///
/// # 返回
/// - 成功:返回合适的适配器
/// - 失败:如果没有合适的适配器,返回错误
pub fn select_adapter(&self, bundle: &RawAssetBundle) -> Result<Arc<dyn UnityAdapter>, String> {
for adapter in &self.adapters {
if adapter.can_handle(bundle) {
return Ok(Arc::clone(adapter));
}
}
Err("No suitable adapter found for this AssetBundle".to_string())
}
/// 获取所有已注册的适配器
pub fn all_adapters(&self) -> &[Arc<dyn UnityAdapter>] {
&self.adapters
}
/// 获取适配器数量
pub fn count(&self) -> usize {
self.adapters.len()
}
}
impl Default for UnityAdapterRegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::unity::Unity2021_3Adapter;
#[test]
fn test_registry_new() {
let registry = UnityAdapterRegistry::new();
assert_eq!(registry.count(), 0);
}
#[test]
fn test_register_adapter() {
let mut registry = UnityAdapterRegistry::new();
let adapter = Arc::new(Unity2021_3Adapter::new());
registry.register(adapter);
assert_eq!(registry.count(), 1);
}
#[test]
fn test_select_adapter() {
let mut registry = UnityAdapterRegistry::new();
registry.register(Arc::new(Unity2021_3Adapter::new()));
// 创建一个 Unity 2021.3 的 bundle
let mut data = Vec::new();
data.extend_from_slice(b"UnityFS\0");
data.extend_from_slice(&[0, 0, 0, 8]);
data.extend_from_slice(b"5.x.x\x002021.3.56f2\0");
let bundle = RawAssetBundle {
data,
path: Some("test.bundle".to_string()),
};
let result = registry.select_adapter(&bundle);
assert!(result.is_ok());
assert_eq!(result.unwrap().name(), "Unity-2021.3");
}
#[test]
fn test_select_adapter_not_found() {
let registry = UnityAdapterRegistry::new();
let bundle = RawAssetBundle {
data: vec![0, 1, 2, 3],
path: None,
};
let result = registry.select_adapter(&bundle);
assert!(result.is_err());
}
}
+158
View File
@@ -0,0 +1,158 @@
//! Unity 2021.3 Adapter
//!
//! 支持 Unity 2021.3.x 版本的 AssetBundle
use super::adapter::{ParsedAssetBundle, RawAssetBundle, UnityAdapter, VersionRange};
use async_trait::async_trait;
/// Unity 2021.3 Adapter
pub struct Unity2021_3Adapter;
impl Unity2021_3Adapter {
/// 创建新的适配器实例
pub fn new() -> Self {
Self
}
/// 检测 Unity 版本(从文件头)
fn detect_unity_version(data: &[u8]) -> Option<String> {
// UnityFS 文件头结构:
// 0x00-0x06: "UnityFS\0"
// 0x08-0x0B: format version
// 0x0C-...: Unity version string
if data.len() < 20 {
return None;
}
// 检查签名
if &data[0..7] != b"UnityFS" {
return None;
}
// 读取 Unity 版本字符串
// 版本字符串从偏移 0x14 开始(可能因格式版本不同而变化)
if let Some(version_start) = data.windows(7).position(|w| w.starts_with(b"2021.3.")) {
// 读取版本字符串直到 null 或非 ASCII
let version_bytes = &data[version_start..];
if let Some(end) = version_bytes.iter().position(|&b| b == 0 || !b.is_ascii()) {
if let Ok(version) = std::str::from_utf8(&version_bytes[..end]) {
return Some(version.to_string());
}
}
}
None
}
}
impl Default for Unity2021_3Adapter {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl UnityAdapter for Unity2021_3Adapter {
fn name(&self) -> &str {
"Unity-2021.3"
}
fn supported_versions(&self) -> VersionRange {
VersionRange::new("2021.3.0", "2021.3.99")
}
fn can_handle(&self, bundle: &RawAssetBundle) -> bool {
// 检测 Unity 版本
if let Some(version) = Self::detect_unity_version(&bundle.data) {
self.supported_versions().contains(&version)
} else {
false
}
}
async fn parse(&self, _bundle: &RawAssetBundle) -> Result<ParsedAssetBundle, String> {
// TODO: Phase 2 实现
// 需要:
// 1. 解析 UnityFS 文件头
// 2. 解压缩数据块
// 3. 解析 TypeTree
// 4. 提取 Asset 对象
Err("parse() 将在 Phase 2 实现".to_string())
}
async fn serialize(&self, _parsed: &ParsedAssetBundle) -> Result<Vec<u8>, String> {
// TODO: Phase 2 实现
// 需要:
// 1. 序列化 Asset 对象
// 2. 重新构建 TypeTree
// 3. 压缩数据块
// 4. 写入 UnityFS 文件头
Err("serialize() 将在 Phase 2 实现".to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_adapter_name() {
let adapter = Unity2021_3Adapter::new();
assert_eq!(adapter.name(), "Unity-2021.3");
}
#[test]
fn test_supported_versions() {
let adapter = Unity2021_3Adapter::new();
let range = adapter.supported_versions();
assert!(range.contains("2021.3.0"));
assert!(range.contains("2021.3.56"));
assert!(!range.contains("2021.2.0"));
}
#[test]
fn test_can_handle_valid_bundle() {
let adapter = Unity2021_3Adapter::new();
// 模拟 UnityFS 文件头
let mut data = Vec::new();
data.extend_from_slice(b"UnityFS\0");
data.extend_from_slice(&[0, 0, 0, 8]); // format version
data.extend_from_slice(b"5.x.x\x002021.3.56f2\0");
let bundle = RawAssetBundle {
data,
path: Some("test.bundle".to_string()),
};
assert!(adapter.can_handle(&bundle));
}
#[test]
fn test_can_handle_invalid_bundle() {
let adapter = Unity2021_3Adapter::new();
let bundle = RawAssetBundle {
data: vec![0, 1, 2, 3],
path: None,
};
assert!(!adapter.can_handle(&bundle));
}
#[tokio::test]
async fn test_parse_not_implemented() {
let adapter = Unity2021_3Adapter::new();
let bundle = RawAssetBundle {
data: vec![],
path: None,
};
let result = adapter.parse(&bundle).await;
assert!(result.is_err());
assert!(result.unwrap_err().contains("Phase 2"));
}
}