mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-07-22 05:55:15 +08:00
feat: prepare experiment push package
This commit is contained in:
@@ -52,9 +52,52 @@ impl AddressablesCatalogDriver {
|
||||
}
|
||||
}
|
||||
|
||||
fn resources(json: &Value) -> Vec<ResourceEntry> {
|
||||
let resources = json
|
||||
.get("m_InternalIds")
|
||||
fn resource_from_entry(value: &Value, index: usize) -> Option<ResourceEntry> {
|
||||
let path = value
|
||||
.get("internal_id")
|
||||
.or_else(|| value.get("InternalId"))
|
||||
.or_else(|| value.get("path"))
|
||||
.or_else(|| value.get("Path"))
|
||||
.and_then(|value| value.as_str())?;
|
||||
|
||||
if path.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let hash = value
|
||||
.get("hash")
|
||||
.or_else(|| value.get("Hash"))
|
||||
.and_then(|value| value.as_str())
|
||||
.map(ToOwned::to_owned)
|
||||
.unwrap_or_else(|| format!("addressable_{}", index));
|
||||
|
||||
let size = value
|
||||
.get("size")
|
||||
.or_else(|| value.get("Size"))
|
||||
.and_then(|value| value.as_u64())
|
||||
.unwrap_or_default();
|
||||
|
||||
Some(ResourceEntry {
|
||||
path: path.to_string(),
|
||||
hash,
|
||||
size,
|
||||
resource_type: Self::resource_type_for_path(path),
|
||||
})
|
||||
}
|
||||
|
||||
fn entry_resources(json: &Value) -> Vec<ResourceEntry> {
|
||||
json.get("m_Entries")
|
||||
.or_else(|| json.get("entries"))
|
||||
.and_then(|value| value.as_array())
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.enumerate()
|
||||
.filter_map(|(index, value)| Self::resource_from_entry(value, index))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn internal_id_resources(json: &Value) -> Vec<ResourceEntry> {
|
||||
json.get("m_InternalIds")
|
||||
.and_then(|value| value.as_array())
|
||||
.into_iter()
|
||||
.flatten()
|
||||
@@ -72,8 +115,55 @@ impl AddressablesCatalogDriver {
|
||||
resource_type: Self::resource_type_for_path(path),
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
resources
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn resources(json: &Value) -> Vec<ResourceEntry> {
|
||||
let entry_resources = Self::entry_resources(json);
|
||||
if !entry_resources.is_empty() {
|
||||
return entry_resources;
|
||||
}
|
||||
|
||||
Self::internal_id_resources(json)
|
||||
}
|
||||
|
||||
fn extra_metadata(json: &Value) -> HashMap<String, String> {
|
||||
let mut extra = HashMap::new();
|
||||
Self::insert_array_len(&mut extra, json, "m_InternalIds", "internal_id_count");
|
||||
Self::insert_array_len(&mut extra, json, "m_Entries", "entry_count");
|
||||
Self::insert_string_len(&mut extra, json, "m_KeyDataString", "key_data_string_len");
|
||||
Self::insert_string_len(
|
||||
&mut extra,
|
||||
json,
|
||||
"m_EntryDataString",
|
||||
"entry_data_string_len",
|
||||
);
|
||||
extra
|
||||
}
|
||||
|
||||
fn insert_array_len(extra: &mut HashMap<String, String>, json: &Value, field: &str, key: &str) {
|
||||
if let Some(len) = json
|
||||
.get(field)
|
||||
.and_then(|value| value.as_array())
|
||||
.map(|values| values.len())
|
||||
{
|
||||
extra.insert(key.to_string(), len.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_string_len(
|
||||
extra: &mut HashMap<String, String>,
|
||||
json: &Value,
|
||||
field: &str,
|
||||
key: &str,
|
||||
) {
|
||||
if let Some(len) = json
|
||||
.get(field)
|
||||
.and_then(|value| value.as_str())
|
||||
.map(|value| value.len())
|
||||
{
|
||||
extra.insert(key.to_string(), len.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,14 +215,10 @@ impl ManifestDriver for AddressablesCatalogDriver {
|
||||
async fn parse(&self, raw_data: &[u8]) -> Result<GenericManifest, String> {
|
||||
let json = Self::parse_json(raw_data)?;
|
||||
|
||||
// TODO: 解析 m_KeyDataString、m_EntryDataString 等压缩字段
|
||||
// 这些字段使用了自定义压缩格式,需要实现解压缩算法
|
||||
// 参考:Unity Addressables 源代码
|
||||
|
||||
let metadata = ManifestMetadata {
|
||||
locator_id: Self::locator_id(&json),
|
||||
cdn_prefixes: Self::cdn_prefixes(&json),
|
||||
extra: HashMap::new(),
|
||||
extra: Self::extra_metadata(&json),
|
||||
};
|
||||
|
||||
Ok(GenericManifest {
|
||||
@@ -178,9 +264,9 @@ mod tests {
|
||||
"m_LocatorId": "AddressablesMainContentCatalog",
|
||||
"m_InternalIdPrefixes": [],
|
||||
"m_InternalIds": [
|
||||
"academy.bundle",
|
||||
"character.bundle",
|
||||
"catalog.json"
|
||||
"synthetic/minimal-a.bundle",
|
||||
"synthetic/minimal-b.bundle",
|
||||
"synthetic/catalog.json"
|
||||
]
|
||||
}"#;
|
||||
|
||||
@@ -195,4 +281,61 @@ mod tests {
|
||||
ResourceType::AssetBundle
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_parse_entry_catalog_resources_and_metadata() {
|
||||
let driver = AddressablesCatalogDriver::new();
|
||||
|
||||
let catalog_json = r#"{
|
||||
"m_LocatorId": "AddressablesMainContentCatalog",
|
||||
"m_InternalIdPrefixes": ["https://synthetic.invalid/bundles/"],
|
||||
"m_InternalIds": ["synthetic/fallback.bundle"],
|
||||
"m_KeyDataString": "key-data",
|
||||
"m_EntryDataString": "entry-data",
|
||||
"m_Entries": [
|
||||
{
|
||||
"internal_id": "synthetic/minimal.bundle",
|
||||
"hash": "synthetic-entry-hash",
|
||||
"size": 119
|
||||
},
|
||||
{
|
||||
"internal_id": "synthetic/catalog.json",
|
||||
"hash": "synthetic-catalog-hash",
|
||||
"size": 2
|
||||
}
|
||||
]
|
||||
}"#;
|
||||
|
||||
let manifest = driver.parse(catalog_json.as_bytes()).await.unwrap();
|
||||
|
||||
assert_eq!(manifest.resources.len(), 2);
|
||||
assert_eq!(manifest.resources[0].path, "synthetic/minimal.bundle");
|
||||
assert_eq!(manifest.resources[0].hash, "synthetic-entry-hash");
|
||||
assert_eq!(manifest.resources[0].size, 119);
|
||||
assert_eq!(
|
||||
manifest.resources[0].resource_type,
|
||||
ResourceType::AssetBundle
|
||||
);
|
||||
assert_eq!(manifest.resources[1].resource_type, ResourceType::Manifest);
|
||||
assert_eq!(
|
||||
manifest.metadata.cdn_prefixes,
|
||||
vec!["https://synthetic.invalid/bundles/".to_string()]
|
||||
);
|
||||
assert_eq!(
|
||||
manifest.metadata.extra.get("internal_id_count"),
|
||||
Some(&"1".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
manifest.metadata.extra.get("entry_count"),
|
||||
Some(&"2".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
manifest.metadata.extra.get("key_data_string_len"),
|
||||
Some(&"8".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
manifest.metadata.extra.get("entry_data_string_len"),
|
||||
Some(&"10".to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user