#byte-stream #byte #serialization #packet-parser #file-content #jppe-rs #ppe

无std jppe_derive

这是一个字节流结构化序列化和反序列化库

12个版本 (2个稳定版)

1.1.0 2024年8月13日
1.0.0 2024年4月4日
0.10.0 2024年4月1日
0.9.0 2024年3月29日

#66 in #packet-parser


3 个crate中使用(通过 jppe

MIT/Apache

72KB
1K SLoC

jppe-rs

Crates.io Crates.io License

这是一个基于Rust的字节流结构化序列化/反序列化通用库,可用于网络包解析、网络包分组、网络通信、文件内容解析等,感觉好的小伙伴们请点赞👍~

安装

$ rustup install nightly
$ cargo +nightly build release

用法

Cargo.toml

[dependencies]
jppe = { version="1.1.0", features = ["derive"] }

[dependencies]
jppe = { version="1.1.0", features = ["derive", "serde"] }

无std

[dependencies]
jppe = { version="1.1.0", default-features = false, features = ["derive"] } # default use alloc.

简单示例

use jppe::{ByteEncode, ByteDecode};


// If the value size is less than 0xff, byte_count does not need to be specified,otherwise, byte_count=<2|4|8>


#[derive(Debug, PartialEq, Eq, ByteEncode, ByteDecode)]
pub struct SimpleExample {
    pub version: u8,
    // #[jppe(byte_count=1)]
    pub value: String,
    // #[jppe(byte_count=1)]
    pub body: SimpleExampleBody,
}


#[derive(Debug, PartialEq, Eq, ByteEncode, ByteDecode)]
#[repr(u8)]
pub enum SimpleExampleBody {
    Read {
        address: u8,
    } = 1,
    Write {
        address: u8,
        value: [u8; 3],
    },
    #[jppe(enum_default)]
    Unknown, 
}


fn main() {
    let input = b"\x01\x03\x31\x32\x33\x01\x05";
    let (input_remain, value) = jppe::decode::<SimpleExample>(input).unwrap();
    assert_eq!(value, SimpleExample { version: 1, value: "123".to_string(), body: SimpleExampleBody::Read { address: 5 } });
    assert_eq!(input_remain.is_empty(), true);
    assert_eq!(jppe::encode(value), input);
}

简单示例2


use jppe::{ByteEncode, ByteDecode};


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


#[derive(Debug, PartialEq, Eq, ByteEncode, ByteDecode)]
#[repr(u8)]
pub enum SimpleExampleBody {
    Read {
        address: u8,
    } = 1,
    Write {
        address: u8,
        value: [u8; 3],
    },
    #[jppe(enum_default)]
    Unknown, 
}


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

默认示例

[dependencies]
jppe = { version="1.1.0", features = ["derive", "jdefault"] }

use jppe::{ByteEncode, ByteDecode, Jdefault};


// If the value size is less than 0xff, byte_count does not need to be specified,otherwise, byte_count=<2|4|8>


#[derive(Debug, PartialEq, Eq, ByteEncode, ByteDecode, Jdefault)]
pub struct SimpleExample {
    #[jppe(byte_count=1, default="\"123\".to_string()")]
    pub value: String,
    #[jppe(byte_count=1)]
    pub body: SimpleExampleBody,
}


#[derive(Debug, PartialEq, Eq, ByteEncode, ByteDecode, Jdefault)]
#[repr(u8)]
pub enum SimpleExampleBody {
    Read {
        address: u8,
    } = 1,
    Write {
        address: u8,
        value: [u8; 3],
    },
    #[jppe(branch_default)]
    Unknown {
        #[jppe(default=10)]
        value: u8,
    },
}


fn main() {
    let value = SimpleExample::default();
    assert_eq!(value, SimpleExample {
        value: "123".to_string(),
        body: SimpleExampleBody::Unknown { value: 10 },
    });

    assert_eq!(jppe::encode(value), b"\x03\x31\x32\x33\x03\x0a");

    let (input_remain, value) = jppe::decode::<SimpleExample>(b"\x03\x31\x32\x33\x03\x0a").unwrap();
    assert_eq!(value, SimpleExample {
        value: "123".to_string(),
        body: SimpleExampleBody::Unknown { value: 10 },
    });
    assert_eq!(input_remain.is_empty(), true);
}

其他示例

特性

容器属性修改器

  • byteorder=<"BE"|"LE">:结构和枚举的全局字节顺序,例如:#[jppe(byteorder="LE")]
  • encode_with:自定义编码函数。
  • decode_with:自定义解码函数。
  • with:自定义编码/解码函数。
  • get_variable_name:获取缓存变量,必须与 variable_name 一起使用,例如:变量名示例

枚举分支

  • 禁用字节计数
  • 枚举分支

字段属性修改器

  • byteorder=<"BE"|"LE">:局部性字段的数据字节顺序,例如:#[jppe(byteorder="LE")]
  • length=<num|variable>:数据长度,支持 int/&str/String/&[u8] 类型,例如:length_example
  • offset=<num|variable>:字节流偏移。
  • count==<num|variable>:数据计数,支持 Vec/HashMap 类型。
  • try_count==<num|variable>:数据计数,支持 Vec/HashMap 类型。
  • full=<int>:编码完整值。
  • untake:不取字节。
  • linend|end_with=<string|bytes>:支持 String/&str/&[u8] 类型。
  • key|starts_with:适用于对键/值结构数据的精确解析,支持 string/&str/&[u8] 类型。
  • split:支持 HashMap 类型,例如:split_example
  • if_expr:支持 Option<T> 类型,例如:if_expr_example
  • encode_with:自定义编码函数,例如:with_example
  • decode_with:自定义解码函数,例如:with_example
  • with:自定义编码/解码函数,例如:with_example
  • with_args:自定义编码/解码函数参数,例如:with_args_example
  • encode_value:值处理表达式,例如:#[jppe(encode_value="length * 2")]
  • decode_value:值处理表达式,例如:#[jppe(decode_value="length / 2")]
  • variable_name:设置整数缓存变量,例如:variable_name_example
  • byte_count=<1|2|4|8>:指定字节数,自动解码/编码长度或其他。
    • String/&str/&[u8]:提前获取n个字节的映射长度,例如:byte_count
    • HexString/HexBytes:提前获取n个字节的映射长度,例如:byte_count
    • Enum:提前获取byte_count字节的枚举映射并编码通过枚举索引,例如:enum_byte_count
    • Vec<T>
  • skip:要求数据类型实现Default特质。
  • skip_encode:跳过编码函数。
  • skip_decode:要求数据类型实现Default特质。
  • check_value
  • default:例如:default example
  • from_str

枚举分支

数据类型

  • u8/u16/u32/u64/usize/u128
  • i8/i16/i32/i64/isize/i128
  • bool
  • f32/f64
  • String&str
  • 数组[T;N]
  • 元组
  • Vec<T>
  • &[u8]
  • 可选<T>
  • 结构体
  • 枚举
  • PhantomData
  • HashMap:支持 String/&str/&[u8],例如:[HashMap示例](https://github.com/caizhengxin/jppe-rs/blob/67c05baeb7280528e19c62486e92114578ab09dc/derive/tests/test_type_hashmap.rs)
  • HashSet<T>:必须指定 #[jppe(count=xxx)] 修饰符,只支持解码函数,默认 count=0,例如:[HashSet示例](https://github.com/caizhengxin/jppe-rs/blob/67c05baeb7280528e19c62486e92114578ab09dc/derive/tests/test_type_hashset.rs)
  • MacAddress:例如:[Mac地址示例](https://github.com/caizhengxin/jppe-rs/blob/67c05baeb7280528e19c62486e92114578ab09dc/derive/tests/test_type_mac_address.rs)
  • std::net::Ipv4Addr/Ipv6Addr/IpAddr:IpAddr 类型必须指定 length=<16|4> 修饰符,否则返回错误,例如:[IP地址示例](https://github.com/caizhengxin/jppe-rs/blob/67c05baeb7280528e19c62486e92114578ab09dc/derive/tests/test_type_ip_address.rs)
  • PpeAddress:必须指定 length=<16|4|6|usize> 修饰符,否则返回错误,例如:[PPE地址示例](https://github.com/caizhengxin/jppe-rs/blob/67c05baeb7280528e19c62486e92114578ab09dc/derive/tests/test_type_ppe_address.rs)
  • HexString:例如:[十六进制字符串示例](https://github.com/caizhengxin/jppe-rs/blob/67c05baeb7280528e19c62486e92114578ab09dc/derive/tests/test_type_hex.rs)
  • HexBytes:例如:[十六进制字节示例](https://github.com/caizhengxin/jppe-rs/blob/67c05baeb7280528e19c62486e92114578ab09dc/derive/tests/test_type_hex_bytes.rs)
  • 日期时间

待办事项

  • jnet-rs 库。
  • jget-rs 库。
  • jdefault-rs 库。
  • jfmt-rs 库。

依赖

~0.4–0.9MB
~20K SLoC