aboutsummaryrefslogtreecommitdiff
path: root/net/src/codec/length_codec.rs
blob: 76a16794ad5c0c721dcea912167322ac9a5a81d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
use karyon_core::util::{decode, encode_into_slice};

use crate::{
    codec::{Codec, Decoder, Encoder},
    Result,
};

/// The size of the message length.
const MSG_LENGTH_SIZE: usize = std::mem::size_of::<u32>();

#[derive(Clone)]
pub struct LengthCodec {}
impl Codec for LengthCodec {
    type Item = Vec<u8>;
}

impl Encoder for LengthCodec {
    type EnItem = Vec<u8>;
    fn encode(&self, src: &Self::EnItem, dst: &mut [u8]) -> Result<usize> {
        let length_buf = &mut [0; MSG_LENGTH_SIZE];
        encode_into_slice(&(src.len() as u32), length_buf)?;
        dst[..MSG_LENGTH_SIZE].copy_from_slice(length_buf);
        dst[MSG_LENGTH_SIZE..src.len() + MSG_LENGTH_SIZE].copy_from_slice(src);
        Ok(src.len() + MSG_LENGTH_SIZE)
    }
}

impl Decoder for LengthCodec {
    type DeItem = Vec<u8>;
    fn decode(&self, src: &mut [u8]) -> Result<Option<(usize, Self::DeItem)>> {
        if src.len() < MSG_LENGTH_SIZE {
            return Ok(None);
        }

        let mut length = [0; MSG_LENGTH_SIZE];
        length.copy_from_slice(&src[..MSG_LENGTH_SIZE]);
        let (length, _) = decode::<u32>(&length)?;
        let length = length as usize;

        if src.len() - MSG_LENGTH_SIZE >= length {
            Ok(Some((
                length + MSG_LENGTH_SIZE,
                src[MSG_LENGTH_SIZE..length + MSG_LENGTH_SIZE].to_vec(),
            )))
        } else {
            Ok(None)
        }
    }
}