6个版本 (3个破坏性版本)
0.4.0 | 2024年6月19日 |
---|---|
0.3.0 | 2022年8月26日 |
0.2.2 | 2022年8月9日 |
0.2.1 | 2022年7月28日 |
0.1.0 | 2022年4月5日 |
#239 在 Rust模式
每月422次下载
用于 2 crates
62KB
819 行
此crate提供字节/位与异构列表(元组)之间转换的库。
库特性
- 实现编译时类型检查
- 既不声明也不导出过程宏
- 从单个字节数组中混合字节序
示例
解析复杂数据结构
use heterob::{P4, endianness::LeBytesInto, bit_numbering::LsbInto};
// Source is a [u8;6] bytes array
let data = [0x00u8,0x11,0x22,0x33,0x44,0x55,0b1010_1001];
// Target struct
#[derive(Debug, Clone, PartialEq, Eq)]
struct S {
byte: u8,
word: Option<u16>,
bytes: [u8;3],
is_byte6_bit0: bool,
byte6_last_4_bits: u8,
}
// Parse bytes array as integers
let P4((byte, word, bytes, byte6)) = data.le_bytes_into();
// Parse last byte as bitfield. Unit type () used as placeholder
let (is_byte6_bit0, (), is_some_word, byte6_last_4_bits) =
P4::<u8, 1, 2, 1, 4>(byte6).lsb_into();
// `is_some_word` coerce to bool via let statement
let _: bool = is_some_word;
// Final structure
let result = S {
byte,
word: is_some_word.then(|| word),
bytes,
is_byte6_bit0,
byte6_last_4_bits,
};
let sample = S {
byte: 0x00,
word: Some(0x2211),
bytes: [0x33,0x44,0x55],
is_byte6_bit0: true,
byte6_last_4_bits: 0b1010,
};
assert_eq!(sample, result);
混合字节序
use heterob::{T3, endianness::{Be, Le}};
#[derive(Debug, Clone, PartialEq, Eq)]
struct S {
le: u16,
be: u16,
bytes: [u8;2]
}
let data = [0x00,0x11,0x22,0x33,0x44,0x55];
let (Le(le),Be(be),bytes) = T3::from(data).into();
let s = S { le, be, bytes };
assert_eq!(S { le: 0x1100, be: 0x2233, bytes: [0x44,0x55] }, s, "{:x}", s.be);
可能失败的字节数组切片解析
use heterob::{Seq, P3, endianness::Be};
// Source is a bytes slice
let data = [0x00u8,0x11,0x22,0x33,0x44,0x55,0b1010_1001].as_slice();
// Target struct
#[derive(Debug, Clone, PartialEq, Eq)]
struct S {
byte: u8,
word: u16,
bytes: [u8;3],
}
// Parse bytes array as integers
let Seq { head: Be((byte, word, bytes)), .. } = P3(data).try_into().unwrap();
// Final structure
let result = S {
byte,
word,
bytes,
};
let sample = S {
byte: 0x00,
word: 0x1122,
bytes: [0x33,0x44,0x55],
};
assert_eq!(sample, result);
编译时类型检查
通过内联const表达式 + assert!实现编译时检查。不幸的是,使用此类编译时检查很难找到错误源。随着稳定化的常量泛型算术,这应该会容易得多。
编译时检查了三件事情
1. 数组在多个数组上的拆分
此检查断言输入数组的长度等于输出数组长度的总和
# use heterob::T2;
let data = [0u8; 13];
let _ = T2::<[u8;4], [u8;3]>::from(data);
尝试将13字节长度的数组拆分为长度为4 + 3 = 7的2个数组将引发错误
error[E0080]: evaluation of `<heterob::T2<[u8; 4], [u8; 3]> as std::convert::From<[u8; 13]>>::from::{constant#1}` failed
--> heterob/src/common.rs:402:1
|
402 | common_impl!(2; A,B);
| ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'The sum AN + BN should be equal to N', heterob/src/
common.rs:402:1
|
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `common_impl` (in Nightly builds, r
un with -Z macro-backtrace for more info)
note: erroneous constant encountered
--> heterob/src/common.rs:402:1
|
402 | common_impl!(2; A,B);
| ^^^^^^^^^^^^^^^^^^^^
|
= note: this note originates in the macro `common_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
note: the above error was encountered while instantiating `fn <heterob::T2<[u8; 4], [u8; 3]> as std::convert::From<[u8; 13]>>::from`
--> src/lib.rs:9:13
|
9 | let _ = T2::<[u8; 4], [u8; 3]>::from(data);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2. 随机值中的位索引
此检查断言位索引的总和小于值位数的数量
# use heterob::{P3, bit_numbering::LsbInto};
let data = 0u16;
let ((),(),()) = P3::<_, 2, 11, 5>(data).lsb_into();
尝试从16位值中提取12-17位将引发错误
err(https://doc.rust-lang.net.cn/core/macro.assert.html): evaluation of `<((), (), ()) as heterob::bit_numbering::FromLsb<heterob::P3<u16, 2, 11, 5>>>::from_lsb::{constant#0}` failed
--> heterob/src/bit_numbering.rs:227:1
|
227 | bit_numbering_impl!(3: A,B,C);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'The bits number in TY in P3<TY, ...> is less than sum AN + BN + CN', heterob/src/t(https://doc.rust-lang.net.cn/core/macro.assert.html)ring.rs:227:1
|
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `bit_numbering_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
note: erroneous constant encountered
--> heterob/src/bit_numbering.rs:227:1
|
227 | bit_numbering_impl!(3: A,B,C);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this note originates in the macro `bit_numbering_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
note: the above error was encountered while instantiating `fn <((), (), ()) as heterob::bit_numbering::FromLsb<heterob::P3<u16, 2, 11, 5>>>::from_lsb`
--> heterob/src/bit_numbering.rs:136:9
|
136 | U::from_lsb(self)
| ^^^^^^^^^^^^^^^^^
3. 字节序转换
此检查检查源和结果中的字节数是否相等。
# use heterob::endianness::FromBeBytes;
let _: [u32; 2] = FromBeBytes::from_be_bytes([0u8; 7]);
尝试将7字节数组转换为8字节类型(u32 * 2)将引发类似以下错误的错误
error[E0080]: evaluation of `<[u32; 2] as heterob::endianness::FromBeBytes<7>>::from_be_bytes::{constant#1}` failed
--> heterob/src/endianness.rs:352:1
|
352 | endianness_integers!(u16, u32, u64, u128, usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'The size of [u32; M] and [u8; N] are different', heterob/src/endianness.rs:352:1
|
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `endianness_integers` (in Nightly builds, run with -Z macro-backtrace for more info)
note: erroneous constant encountered
--> heterob/src/endianness.rs:352:1
|
352 | endianness_integers!(u16, u32, u64, u128, usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this note originates in the macro `endianness_integers` (in Nightly builds, run with -Z macro-backtrace for more info)
note: the above error was encountered while instantiating `fn <[u32; 2] as heterob::endianness::FromBeBytes<7>>::from_be_bytes`
--> src/lib.rs:8:23
|
8 | let _: [u32; 2] = FromBeBytes::from_be_bytes([0u8; 7]);
依赖项
~83KB