use tokio::io::{AsyncWrite, AsyncWriteExt};
use crate::error::BoltError;
const MAX_CHUNK_SIZE: usize = 65535;
pub struct ChunkWriter<W> {
writer: W,
max_chunk_size: usize,
}
impl<W: AsyncWrite + Unpin> ChunkWriter<W> {
pub fn new(writer: W) -> Self {
Self {
writer,
max_chunk_size: MAX_CHUNK_SIZE,
}
}
pub async fn write_message(&mut self, data: &[u8]) -> Result<(), BoltError> {
let mut offset = 0;
while offset < data.len() {
let end = (offset + self.max_chunk_size).min(data.len());
let chunk = &data[offset..end];
let len = chunk.len() as u16;
self.writer.write_all(&len.to_be_bytes()).await?;
self.writer.write_all(chunk).await?;
offset = end;
}
self.writer.write_all(&[0x00, 0x00]).await?;
Ok(())
}
pub async fn flush(&mut self) -> Result<(), BoltError> {
self.writer.flush().await?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn write_small_message() {
let mut output = Vec::new();
let mut writer = ChunkWriter::new(&mut output);
writer.write_message(&[0x01, 0x02, 0x03]).await.unwrap();
assert_eq!(
output,
vec![
0x00, 0x03, 0x01, 0x02, 0x03, 0x00, 0x00, ]
);
}
#[tokio::test]
async fn write_empty_message() {
let mut output = Vec::new();
let mut writer = ChunkWriter::new(&mut output);
writer.write_message(&[]).await.unwrap();
assert_eq!(output, vec![0x00, 0x00]);
}
}