use std::io::{self, Write};
use super::framing::{Len, frame_len};
use crate::Schema;
use crate::binary::Writer;
use crate::frame::Packer;
#[derive(Debug, Default)]
pub struct FrameWriter {
named: Writer,
packer: Packer,
packed: Vec<u8>,
}
impl FrameWriter {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn send<T: Schema>(&mut self, w: &mut impl Write, message: &T) -> io::Result<()> {
let frame = self.named_frame(message)?;
w.write_all(frame)?;
w.flush()
}
pub fn send_packed<T: Schema>(&mut self, w: &mut impl Write, message: &T) -> io::Result<()> {
let frame = self.packed_frame(message)?;
w.write_all(frame)?;
w.flush()
}
pub(super) fn named_frame<T: Schema>(&mut self, message: &T) -> io::Result<&[u8]> {
self.named.restart(size_of::<Len>());
message.encode(&mut self.named);
with_len(self.named.buffer_mut())
}
pub(super) fn packed_frame<T: Schema>(&mut self, message: &T) -> io::Result<&[u8]> {
let packed = &mut self.packed;
packed.clear();
packed.extend_from_slice(&[0; size_of::<Len>()]);
self.packer
.with_frame(message, |frame| packed.extend_from_slice(frame));
with_len(packed)
}
}
fn with_len(buf: &mut [u8]) -> io::Result<&[u8]> {
let (len, body) = buf.split_at_mut(size_of::<Len>());
len.copy_from_slice(&frame_len(body.len())?.to_le_bytes());
Ok(buf)
}