diff --git a/northbridge/src/framed_codec.rs b/northbridge/src/framed_codec.rs new file mode 100644 index 0000000..6a4ff2a --- /dev/null +++ b/northbridge/src/framed_codec.rs @@ -0,0 +1,55 @@ +use anyhow::anyhow; +use common::Command; +use framed::{BoxPayload, FRAME_END_SYMBOL}; +use tokio_util::{bytes::BytesMut, codec::{Decoder, Encoder}}; + +pub struct FramedCodec { + codec: framed::bytes::Codec, +} + +impl FramedCodec { + pub fn new() -> FramedCodec { + let codec = framed::bytes::Config::default().to_codec(); + FramedCodec {codec} + } +} + +impl Decoder for FramedCodec { + type Item = BoxPayload; + type Error = framed::Error; + + fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { + + match src.iter().position(|e| *e==FRAME_END_SYMBOL) { + Some(len) => { + let data = src.split_to(len); + + Ok(Some(self.codec.decode_to_box(&data)?)) + } + None => { + Ok(None) + } + } + } +} + +impl Encoder> for FramedCodec { + type Error = framed::Error; + + fn encode(&mut self, item: Vec, dst: &mut BytesMut) -> Result<(), Self::Error> { + let encoded = self.codec.encode_to_box(&item)?; + + dst.extend_from_slice(&encoded); + + Ok(()) + } +} + +impl Encoder for FramedCodec { + type Error = anyhow::Error; + + fn encode(&mut self, item: Command, dst: &mut BytesMut) -> Result<(), Self::Error> { + let data = postcard::to_stdvec(&item)?; + Ok(self.encode(data, dst).map_err(|e| anyhow!("encode fail: {e:?}"))?) + } +}