17 个版本 (10 个破坏性更改)
使用旧的 Rust 2015
0.11.3 | 2024 年 5 月 21 日 |
---|---|
0.11.2 | 2021 年 5 月 31 日 |
0.11.1 | 2021 年 2 月 3 日 |
0.11.0 | 2020 年 6 月 20 日 |
0.3.0 | 2016 年 11 月 11 日 |
#169 in Rust 模式
每月下载量 22,468
用于 122 个 crate (22 个直接)
95KB
690 行
safe-transmute-rs
为 Rust 提供受保护的 transmute()
函数。
文档
lib.rs
:
此 crate 包含了 transmutation 程序的 checked 实现,其中一些确保了内存安全。
crate 结构
以下模块可用
base
模块中的函数本身不是安全的,但只是防止越界访问(例如,尝试从 7 个字节创建一个 8 字节类型)。这些函数与传递给它们的数据一样安全:尝试将数据转换为一个无效的内存表示仍然是未定义行为。此外,未对齐的内存访问不会被阻止,必须由调用者事先确保。guard
模块包含 Guard API,它在一个转换中强加切片边界限制。- 《trivial》模块引入了《TriviallyTransmutable》特质,它静态地确保任何位组合对于给定类型都构成一个有效的值。该模块中的函数比《base》模块更安全,但仍然不能防止未对齐的内存访问。
to_bytes
实现了将值重新解释为字节的反向操作。- 《bool》模块确保将字节安全地转换为布尔值。
- 在该包的根目录中,有一些转换函数,经过足够的检查,可以在任何情况下使用。由于未对齐的数据或不可兼容的向量转换目标,操作可能还会任意返回(可恢复的)错误,但它不会吃掉你的衣物,并且有辅助函数可供程序员在特定用例中使用。
可以通过在导入时指定 default-features = false
来禁用 std
功能,从而在无 std
环境中使用此包。然而,std
只用于与 std::error::Error
集成。
请注意,这也会禁用对 alloc
的操作。如果你的无 std
环境有一个 alloc
实现,你将必须通过使用 features = ["alloc"]
来重新启用它们。
迁移
如果你在 v0.11 之前使用过 safe-transmute
,我们建议查看 v0.11 迁移指南 以快速开始。
示例
将字节视为一系列 u16
,具有单对多边界保护(至少一个值,允许多余的字节)
let bytes = &[0x00, 0x01, 0x12, 0x24,
0x00]; // 1 spare byte
match transmute_many::<u16, SingleManyGuard>(bytes) {
Ok(words) => {
assert_eq!(words,
[u16::from_be(0x0001), u16::from_be(0x1224)]);
},
Err(Error::Unaligned(e)) => {
// Copy needed, would otherwise trap on some archs
let words = e.copy();
assert_eq!(*words,
[u16::from_be(0x0001), u16::from_be(0x1224)]);
},
Err(e) => panic!("Unexpected error: {}", e),
}
由于无法始终确保字节切片在读取不同约束的数据(如从 u8 到
u16
)时对齐良好,因此操作可能无法成功,且没有简单的方法来防止这种情况。
作为补救措施,可以在新向量中逐字节复制数据,这得益于 try_copy!
宏的帮助。
let bytes = &[0x00, 0x01, 0x12, 0x24, 0x00];
let words = try_copy!(transmute_many::<u16, SingleManyGuard>(bytes));
assert_eq!(*words,
[u16::from_be(0x0001), u16::from_be(0x1224)]);
将所有字节视为一系列 u16
// Assuming little-endian
let bytes = &[0x00, 0x01, 0x12, 0x34];
let words = try_copy!(transmute_many_pedantic::<u16>(bytes));
assert_eq!(*words, [0x0100, 0x3412]);
将字节切片视为单个 f64
assert_eq!(transmute_one::<f64>(
&[0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40])?,
2.0);
将一系列 u16
视为字节
assert_eq!(transmute_to_bytes(&[0x0001u16,
0x1234u16]),
&[0x01, 0x00, 0x34, 0x12]);