use bytes::{BufMut, BytesMut};
use tokio_util::codec::{Decoder, Encoder};
use crate::frame::{encode_frame, try_decode_frame};
use crate::types::{Frame, VstpError};
pub struct VstpFrameCodec {
max_frame_size: usize,
}
impl VstpFrameCodec {
pub fn new(max_frame_size: usize) -> Self {
Self { max_frame_size }
}
pub fn default() -> Self {
Self::new(8 * 1024 * 1024) }
}
impl Decoder for VstpFrameCodec {
type Item = Frame;
type Error = VstpError;
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
try_decode_frame(src, self.max_frame_size)
}
}
impl Encoder<Frame> for VstpFrameCodec {
type Error = VstpError;
fn encode(&mut self, item: Frame, dst: &mut BytesMut) -> Result<(), Self::Error> {
let encoded = encode_frame(&item)?;
dst.put_slice(&encoded);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::{Frame, FrameType};
#[test]
fn test_codec_roundtrip() {
let mut codec = VstpFrameCodec::default();
let mut buf = BytesMut::new();
let frame = Frame::new(FrameType::Data)
.with_header("test", "value")
.with_payload(b"hello".to_vec());
codec.encode(frame.clone(), &mut buf).unwrap();
let decoded = codec.decode(&mut buf).unwrap().unwrap();
assert_eq!(frame, decoded);
}
#[test]
fn test_codec_partial_decode() {
let mut codec = VstpFrameCodec::default();
let mut buf = BytesMut::new();
let frame = Frame::new(FrameType::Hello);
let encoded = encode_frame(&frame).unwrap();
buf.put_slice(&encoded[..5]);
let result = codec.decode(&mut buf).unwrap();
assert!(result.is_none());
buf.put_slice(&encoded[5..]);
let decoded = codec.decode(&mut buf).unwrap().unwrap();
assert_eq!(frame, decoded);
}
}