< 返回版块

jankincai 发表于 2025-01-08 10:50

Tags:序列化,反序列化,网络数据包解析,bytes

项目地址:https://github.com/caizhengxin/jbytes

use jbytes::{ByteEncode, ByteDecode};


#[derive(Debug, PartialEq, Eq, ByteEncode, ByteDecode)]
pub struct SimpleExample {
    pub length: u16,
    #[jbytes(length="length")]
    pub value: String,
    pub cmd: u8,
    #[jbytes(branch="cmd")]
    pub body: SimpleExampleBody,
}


#[derive(Debug, PartialEq, Eq, ByteEncode, ByteDecode)]
pub enum SimpleExampleBody {
    #[jbytes(branch_value=1)]  // Set 1
    Read {
        address: u8,
    },
    Write {
        address: u8,
        value: [u8; 3],
    },                        // Increment to 2
    #[jbytes(branch_default)]
    Unknown,                  // _ => { ... }
}


fn main() {
    let input = b"\x00\x03\x31\x32\x33\x01\x05";
    let value: SimpleExample = jbytes::decode(input).unwrap();
    assert_eq!(value, SimpleExample { length: 3, value: "123".to_string(), cmd: 1, body: SimpleExampleBody::Read { address: 5 } });
    assert_eq!(*jbytes::encode(value).unwrap(), input);
}

Enum 解析简单例子:

use jbytes::{ByteEncode, ByteDecode};
use jbytes::prelude::*;


#[derive(Debug, PartialEq, Eq, ByteEncode, ByteDecode)]
pub struct SimpleExample {
    pub version: u8,
    pub cmd: u8,
    #[jbytes(branch="cmd")]
    pub body: SimpleExampleBody,
}


#[derive(Debug, PartialEq, Eq, ByteEncode, ByteDecode)]
pub enum SimpleExampleBody {
    #[jbytes(branch_value=1)]
    Stop,                             // Set 1
    Start,                            // Increment to 2
    #[jbytes(branch_value="4..=7")]
    Read {
        address: u16,
        length: u16,
    },                                // Set 4..=7, including: 4、5、6、7
    Write {
        address: u16,
        length: u16,
        #[jbytes(count="length")]
        data: Vec<u8>,
    },                                // Increment to 8
    #[jbytes(branch_default)]
    Unknown {
        address: u16,
    },                          // _ => { ... }
}


fn main() -> JResult<()> {
    // Start 
    let input = [
        0x01,                   // version
        0x02,                   // cmd => Start
    ];
    let value: SimpleExample = jbytes::decode(&input)?;
    assert_eq!(value, SimpleExample {
        version: 1,
        cmd: 2,
        body: SimpleExampleBody::Start
    });
    assert_eq!(*jbytes::encode(value)?, input);

    // Read 
    let input = [
        0x01,                   // version
        0x05,                   // cmd => Read
        0x00, 0x01,             // Read, address
        0x00, 0x0a,             // Read, length
    ];
    let value: SimpleExample = jbytes::decode(&input)?;
    assert_eq!(value, SimpleExample {
        version: 1,
        cmd: 5,
        body: SimpleExampleBody::Read {
            address: 0x0001,
            length: 0x000a,
        }
    });
    assert_eq!(*jbytes::encode(value)?, input);

    // Write
    let input = [
        0x01,                   // version
        0x08,                   // cmd => Write
        0x00, 0x01,             // Write, address
        0x00, 0x03,             // Write, length
        0x01, 0x02, 0x03,       // Write, data
    ];
    let value: SimpleExample = jbytes::decode(&input)?;
    assert_eq!(value, SimpleExample {
        version: 1,
        cmd: 8,
        body: SimpleExampleBody::Write {
            address: 0x0001,
            length: 0x0003,
            data: vec![0x01, 0x02, 0x03],
        }
    });
    assert_eq!(*jbytes::encode(value)?, input);

    // Unknown
    let input = [
        0x01,                   // version
        0x09,                   // cmd => Unknown
        0x00, 0x01,             // Unknown, address
    ];
    let value: SimpleExample = jbytes::decode(&input).unwrap();
    assert_eq!(value, SimpleExample {
        version: 1,
        cmd: 9,
        body: SimpleExampleBody::Unknown {
            address: 0x0001,
        }
    });
    assert_eq!(*jbytes::encode(value)?, input);

    Ok(())
}

HTTP Header 解析简单例子:

use jkcenum::JkcEnum;
use jbytes::{BorrowByteEncode, BorrowByteDecode};
use jbytes::prelude::*;


#[derive(Debug, Default, PartialEq, Eq, BorrowByteEncode, BorrowByteDecode)]
pub struct Http<'a> {
    #[jbytes(linend=b"\x20", from_str)]
    pub method: HttpMethodEnum,
    #[jbytes(linend=b"\x20")]
    pub uri: &'a str,
    #[jbytes(linend=b"\r\n")]
    pub version: &'a str,
    #[jbytes(try_count=20)]
    pub headers: Vec<HttpHeader<'a>>,
}


#[derive(Debug, Default, PartialEq, Eq, BorrowByteEncode, BorrowByteDecode)]
pub struct HttpHeader<'a> {
    #[jbytes(linend=b": ")]
    pub key: &'a str,
    #[jbytes(linend=b"\r\n")]
    pub value: &'a str,
}


#[derive(Debug, Default, PartialEq, Eq, BorrowByteDecode, BorrowByteEncode, JkcEnum)]
#[jbytes(byte_count_disable)]
pub enum HttpMethodEnum {
    #[default]
    GET,
    POST,
    HEAD,
    PUT,
    DELETE,
    CONNECT,
    OPTIONS,
    TRACE,
    PATCH,
}


fn main() {
    // decode
    let data = b"GET http://www.jankincai.com/ HTTP/1.1\r\nHost: www.jankincai.com\r\nAccept-Encoding: gzip, deflate\r\n";
    let bytes = Bytes::new(data);
    let value: Http = jbytes::decode_borrow(&bytes).unwrap();
    println!("{value:?}");

    // encode
    assert_eq!(*jbytes::encode_borrow(value).unwrap(), data);

    // error
    let data: &[u8; 97] = b"SET http://www.jankincai.com/ HTTP/1.1\r\nHost: www.jankincai.com\r\nAccept-Encoding: gzip, deflate\r\n";
    let bytes = Bytes::new(data);
    let value: JResult<Http> = jbytes::decode_borrow(&bytes);
    assert_eq!(value.is_err(), true);
}

Ext Link: https://github.com/caizhengxin/jbytes

评论区

写评论
作者 jankincai 2025-01-13 11:12

你好,zerocopy我没有实际使用过,看起来使用方式和bincode差不多,jbytes主要在网络数据包解析、文件格式解析等可能有优势,不支持跨语言,目前还不完善,主要根据我对数据解析理解,简单封装了一个库,在于学习,哈哈。

--
👇
miaomiao1992: 和zerocopy有和异同?

跨语言,该协议是否通用?

miaomiao1992 2025-01-10 20:38

和zerocopy有和异同?

跨语言,该协议是否通用?

miaomiao1992 2025-01-10 20:36

字节流结构化 不是字节跳动结构化

--
👇
liangyongrui: 好奇为啥是私人仓库。这种不应该是审计后 用公司的名义发吗?

作者 jankincai 2025-01-08 17:26

嗯,没事,第一版在2024年3月份就开源了,陆陆续续也更新了很久,目前这个是重构了大部分底层逻辑,换了个名字,重新开源了。

--
👇
liangyongrui: 不好意思,看错了。。

--
👇
jankincai: 很好奇,你从哪看到是公司项目,这个是我最近从头重新构思的个人项目。

--
👇
liangyongrui: 好奇为啥是私人仓库。这种不应该是审计后 用公司的名义发吗?

liangyongrui 2025-01-08 17:20

不好意思,看错了。。

--
👇
jankincai: 很好奇,你从哪看到是公司项目,这个是我最近从头重新构思的个人项目。

--
👇
liangyongrui: 好奇为啥是私人仓库。这种不应该是审计后 用公司的名义发吗?

作者 jankincai 2025-01-08 16:32

好的,谢谢建议!

--
👇
regomne: 给个建议,要推广的话,还是要在页面中提一下竞品和跟竞品相比的区别,比如评论区就有人问和bincode啥区别,虽然在我看来其实不完全构成竞品

作者 jankincai 2025-01-08 16:29

很好奇,你从哪看到是公司项目,这个是我最近从头重新构思的个人项目。

--
👇
liangyongrui: 好奇为啥是私人仓库。这种不应该是审计后 用公司的名义发吗?

regomne 2025-01-08 16:23

给个建议,要推广的话,还是要在页面中提一下竞品和跟竞品相比的区别,比如评论区就有人问和bincode啥区别,虽然在我看来其实不完全构成竞品

liangyongrui 2025-01-08 16:21

好奇为啥是私人仓库。这种不应该是审计后 用公司的名义发吗?

作者 jankincai 2025-01-08 15:52

可以的,很多修饰符可以通过数据内容动态解析后面的内容

--
👇
regomne: 这个不错啊,感觉也适合写各种文件格式的parser

regomne 2025-01-08 15:40

这个不错啊,感觉也适合写各种文件格式的parser

作者 jankincai 2025-01-08 13:55

有的,bincode功能很单一,这个更适合网络数据包解析。

--
👇
我心飞翔: 与 bincode 有什么区别吗

我心飞翔 2025-01-08 13:51

与 bincode 有什么区别吗

1 共 13 条评论, 1 页