Skip to main content

futu_backend/
search.rs

1use bytes::Bytes;
2use prost::Message as _;
3
4use futu_command_spec::SystemReadOperation;
5use futu_core::error::{FutuError, Result};
6use futu_domain_qot_search::SearchRequestPlan;
7
8use crate::command_runtime::execute_system_read;
9use crate::conn::BackendConn;
10use crate::proto_internal::global_search_entry::{
11    GetSearchResultRequest, GetSearchResultResponse, SceneContext, SearchParams, UserContext,
12};
13
14pub fn build_global_search_request(plan: &SearchRequestPlan) -> GetSearchResultRequest {
15    GetSearchResultRequest {
16        search_params: Some(SearchParams {
17            keyword: Some(plan.keyword.clone()),
18            size: Some(plan.size),
19            sort_type: Some(plan.sort_type),
20        }),
21        user_context: Some(UserContext {
22            union_id: Some(plan.union_id.clone()),
23            pvid: None,
24            broker_id_list: plan.broker_ids.clone(),
25        }),
26        scene_context: Some(SceneContext {
27            page_source: Some(plan.page_source),
28            sub_page_source: None,
29            main_tab_id: Some(plan.main_tab_id),
30            sub_tab_id: Some(plan.sub_tab_id),
31            stock_id: None,
32            uid: None,
33            web_source_url: None,
34        }),
35        order_mark: None,
36        keyword_source: None,
37    }
38}
39
40pub async fn pull_global_search(
41    backend: &BackendConn,
42    plan: &SearchRequestPlan,
43) -> Result<GetSearchResultResponse> {
44    let request = build_global_search_request(plan);
45    let response = execute_system_read(
46        backend,
47        SystemReadOperation::GlobalSearch,
48        Bytes::from(request.encode_to_vec()),
49    )
50    .await?;
51    decode_global_search_response(response.body.as_ref())
52}
53
54pub fn decode_global_search_response(body: &[u8]) -> Result<GetSearchResultResponse> {
55    let response = GetSearchResultResponse::decode(body).map_err(FutuError::Proto)?;
56    match response.code {
57        Some(0) => Ok(response),
58        Some(code) => Err(FutuError::ServerError {
59            ret_type: code,
60            msg: response
61                .message
62                .clone()
63                .unwrap_or_else(|| "global search backend rejected request".to_string()),
64        }),
65        None => Err(FutuError::Codec(
66            "global search backend response missing code".to_string(),
67        )),
68    }
69}
70
71#[cfg(test)]
72#[path = "search/tests.rs"]
73mod tests;