mirror of
https://github.com/StarCitizenToolBox/app.git
synced 2026-01-14 12:10: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);
|
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 = 合并为单个 XML,false = 分离为多个 XML 文件
|
/// merge: true = 合并为单个 XML,false = 分离为多个 XML 文件
|
||||||
|
|||||||
@ -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}) {
|
||||||
|
|||||||
@ -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(
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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
1
rust/Cargo.lock
generated
@ -4916,6 +4916,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"ort",
|
"ort",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"rayon",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"scopeguard",
|
"scopeguard",
|
||||||
"serde",
|
"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 = { 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" }
|
||||||
|
|||||||
@ -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)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -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)]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user