mirror of
https://github.com/StarCitizenToolBox/app.git
synced 2026-01-13 19:50:28 +00:00
feat: unp4k supper search support
This commit is contained in:
parent
83c0fa6a26
commit
3fd020b8b0
@ -63,13 +63,8 @@ Future<String> dcbRecordToXmlByIndex({required BigInt index}) =>
|
||||
RustLib.instance.api.crateApiUnp4KApiDcbRecordToXmlByIndex(index: index);
|
||||
|
||||
/// 全文搜索 DCB 记录
|
||||
Future<List<DcbSearchResult>> dcbSearchAll({
|
||||
required String query,
|
||||
required BigInt maxResults,
|
||||
}) => RustLib.instance.api.crateApiUnp4KApiDcbSearchAll(
|
||||
query: query,
|
||||
maxResults: maxResults,
|
||||
);
|
||||
Future<List<DcbSearchResult>> dcbSearchAll({required String query}) =>
|
||||
RustLib.instance.api.crateApiUnp4KApiDcbSearchAll(query: query);
|
||||
|
||||
/// 导出 DCB 到磁盘
|
||||
/// merge: true = 合并为单个 XML,false = 分离为多个 XML 文件
|
||||
|
||||
@ -116,7 +116,6 @@ abstract class RustLibApi extends BaseApi {
|
||||
|
||||
Future<List<DcbSearchResult>> crateApiUnp4KApiDcbSearchAll({
|
||||
required String query,
|
||||
required BigInt maxResults,
|
||||
});
|
||||
|
||||
Future<List<String>> crateApiHttpApiDnsLookupIps({required String host});
|
||||
@ -693,35 +692,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
@override
|
||||
Future<List<DcbSearchResult>> crateApiUnp4KApiDcbSearchAll({
|
||||
required String query,
|
||||
required BigInt maxResults,
|
||||
}) {
|
||||
return handler.executeNormal(
|
||||
NormalTask(
|
||||
callFfi: (port_) {
|
||||
var arg0 = cst_encode_String(query);
|
||||
var arg1 = cst_encode_usize(maxResults);
|
||||
return wire.wire__crate__api__unp4k_api__dcb_search_all(
|
||||
port_,
|
||||
arg0,
|
||||
arg1,
|
||||
);
|
||||
return wire.wire__crate__api__unp4k_api__dcb_search_all(port_, arg0);
|
||||
},
|
||||
codec: DcoCodec(
|
||||
decodeSuccessData: dco_decode_list_dcb_search_result,
|
||||
decodeErrorData: dco_decode_AnyhowException,
|
||||
),
|
||||
constMeta: kCrateApiUnp4KApiDcbSearchAllConstMeta,
|
||||
argValues: [query, maxResults],
|
||||
argValues: [query],
|
||||
apiImpl: this,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TaskConstMeta get kCrateApiUnp4KApiDcbSearchAllConstMeta =>
|
||||
const TaskConstMeta(
|
||||
debugName: "dcb_search_all",
|
||||
argNames: ["query", "maxResults"],
|
||||
);
|
||||
const TaskConstMeta(debugName: "dcb_search_all", argNames: ["query"]);
|
||||
|
||||
@override
|
||||
Future<List<String>> crateApiHttpApiDnsLookupIps({required String host}) {
|
||||
|
||||
@ -1450,13 +1450,8 @@ class RustLibWire implements BaseWire {
|
||||
void wire__crate__api__unp4k_api__dcb_search_all(
|
||||
int port_,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict> query,
|
||||
int max_results,
|
||||
) {
|
||||
return _wire__crate__api__unp4k_api__dcb_search_all(
|
||||
port_,
|
||||
query,
|
||||
max_results,
|
||||
);
|
||||
return _wire__crate__api__unp4k_api__dcb_search_all(port_, query);
|
||||
}
|
||||
|
||||
late final _wire__crate__api__unp4k_api__dcb_search_allPtr =
|
||||
@ -1465,7 +1460,6 @@ class RustLibWire implements BaseWire {
|
||||
ffi.Void Function(
|
||||
ffi.Int64,
|
||||
ffi.Pointer<wire_cst_list_prim_u_8_strict>,
|
||||
ffi.UintPtr,
|
||||
)
|
||||
>
|
||||
>(
|
||||
@ -1474,7 +1468,7 @@ class RustLibWire implements BaseWire {
|
||||
late final _wire__crate__api__unp4k_api__dcb_search_all =
|
||||
_wire__crate__api__unp4k_api__dcb_search_allPtr
|
||||
.asFunction<
|
||||
void Function(int, ffi.Pointer<wire_cst_list_prim_u_8_strict>, int)
|
||||
void Function(int, ffi.Pointer<wire_cst_list_prim_u_8_strict>)
|
||||
>();
|
||||
|
||||
void wire__crate__api__http_api__dns_lookup_ips(
|
||||
|
||||
@ -261,7 +261,7 @@ class DcbViewerModel extends _$DcbViewerModel {
|
||||
state = state.copyWith(isSearching: true, fullTextSearchQuery: query, viewMode: DcbViewMode.searchResults);
|
||||
|
||||
try {
|
||||
final apiResults = await unp4k_api.dcbSearchAll(query: query, maxResults: BigInt.from(1000000));
|
||||
final apiResults = await unp4k_api.dcbSearchAll(query: query);
|
||||
|
||||
// 转换为本地数据类型
|
||||
final results = apiResults.map((r) {
|
||||
|
||||
@ -41,7 +41,7 @@ final class DcbViewerModelProvider
|
||||
}
|
||||
}
|
||||
|
||||
String _$dcbViewerModelHash() => r'94c3542282f64917efadbe14a0ee4967220bec77';
|
||||
String _$dcbViewerModelHash() => r'f0af2a7b4451f746288e2c9565a418af80f58835';
|
||||
|
||||
abstract class _$DcbViewerModel extends $Notifier<DcbViewerState> {
|
||||
DcbViewerState build();
|
||||
|
||||
1
rust/Cargo.lock
generated
1
rust/Cargo.lock
generated
@ -4916,6 +4916,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"ort",
|
||||
"parking_lot",
|
||||
"rayon",
|
||||
"reqwest",
|
||||
"scopeguard",
|
||||
"serde",
|
||||
|
||||
@ -34,6 +34,7 @@ serde = { version = "1.0.228", features = ["derive"] }
|
||||
unp4k_rs = { git = "https://github.com/StarCitizenToolBox/unp4k_rs", rev = "29430002d6f3a8d87feabac26c03ae0311c81263" }
|
||||
#unp4k_rs = { path = "../../unp4k_rs" }
|
||||
uuid = { version = "1.19.0", features = ["v4"] }
|
||||
rayon = "1.10"
|
||||
parking_lot = "0.12.5"
|
||||
crossbeam-channel = "0.5.15"
|
||||
librqbit = { git = "https://github.com/StarCitizenToolBox/rqbit", rev = "f8c0b0927904e1d8b0e28e708bd69fd8069d413a" }
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use flutter_rust_bridge::frb;
|
||||
use rayon::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex};
|
||||
@ -329,7 +330,7 @@ pub struct DcbSearchMatch {
|
||||
}
|
||||
|
||||
/// 全文搜索 DCB 记录
|
||||
pub async fn dcb_search_all(query: String, max_results: usize) -> Result<Vec<DcbSearchResult>> {
|
||||
pub async fn dcb_search_all(query: String) -> Result<Vec<DcbSearchResult>> {
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let reader = GLOBAL_DCB_READER.lock().unwrap();
|
||||
let df = reader
|
||||
@ -337,48 +338,58 @@ pub async fn dcb_search_all(query: String, max_results: usize) -> Result<Vec<Dcb
|
||||
.ok_or_else(|| anyhow!("DCB reader not initialized"))?;
|
||||
|
||||
let query_lower = query.to_lowercase();
|
||||
let mut results = Vec::new();
|
||||
|
||||
for (path, &index) in df.path_to_record() {
|
||||
if results.len() >= max_results {
|
||||
break;
|
||||
}
|
||||
// 收集所有记录路径和索引
|
||||
let records: Vec<(String, usize)> = df
|
||||
.path_to_record()
|
||||
.iter()
|
||||
.map(|(path, &index)| (path.clone(), index))
|
||||
.collect();
|
||||
|
||||
// 先检查路径是否匹配
|
||||
let path_matches = path.to_lowercase().contains(&query_lower);
|
||||
// 使用 rayon 并发搜索
|
||||
let mut results: Vec<DcbSearchResult> = records
|
||||
.par_iter()
|
||||
.filter_map(|(path, index)| {
|
||||
// 先检查路径是否匹配
|
||||
let path_matches = path.to_lowercase().contains(&query_lower);
|
||||
|
||||
// 尝试获取 XML 并搜索内容
|
||||
if let Ok(xml) = df.record_to_xml_by_index(index, true) {
|
||||
let mut matches = Vec::new();
|
||||
// 尝试获取 XML 并搜索内容
|
||||
if let Ok(xml) = df.record_to_xml_by_index(*index, true) {
|
||||
let mut matches = Vec::new();
|
||||
|
||||
for (line_num, line) in xml.lines().enumerate() {
|
||||
if line.to_lowercase().contains(&query_lower) {
|
||||
let line_content = if line.len() > 200 {
|
||||
format!("{}...", &line[..200])
|
||||
} else {
|
||||
line.to_string()
|
||||
};
|
||||
matches.push(DcbSearchMatch {
|
||||
line_number: line_num + 1,
|
||||
line_content,
|
||||
});
|
||||
for (line_num, line) in xml.lines().enumerate() {
|
||||
if line.to_lowercase().contains(&query_lower) {
|
||||
let line_content = if line.len() > 200 {
|
||||
format!("{}...", &line[..200])
|
||||
} else {
|
||||
line.to_string()
|
||||
};
|
||||
matches.push(DcbSearchMatch {
|
||||
line_number: line_num + 1,
|
||||
line_content,
|
||||
});
|
||||
|
||||
// 每条记录最多保留 5 个匹配
|
||||
if matches.len() >= 5 {
|
||||
break;
|
||||
// 每条记录最多保留 5 个匹配
|
||||
if matches.len() >= 5 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if path_matches || !matches.is_empty() {
|
||||
results.push(DcbSearchResult {
|
||||
path: path.clone(),
|
||||
index,
|
||||
matches,
|
||||
});
|
||||
if path_matches || !matches.is_empty() {
|
||||
return Some(DcbSearchResult {
|
||||
path: path.clone(),
|
||||
index: *index,
|
||||
matches,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.collect();
|
||||
|
||||
// 按路径排序以保持结果稳定性
|
||||
results.sort_by(|a, b| a.path.cmp(&b.path));
|
||||
|
||||
Ok(results)
|
||||
})
|
||||
|
||||
@ -332,7 +332,6 @@ fn wire__crate__api__unp4k_api__dcb_record_to_xml_by_index_impl(
|
||||
fn wire__crate__api__unp4k_api__dcb_search_all_impl(
|
||||
port_: flutter_rust_bridge::for_generated::MessagePort,
|
||||
query: impl CstDecode<String>,
|
||||
max_results: impl CstDecode<usize>,
|
||||
) {
|
||||
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::DcoCodec, _, _, _>(
|
||||
flutter_rust_bridge::for_generated::TaskInfo {
|
||||
@ -342,13 +341,10 @@ fn wire__crate__api__unp4k_api__dcb_search_all_impl(
|
||||
},
|
||||
move || {
|
||||
let api_query = query.cst_decode();
|
||||
let api_max_results = max_results.cst_decode();
|
||||
move |context| async move {
|
||||
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
|
||||
(move || async move {
|
||||
let output_ok =
|
||||
crate::api::unp4k_api::dcb_search_all(api_query, api_max_results)
|
||||
.await?;
|
||||
let output_ok = crate::api::unp4k_api::dcb_search_all(api_query).await?;
|
||||
Ok(output_ok)
|
||||
})()
|
||||
.await,
|
||||
@ -4649,9 +4645,8 @@ mod io {
|
||||
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__unp4k_api__dcb_search_all(
|
||||
port_: i64,
|
||||
query: *mut wire_cst_list_prim_u_8_strict,
|
||||
max_results: usize,
|
||||
) {
|
||||
wire__crate__api__unp4k_api__dcb_search_all_impl(port_, query, max_results)
|
||||
wire__crate__api__unp4k_api__dcb_search_all_impl(port_, query)
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user