use nodedb_types::{DatabaseId, Surrogate, TenantId};
use serde_json::Value as JsonValue;
use crate::control::state::SharedState;
use crate::data::executor::response_codec::decode_payload_to_json;
use super::vector::resolve_surrogate_pk;
const HEADLESS_SENTINEL_PREFIX: &str = "__local_";
fn parse_surrogate_hex(candidate: &str) -> Option<Surrogate> {
if candidate.starts_with(HEADLESS_SENTINEL_PREFIX) {
return None;
}
u32::from_str_radix(candidate, 16).ok().map(Surrogate::new)
}
pub fn translate_text_search_payload(
payload: &[u8],
state: &SharedState,
database_id: DatabaseId,
tenant_id: TenantId,
collection: &str,
) -> Vec<u8> {
if payload.is_empty() {
return payload.to_vec();
}
let text = decode_payload_to_json(payload);
let Ok(JsonValue::Array(mut rows)) = sonic_rs::from_str::<JsonValue>(&text) else {
return payload.to_vec();
};
for row in &mut rows {
let JsonValue::Object(map) = row else {
continue;
};
let Some(JsonValue::String(hex_id)) = map.get("id").cloned() else {
continue;
};
let data_has_id = matches!(
map.get("data"),
Some(JsonValue::Object(inner)) if inner.contains_key("id")
);
if data_has_id {
continue;
}
let Some(surrogate) = parse_surrogate_hex(&hex_id) else {
continue;
};
if let Some(pk) = resolve_surrogate_pk(state, database_id, tenant_id, collection, surrogate)
&& let Some(JsonValue::Object(inner)) = map.get_mut("data")
{
inner.insert("id".to_string(), JsonValue::String(pk));
}
}
match sonic_rs::to_string(&JsonValue::Array(rows)) {
Ok(s) => s.into_bytes(),
Err(_) => payload.to_vec(),
}
}
pub fn translate_hybrid_search_payload(
payload: &[u8],
state: &SharedState,
database_id: DatabaseId,
tenant_id: TenantId,
collection: &str,
) -> Vec<u8> {
if payload.is_empty() {
return payload.to_vec();
}
let text = decode_payload_to_json(payload);
let Ok(JsonValue::Array(mut rows)) = sonic_rs::from_str::<JsonValue>(&text) else {
return payload.to_vec();
};
for row in &mut rows {
let JsonValue::Object(map) = row else {
continue;
};
let Some(JsonValue::String(hex_id)) = map.get("doc_id").cloned() else {
continue;
};
let Some(surrogate) = parse_surrogate_hex(&hex_id) else {
continue;
};
if let Some(pk) = resolve_surrogate_pk(state, database_id, tenant_id, collection, surrogate)
{
map.insert("id".to_string(), JsonValue::String(pk));
}
}
match sonic_rs::to_string(&JsonValue::Array(rows)) {
Ok(s) => s.into_bytes(),
Err(_) => payload.to_vec(),
}
}