< 返回版块

ywzjackal 发表于 2019-04-26 14:31

Tags:Encode,Decode,Binary,Bit Field,Library

因为

工作涉及的编解码内容较多,且字段灵活,目前没有找到能适配的lib能可以用的。最早用c语言可以使用bit field,还能方便点,但是遇到Optional字段或者Dynamic Length字段一样需要手写代码。 自从使用Rust后,都是手写编解码,每个字节&>>,<<,~,|很累,特别是遇到不对齐的field时候更头疼。

所以

打算自己造个轮子,使用proc_macro

为什么不用bincode? 因为bincode编码方式不能自定义,比如对于vec字段,前8个字节是固定vec数量大小的。

目标

灵活定义字段

#[derive(BinEncodeBe)]
pub struct TsPack {
    // 默认bit size等于字段类型
    pub sync_code: u8,
    // bool类型的bit size 总是等于1
    pub translation_error: bool,
    pub first_payload: bool,
    pub high_priority: bool,
    // 可自定义数值类型的bit 大小
    #[bin(bits(13))]
    pub pid: u16,
    pub first: bool,
    pub last: bool,
    // 可以使用skip属性定义保留bit位
    #[bin(skip(2))]
    #[bin(bits(4))]
    pub cnt: i8,
    // 可以使用Option、Vec类型包裹
    // None时不编码
    // 当first_payload=true时才会解码该字段,否则设置未None
    #[bin(is_some(first_payload))]
    pub option: Option<u128>,
    // 可以嵌套复合类型
    // 解码时根据count进行匹配vec items数量
    #[bin(count(cnt as usize))]
    pub vec: Vec<TsPack>,
}

目前

以前已经实现过一次,但是性能堪忧。 目前已经重写了编码,解码还在进行中。所以是否有人对这个库感兴趣?

项目地址

https://github.com/ywzjackal/bin_codec.rs crates: bin_codec, bin_codec_derive

评论区

写评论
作者 ywzjackal 2019-04-29 13:21

Hello, 项目发布在https://github.com/ywzjackal/bin_codec.rs。由于支持灵活的bit定义,所以性能比较差,等const fn稳定后应该会很方便进行优化。 对以下内容的回复:

关注
rdigua 2019-04-26 16:40

关注

作者 ywzjackal 2019-04-26 14:34
use bin_codec::*;
use bin_codec_derive2::{BinEncodeBe};

#[derive(BinEncodeBe)]
pub struct TsPack {
    // 00 : 0
    pub sync_code: u8,
    // 01 : 7
    pub translation_error: bool,
    // 01 : 6
    pub first_payload: bool,
    // 01 : 5
    pub high_priority: bool,
    // 01 : 4
    #[bin(bits(13))]
    pub pid: u16,
    pub first: bool,
    pub last: bool,
    #[bin(skip(2))]
    #[bin(bits(4))]
    pub seq: i8,
}

#[test]
fn test_ts_encode() {
    let ts = TsPack {
        sync_code: 0x47,
        translation_error: false,
        first_payload: true,
        high_priority: false,
        pid: 0x1abc,
        first: true,
        last: false,
        seq: 0xA,
    };
    let mut target = [0u8; 4];
    ts.encode(&mut target, &mut Context::<()>::default());
    let shouldbe = [0x47, 0b0100_0000 | 0x1A, 0xBC, 0b1000_0000 | 0xA];
    assert_eq!(target, shouldbe, "\r\n{:02X?} \r\n {:02X?}", target, shouldbe);
    assert_eq!(4 * 8, ts.bits());
}
1 共 3 条评论, 1 页