use helix_core::effect::Effect;
pub fn emit_read_result(req_id: &str, raw_body: &[u8]) -> Effect {
let body: serde_json::Value = serde_json::from_slice(raw_body).unwrap_or_else(|_| {
serde_json::Value::String(String::from_utf8_lossy(raw_body).into_owned())
});
emit_read_body(req_id, body)
}
pub fn emit_read_body(req_id: &str, body: serde_json::Value) -> Effect {
emit_read(serde_json::json!({ "req_id": req_id, "body": body }))
}
pub fn emit_read_error(req_id: &str, error: &str) -> Effect {
emit_read(serde_json::json!({ "req_id": req_id, "error": error }))
}
fn emit_read(data: serde_json::Value) -> Effect {
crate::event::MessageV3Event::new("im:read:result", data)
.expect("emit_read: data is always an object")
.into_effect()
}
pub(crate) fn read_req_id(payload: &[u8]) -> Option<String> {
let v: serde_json::Value = serde_json::from_slice(payload).ok()?;
v.get("req_id")
.and_then(serde_json::Value::as_str)
.filter(|s| !s.is_empty())
.map(str::to_string)
}
#[cfg(test)]
mod tests {
use super::*;
fn emit_json(e: Effect) -> serde_json::Value {
match e {
Effect::Emit { event } => serde_json::from_slice(event.0.as_ref()).unwrap(),
_ => panic!("expected Emit"),
}
}
#[test]
fn read_result_uses_canonical_event_first_envelope() {
let Effect::Emit { event } = emit_read_body("rq-prefix", serde_json::json!({})) else {
panic!("expected Emit");
};
assert!(event
.0
.starts_with(b"{\"event\":\"im:read:result\",\"data\":"));
}
#[test]
fn read_result_passes_body_through_verbatim() {
let raw = serde_json::to_vec(&serde_json::json!({ "status": "SUCCESS", "data": [1, 2] }))
.unwrap();
let v = emit_json(emit_read_result("rq-1", &raw));
assert_eq!(v["event"], "im:read:result");
assert_eq!(v["data"]["req_id"], "rq-1");
assert_eq!(v["data"]["body"]["status"], "SUCCESS");
assert_eq!(v["data"]["body"]["data"][1], 2);
assert!(v["data"].get("error").is_none());
}
#[test]
fn read_result_non_json_body_degrades_to_string() {
let v = emit_json(emit_read_result("rq-2", b"plain text not json"));
assert_eq!(v["data"]["body"], "plain text not json");
}
#[test]
fn read_error_keeps_req_id_and_no_body() {
let v = emit_json(emit_read_error("rq-3", "http request failed"));
assert_eq!(v["event"], "im:read:result");
assert_eq!(v["data"]["req_id"], "rq-3");
assert_eq!(v["data"]["error"], "http request failed");
assert!(v["data"].get("body").is_none());
}
}