use fandhe_backend_http::response::Response;
const MAX_RETAINED_CAPACITY: usize = 64 * 1024;
#[derive(Debug, Default)]
pub(crate) struct SendBuffer {
buf: Vec<u8>,
}
impl SendBuffer {
pub(crate) fn new() -> Self {
Self { buf: Vec::new() }
}
pub(crate) fn serialize_response(&mut self, response: &Response, keep_alive: bool) -> &[u8] {
response.serialize_into(keep_alive, &mut self.buf);
&self.buf
}
pub(crate) fn shrink_if_oversized(&mut self) {
if self.buf.capacity() <= MAX_RETAINED_CAPACITY {
return;
}
self.buf.clear();
self.buf.shrink_to(MAX_RETAINED_CAPACITY);
}
#[cfg(test)]
pub(crate) fn capacity(&self) -> usize {
self.buf.capacity()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn send_buffer_new_has_zero_capacity() {
let buf = SendBuffer::new();
assert_eq!(buf.capacity(), 0);
}
#[test]
fn send_buffer_serialize_response_matches_response_serialize() {
let mut send_buf = SendBuffer::new();
let res = Response::new(200, b"payload".to_vec());
let wire = send_buf.serialize_response(&res, true).to_vec();
assert_eq!(wire, res.serialize(true));
}
#[test]
fn send_buffer_reuses_capacity_across_two_responses_without_stale_bytes() {
let mut send_buf = SendBuffer::new();
let first = Response::new(200, b"first response".to_vec());
let second = Response::empty(404);
let first_wire = send_buf.serialize_response(&first, true).to_vec();
assert_eq!(first_wire, first.serialize(true));
let cap_after_first = send_buf.capacity();
assert!(cap_after_first > 0);
let second_wire = send_buf.serialize_response(&second, true).to_vec();
assert_eq!(second_wire, second.serialize(true));
assert_eq!(send_buf.capacity(), cap_after_first);
}
#[test]
fn send_buffer_shrink_if_oversized_shrinks_large_capacity() {
let mut send_buf = SendBuffer::new();
let big_body = vec![0xabu8; MAX_RETAINED_CAPACITY * 2];
let res = Response::new(200, big_body);
send_buf.serialize_response(&res, true);
assert!(send_buf.capacity() > MAX_RETAINED_CAPACITY);
send_buf.shrink_if_oversized();
assert!(send_buf.capacity() <= MAX_RETAINED_CAPACITY);
}
#[test]
fn send_buffer_shrink_if_oversized_keeps_capacity_at_or_below_threshold_untouched() {
let mut send_buf = SendBuffer::new();
let res = Response::new(200, b"small".to_vec());
send_buf.serialize_response(&res, true);
let cap_before = send_buf.capacity();
assert!(cap_before <= MAX_RETAINED_CAPACITY);
send_buf.shrink_if_oversized();
assert_eq!(send_buf.capacity(), cap_before);
}
}