feat: unp4k supper search support

This commit is contained in:
xkeyC 2025-12-11 00:54:30 +08:00
parent 83c0fa6a26
commit 3fd020b8b0
9 changed files with 58 additions and 71 deletions

View File

@ -63,13 +63,8 @@ Future<String> dcbRecordToXmlByIndex({required BigInt index}) =>
RustLib.instance.api.crateApiUnp4KApiDcbRecordToXmlByIndex(index: index); RustLib.instance.api.crateApiUnp4KApiDcbRecordToXmlByIndex(index: index);
/// DCB /// DCB
Future<List<DcbSearchResult>> dcbSearchAll({ Future<List<DcbSearchResult>> dcbSearchAll({required String query}) =>
required String query, RustLib.instance.api.crateApiUnp4KApiDcbSearchAll(query: query);
required BigInt maxResults,
}) => RustLib.instance.api.crateApiUnp4KApiDcbSearchAll(
query: query,
maxResults: maxResults,
);
/// DCB /// DCB
/// merge: true = XMLfalse = XML /// merge: true = XMLfalse = XML

View File

@ -116,7 +116,6 @@ abstract class RustLibApi extends BaseApi {
Future<List<DcbSearchResult>> crateApiUnp4KApiDcbSearchAll({ Future<List<DcbSearchResult>> crateApiUnp4KApiDcbSearchAll({
required String query, required String query,
required BigInt maxResults,
}); });
Future<List<String>> crateApiHttpApiDnsLookupIps({required String host}); Future<List<String>> crateApiHttpApiDnsLookupIps({required String host});
@ -693,35 +692,26 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
@override @override
Future<List<DcbSearchResult>> crateApiUnp4KApiDcbSearchAll({ Future<List<DcbSearchResult>> crateApiUnp4KApiDcbSearchAll({
required String query, required String query,
required BigInt maxResults,
}) { }) {
return handler.executeNormal( return handler.executeNormal(
NormalTask( NormalTask(
callFfi: (port_) { callFfi: (port_) {
var arg0 = cst_encode_String(query); var arg0 = cst_encode_String(query);
var arg1 = cst_encode_usize(maxResults); return wire.wire__crate__api__unp4k_api__dcb_search_all(port_, arg0);
return wire.wire__crate__api__unp4k_api__dcb_search_all(
port_,
arg0,
arg1,
);
}, },
codec: DcoCodec( codec: DcoCodec(
decodeSuccessData: dco_decode_list_dcb_search_result, decodeSuccessData: dco_decode_list_dcb_search_result,
decodeErrorData: dco_decode_AnyhowException, decodeErrorData: dco_decode_AnyhowException,
), ),
constMeta: kCrateApiUnp4KApiDcbSearchAllConstMeta, constMeta: kCrateApiUnp4KApiDcbSearchAllConstMeta,
argValues: [query, maxResults], argValues: [query],
apiImpl: this, apiImpl: this,
), ),
); );
} }
TaskConstMeta get kCrateApiUnp4KApiDcbSearchAllConstMeta => TaskConstMeta get kCrateApiUnp4KApiDcbSearchAllConstMeta =>
const TaskConstMeta( const TaskConstMeta(debugName: "dcb_search_all", argNames: ["query"]);
debugName: "dcb_search_all",
argNames: ["query", "maxResults"],
);
@override @override
Future<List<String>> crateApiHttpApiDnsLookupIps({required String host}) { Future<List<String>> crateApiHttpApiDnsLookupIps({required String host}) {

View File

@ -1450,13 +1450,8 @@ class RustLibWire implements BaseWire {
void wire__crate__api__unp4k_api__dcb_search_all( void wire__crate__api__unp4k_api__dcb_search_all(
int port_, int port_,
ffi.Pointer<wire_cst_list_prim_u_8_strict> query, ffi.Pointer<wire_cst_list_prim_u_8_strict> query,
int max_results,
) { ) {
return _wire__crate__api__unp4k_api__dcb_search_all( return _wire__crate__api__unp4k_api__dcb_search_all(port_, query);
port_,
query,
max_results,
);
} }
late final _wire__crate__api__unp4k_api__dcb_search_allPtr = late final _wire__crate__api__unp4k_api__dcb_search_allPtr =
@ -1465,7 +1460,6 @@ class RustLibWire implements BaseWire {
ffi.Void Function( ffi.Void Function(
ffi.Int64, ffi.Int64,
ffi.Pointer<wire_cst_list_prim_u_8_strict>, 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 = late final _wire__crate__api__unp4k_api__dcb_search_all =
_wire__crate__api__unp4k_api__dcb_search_allPtr _wire__crate__api__unp4k_api__dcb_search_allPtr
.asFunction< .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( void wire__crate__api__http_api__dns_lookup_ips(

View File

@ -261,7 +261,7 @@ class DcbViewerModel extends _$DcbViewerModel {
state = state.copyWith(isSearching: true, fullTextSearchQuery: query, viewMode: DcbViewMode.searchResults); state = state.copyWith(isSearching: true, fullTextSearchQuery: query, viewMode: DcbViewMode.searchResults);
try { 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) { final results = apiResults.map((r) {

View File

@ -41,7 +41,7 @@ final class DcbViewerModelProvider
} }
} }
String _$dcbViewerModelHash() => r'94c3542282f64917efadbe14a0ee4967220bec77'; String _$dcbViewerModelHash() => r'f0af2a7b4451f746288e2c9565a418af80f58835';
abstract class _$DcbViewerModel extends $Notifier<DcbViewerState> { abstract class _$DcbViewerModel extends $Notifier<DcbViewerState> {
DcbViewerState build(); DcbViewerState build();

1
rust/Cargo.lock generated
View File

@ -4916,6 +4916,7 @@ dependencies = [
"once_cell", "once_cell",
"ort", "ort",
"parking_lot", "parking_lot",
"rayon",
"reqwest", "reqwest",
"scopeguard", "scopeguard",
"serde", "serde",

View File

@ -34,6 +34,7 @@ serde = { version = "1.0.228", features = ["derive"] }
unp4k_rs = { git = "https://github.com/StarCitizenToolBox/unp4k_rs", rev = "29430002d6f3a8d87feabac26c03ae0311c81263" } unp4k_rs = { git = "https://github.com/StarCitizenToolBox/unp4k_rs", rev = "29430002d6f3a8d87feabac26c03ae0311c81263" }
#unp4k_rs = { path = "../../unp4k_rs" } #unp4k_rs = { path = "../../unp4k_rs" }
uuid = { version = "1.19.0", features = ["v4"] } uuid = { version = "1.19.0", features = ["v4"] }
rayon = "1.10"
parking_lot = "0.12.5" parking_lot = "0.12.5"
crossbeam-channel = "0.5.15" crossbeam-channel = "0.5.15"
librqbit = { git = "https://github.com/StarCitizenToolBox/rqbit", rev = "f8c0b0927904e1d8b0e28e708bd69fd8069d413a" } librqbit = { git = "https://github.com/StarCitizenToolBox/rqbit", rev = "f8c0b0927904e1d8b0e28e708bd69fd8069d413a" }

View File

@ -1,5 +1,6 @@
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use flutter_rust_bridge::frb; use flutter_rust_bridge::frb;
use rayon::prelude::*;
use std::collections::HashMap; use std::collections::HashMap;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -329,7 +330,7 @@ pub struct DcbSearchMatch {
} }
/// 全文搜索 DCB 记录 /// 全文搜索 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 || { tokio::task::spawn_blocking(move || {
let reader = GLOBAL_DCB_READER.lock().unwrap(); let reader = GLOBAL_DCB_READER.lock().unwrap();
let df = reader 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"))?; .ok_or_else(|| anyhow!("DCB reader not initialized"))?;
let query_lower = query.to_lowercase(); let query_lower = query.to_lowercase();
let mut results = Vec::new();
for (path, &index) in df.path_to_record() { // 收集所有记录路径和索引
if results.len() >= max_results { let records: Vec<(String, usize)> = df
break; .path_to_record()
} .iter()
.map(|(path, &index)| (path.clone(), index))
.collect();
// 先检查路径是否匹配 // 使用 rayon 并发搜索
let path_matches = path.to_lowercase().contains(&query_lower); let mut results: Vec<DcbSearchResult> = records
.par_iter()
.filter_map(|(path, index)| {
// 先检查路径是否匹配
let path_matches = path.to_lowercase().contains(&query_lower);
// 尝试获取 XML 并搜索内容 // 尝试获取 XML 并搜索内容
if let Ok(xml) = df.record_to_xml_by_index(index, true) { if let Ok(xml) = df.record_to_xml_by_index(*index, true) {
let mut matches = Vec::new(); let mut matches = Vec::new();
for (line_num, line) in xml.lines().enumerate() { for (line_num, line) in xml.lines().enumerate() {
if line.to_lowercase().contains(&query_lower) { if line.to_lowercase().contains(&query_lower) {
let line_content = if line.len() > 200 { let line_content = if line.len() > 200 {
format!("{}...", &line[..200]) format!("{}...", &line[..200])
} else { } else {
line.to_string() line.to_string()
}; };
matches.push(DcbSearchMatch { matches.push(DcbSearchMatch {
line_number: line_num + 1, line_number: line_num + 1,
line_content, line_content,
}); });
// 每条记录最多保留 5 个匹配 // 每条记录最多保留 5 个匹配
if matches.len() >= 5 { if matches.len() >= 5 {
break; break;
}
} }
} }
}
if path_matches || !matches.is_empty() { if path_matches || !matches.is_empty() {
results.push(DcbSearchResult { return Some(DcbSearchResult {
path: path.clone(), path: path.clone(),
index, index: *index,
matches, matches,
}); });
}
} }
} None
} })
.collect();
// 按路径排序以保持结果稳定性
results.sort_by(|a, b| a.path.cmp(&b.path));
Ok(results) Ok(results)
}) })

View File

@ -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( fn wire__crate__api__unp4k_api__dcb_search_all_impl(
port_: flutter_rust_bridge::for_generated::MessagePort, port_: flutter_rust_bridge::for_generated::MessagePort,
query: impl CstDecode<String>, query: impl CstDecode<String>,
max_results: impl CstDecode<usize>,
) { ) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::DcoCodec, _, _, _>( FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::DcoCodec, _, _, _>(
flutter_rust_bridge::for_generated::TaskInfo { flutter_rust_bridge::for_generated::TaskInfo {
@ -342,13 +341,10 @@ fn wire__crate__api__unp4k_api__dcb_search_all_impl(
}, },
move || { move || {
let api_query = query.cst_decode(); let api_query = query.cst_decode();
let api_max_results = max_results.cst_decode();
move |context| async move { move |context| async move {
transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>( transform_result_dco::<_, _, flutter_rust_bridge::for_generated::anyhow::Error>(
(move || async move { (move || async move {
let output_ok = let output_ok = crate::api::unp4k_api::dcb_search_all(api_query).await?;
crate::api::unp4k_api::dcb_search_all(api_query, api_max_results)
.await?;
Ok(output_ok) Ok(output_ok)
})() })()
.await, .await,
@ -4649,9 +4645,8 @@ mod io {
pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__unp4k_api__dcb_search_all( pub extern "C" fn frbgen_starcitizen_doctor_wire__crate__api__unp4k_api__dcb_search_all(
port_: i64, port_: i64,
query: *mut wire_cst_list_prim_u_8_strict, 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)] #[unsafe(no_mangle)]