#cast #struct #view #traits #fields #derive #structview

structview_derive

为 structview 的 View 特性提供自定义 derive

6 个版本 (2 个稳定版)

1.1.0 2020 年 6 月 5 日
1.0.0 2020 年 3 月 15 日
0.3.1 2019 年 10 月 7 日
0.3.0 2019 年 1 月 13 日
0.1.0 2018 年 12 月 19 日

#80#cast

Download history 229/week @ 2024-03-13 220/week @ 2024-03-20 198/week @ 2024-03-27 227/week @ 2024-04-03 181/week @ 2024-04-10 255/week @ 2024-04-17 294/week @ 2024-04-24 444/week @ 2024-05-01 274/week @ 2024-05-08 183/week @ 2024-05-15 189/week @ 2024-05-22 213/week @ 2024-05-29 208/week @ 2024-06-05 152/week @ 2024-06-12 138/week @ 2024-06-19 112/week @ 2024-06-26

630 每月下载次数
10 个 crate 中使用(通过 structview

MIT 许可证

6KB
80

structview

structview 是一个 Rust 库,可以将对二进制数据的引用转换为对更高层次数据结构的引用,例如结构体、联合体和数组。

实现的方法类似于在 C 中解析二进制数据格式时常用的模式,其中表示原始数据的 char * 直接转换为结构体指针等。这种技术具有简单和高度高效的优势。然而,它也是不安全的,因为通常忽略对齐和整数字节序的问题。 structview 通过为用户提供安全接口来避免这些问题。

此 crate 的预期用途是解析二进制数据格式,特别是当仅对某些字段的值感兴趣时。在这些情况下,structview 可以用于高效地查找感兴趣的字段,而无需对无关字段执行潜在的 byteorder 转换。如果所有字段都需要解析,则直接使用 byteorder crate 可能更直接。

示例

以下示例演示了将二进制数据切片视为简单结构体的过程

use structview::{u32_le, View};

#[derive(Clone, Copy, View)]
#[repr(C)]
struct Animal {
    name: [u8; 4],
    number_of_heads: u8,
    number_of_legs: u32_le,
}

fn main() -> Result<(), structview::Error> {
    let data = [0x43, 0x61, 0x74, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00];
    let animal = Animal::view(&data)?;

    assert_eq!(animal.name, *b"Cat\x00");
    assert_eq!(animal.number_of_heads, 1);
    assert_eq!(animal.number_of_legs.to_int(), 4);

    Ok(())
}

正如示例所示,structview 通过提供 一个(自动可推导的)特性 View 以及 用于安全查看整数字段的类型,使得重新解释原始数据既安全又方便。

要求

需要 Rust 版本 1.38.0 或更高版本。

View 特性

通过实现 View 特性,一个类型承诺它可以安全地从原始二进制数据转换而来。该特性为实现类型添加了几个视图方法,使它们能够从字节数组中生成这些类型的实例的引用。

pub unsafe trait View: Copy {
    fn view(data: &[u8]) -> Result<&Self, structview::Error> { ... }
    fn view_slice(data: &[u8]) -> Result<&[Self], Error> { ... }
    fn view_boxed_slice(data: Box<[u8]>) -> Result<Box<[Self]>, Error> { ... }
}

所有视图方法都会检查给定数据data的长度,如果字节数过少,则返回Error::NotEnoughData。此外,两个切片视图方法要求mem::size_of::<Self>() > 0,否则会panic。

实现View是不安全的,因为必须确保

  • 每个可能的原始字节数值都构成实现类型的有效数据
  • 实现类型是1字节对齐的
  • 编译器不会改变实现类型字段(在复合类型的情况下)的顺序

structview已经为1字节整数类型(i8u8)、View类型数组以及提供的整数视图(u32_le和类似)实现了View。基于这些原始类型,用户可以为自己的结构体和联合体创建视图。

手动实现View trait是不推荐的。相反,它应该像上面示例中那样自动推导。推导确保了通过强制实现结构体和联合体使用repr(C)并且只包含View字段来满足上述安全要求。

整数视图

虽然单字节整数i8u8可以从原始数据安全地转换,但更宽的整数不行:它们的对齐方式与字节的1字节对齐不兼容,并且它们的(应用程序定义的)字节序可能与系统的本地字节序不兼容。

structview通过将这些更宽的整数类型转换为特殊的整数视图来解决此问题:围绕适当大小的u8数组的包装器,提供了将原始数据解析为实际整数的方法。

示例中使用的u32_le类型就是这些整数视图之一。它实际上是对U32<LittleEndian>的别称,这是一个泛型类型,由byteorder crate提供的ByteOrder。以下表格列出了所有提供的整数视图

位宽 泛型 小端 大端
16 I16<BO> i16_le i16_be
U16<BO> u16_le u16_be
32 I32<BO> i32_le i32_be
U32<BO> u32_le u32_be
64 I64<BO> i64_le i64_be
U64<BO> u64_le u64_be

每个整数视图都提供了一个to_int方法,用于解析并返回相应的整数值。每个整数视图还为其整数类型实现了From转换trait

no_std上下文中的使用

structview有一个默认启用的功能std。要在no_std上下文中使用该crate,请在Cargo.toml中禁用默认功能

[dependencies.structview]
version = "1"
default-features = false

如果禁用std

  • structview::Error 没有实现 std::error::Error
  • View::view_boxed_slice 不可用

许可证

本项目采用 MIT 许可证许可(LICENSEhttp://opensource.org/licenses/MIT)。

除非你明确表示,否则你提交给 structview 的任何有意贡献,都应按上述方式许可,不附加任何额外条款或条件。


lib.rs:

structview 包的 View 特性提供自定义安全的 derive 实现。

依赖

~1.5MB
~35K SLoC