1use bytes::{Buf, BytesMut};
2use tokio_util::codec::{Decoder, Encoder};
3
4use crate::frame::FutuFrame;
5use crate::header::{FutuHeader, HEADER_SIZE};
6
7pub struct FutuCodec;
12
13impl Decoder for FutuCodec {
14 type Item = FutuFrame;
15 type Error = futu_core::error::FutuError;
16
17 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
18 let header = match FutuHeader::peek(src)? {
20 Some(h) => h,
21 None => return Ok(None),
22 };
23
24 let total_len = HEADER_SIZE + header.body_len as usize;
25
26 if src.len() < total_len {
28 src.reserve(total_len - src.len());
29 return Ok(None);
30 }
31
32 src.advance(HEADER_SIZE);
34
35 let body = src.split_to(header.body_len as usize).freeze();
37
38 let frame = FutuFrame { header, body };
39
40 Ok(Some(frame))
41 }
42}
43
44impl Encoder<FutuFrame> for FutuCodec {
45 type Error = futu_core::error::FutuError;
46
47 fn encode(&mut self, item: FutuFrame, dst: &mut BytesMut) -> Result<(), Self::Error> {
48 item.header.encode(dst);
49 dst.extend_from_slice(&item.body);
50 Ok(())
51 }
52}
53
54#[cfg(test)]
55mod tests;