use std::cell::RefCell;
pub struct SerBuffer;
thread_local! {
static BUFFER: RefCell<Vec<u8>> = RefCell::new(Vec::with_capacity(1024));
}
impl SerBuffer {
pub fn serialize<T: serde::Serialize>(value: &T) -> Result<Vec<u8>, serde_json::Error> {
BUFFER.with(|buf| {
let mut buf = buf.borrow_mut();
buf.clear();
serde_json::to_writer(&mut *buf, value)?;
Ok(buf.clone())
})
}
pub fn serialize_into<T: serde::Serialize, W: std::io::Write>(
writer: W,
value: &T,
) -> Result<(), serde_json::Error> {
serde_json::to_writer(writer, value)
}
}
pub fn deser_from_str<'a, T: serde::Deserialize<'a>>(s: &'a str) -> Result<T, serde_json::Error> {
serde_json::from_str(s)
}
pub fn deser_from_slice<'a, T: serde::Deserialize<'a>>(
bytes: &'a [u8],
) -> Result<T, serde_json::Error> {
std::str::from_utf8(bytes).map_or_else(|_| serde_json::from_slice(bytes), serde_json::from_str)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::message::Part;
use crate::task::{ContextId, Task, TaskId, TaskState, TaskStatus};
#[test]
fn ser_buffer_roundtrip() {
let part = Part::text("hello world");
let bytes = SerBuffer::serialize(&part).expect("serialize");
let json = std::str::from_utf8(&bytes).expect("utf8");
assert!(json.contains("\"text\":\"hello world\""));
}
#[test]
fn ser_buffer_reuses_allocation() {
let part1 = Part::text("first");
let _ = SerBuffer::serialize(&part1).expect("first");
let part2 = Part::text("second");
let bytes = SerBuffer::serialize(&part2).expect("second");
let json = std::str::from_utf8(&bytes).expect("utf8");
assert!(json.contains("\"text\":\"second\""));
}
#[test]
fn deser_from_str_works() {
let json = r#"{"text":"hello"}"#;
let part: Part = deser_from_str(json).expect("deser");
assert_eq!(part.text_content(), Some("hello"));
}
#[test]
fn deser_from_slice_works() {
let json = br#"{"text":"hello"}"#;
let part: Part = deser_from_slice(json).expect("deser");
assert_eq!(part.text_content(), Some("hello"));
}
#[test]
fn deser_from_str_task() {
let task = Task {
id: TaskId::new("t1"),
context_id: ContextId::new("c1"),
status: TaskStatus::new(TaskState::Working),
history: None,
artifacts: None,
metadata: None,
};
let json = serde_json::to_string(&task).expect("ser");
let back: Task = deser_from_str(&json).expect("deser");
assert_eq!(back.id, TaskId::new("t1"));
}
#[test]
fn serialize_into_writer() {
let part = Part::text("direct");
let mut buf = Vec::new();
SerBuffer::serialize_into(&mut buf, &part).expect("serialize_into");
let json = std::str::from_utf8(&buf).expect("utf8");
assert!(json.contains("\"text\":\"direct\""));
}
}