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 日

#805解析器实现

Download history 228/week @ 2024-03-13 214/week @ 2024-03-20 194/week @ 2024-03-27 221/week @ 2024-04-03 174/week @ 2024-04-10 243/week @ 2024-04-17 283/week @ 2024-04-24 441/week @ 2024-05-01 273/week @ 2024-05-08 179/week @ 2024-05-15 185/week @ 2024-05-22 211/week @ 2024-05-29 205/week @ 2024-06-05 150/week @ 2024-06-12 136/week @ 2024-06-19 105/week @ 2024-06-26

每月 617 次下载
9 个 crate 中使用 (通过 twmap)

MIT 许可证

18KB
129

structview

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

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

此 crate 的预期用例是解析二进制数据格式,尤其是如果只对某些字段的值感兴趣,而不是所有字段。在这些情况下,structview 可以用来高效地找到感兴趣的字段,而无需对无关的字段进行潜在的字节序转换。如果所有字段都需要解析,则直接使用 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 通过提供 一个可自动派生的 trait View 以及 用于安全查看整数字段的类型,使得重新解释原始数据既安全又方便。

要求

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

View Trait

通过实现 View trait,类型保证可以从原始二进制数据安全地转换为。该 trait 为实现类型添加了几个视图方法,使得可以从字节切片生成这些类型的实例的引用。

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,否则会引发恐慌。

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

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

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

不建议手动实现 View 特性。相反,应该像上面的示例那样自动推导。推导确保了安全性,强制实施实现结构体和联合体是 repr(C) 并且只包含 View 字段。这足以满足上述安全性要求。

整数视图

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

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

示例中使用的 u32_le 类型就是这些整数视图之一。实际上,它是 U32<LittleEndian> 的别名,这是一个由 byteorder 提供的泛型类型 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 转换特性

no_std 上下文中的使用

structview 有一个特性,std,默认启用。要在 no_std 上下文中使用该包,请在 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 的任何贡献,都应按照上述许可证授权,不附加任何额外条款或条件。

依赖项

约 1.5MB
约 37K SLoC