Skip to main content

futu_codec/
codec.rs

1use bytes::{Buf, BytesMut};
2use tokio_util::codec::{Decoder, Encoder};
3
4use crate::frame::FutuFrame;
5use crate::header::{FutuHeader, HEADER_SIZE};
6
7/// **Stable API** — FutuOpenD 协议帧编解码器。
8///
9/// 实现 `tokio_util` 的 `Decoder` / `Encoder` trait,用于在 TCP 流上进行帧
10/// 边界识别和编解码。零 state unit struct,可以自由多实例。
11pub 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        // 尝试解析帧头(不消费)
19        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        // 检查是否有足够的数据
27        if src.len() < total_len {
28            src.reserve(total_len - src.len());
29            return Ok(None);
30        }
31
32        // 消费帧头
33        src.advance(HEADER_SIZE);
34
35        // 提取 body
36        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;