use serde_json::{Map, Value as JsonValue};
use crate::bridge::envelope::PhysicalPlan;
use crate::data::executor::response_codec::decode_payload_to_json;
use nodedb_physical::physical_plan::KvOp;
use nodedb_query::msgpack_scan;
pub fn apply_kv_wrap(plan: &PhysicalPlan, payload: &[u8]) -> Vec<u8> {
if payload.is_empty() {
return payload.to_vec();
}
match plan {
PhysicalPlan::Kv(KvOp::Get { key, .. }) => wrap_single_get(key, payload),
PhysicalPlan::Kv(KvOp::BatchGet { keys, .. }) => wrap_batch_get(keys, payload),
_ => payload.to_vec(),
}
}
fn wrap_single_get(key: &[u8], payload: &[u8]) -> Vec<u8> {
let key_str = String::from_utf8_lossy(key);
if msgpack_scan::map_header(payload, 0).is_some() {
msgpack_scan::inject_str_field(payload, "key", &key_str)
} else {
let mut buf = Vec::with_capacity(payload.len() + key_str.len() + 16);
msgpack_scan::write_map_header(&mut buf, 2);
msgpack_scan::write_str(&mut buf, "key");
msgpack_scan::write_str(&mut buf, &key_str);
msgpack_scan::write_str(&mut buf, "value");
msgpack_scan::write_str(&mut buf, &String::from_utf8_lossy(payload));
buf
}
}
fn wrap_batch_get(keys: &[Vec<u8>], payload: &[u8]) -> Vec<u8> {
let decoded = decode_payload_to_json(payload);
let Ok(JsonValue::Array(values)) = sonic_rs::from_str::<JsonValue>(&decoded) else {
return payload.to_vec();
};
let rows: Vec<JsonValue> = keys
.iter()
.zip(values)
.map(|(key, value)| {
let mut row = Map::new();
row.insert(
"key".to_string(),
JsonValue::String(String::from_utf8_lossy(key).into_owned()),
);
row.insert("value".to_string(), value);
JsonValue::Object(row)
})
.collect();
nodedb_types::json_to_msgpack(&JsonValue::Array(rows)).unwrap_or_else(|_| payload.to_vec())
}