4个版本 (2个重大更新)
使用旧的Rust 2015
0.2.3 | 2017年11月24日 |
---|---|
0.2.2 |
|
0.2.1 |
|
0.1.0 | 2017年4月11日 |
0.0.2 | 2017年4月4日 |
#281 in 解析工具
530,967每月下载量
用于 981 个crate (23直接)
23KB
287 代码行
libplain
一个小的Rust库,允许用户安全地将字节序列解释为某些类型的结构。
此crate提供了一个不安全的特质 Plain
,用户使用此特质标记对此库操作安全的类型。参见 Plain
的合同义务。
除此之外,此crate中的所有其他内容在Plain
特质不在不允许的类型上实现的情况下(类似于标准库中的Send
和Sync
)都是完全安全的。
用途
在底层系统开发中,有时需要将内存位置解释为数据结构。此crate中的函数旨在避免与此相关的陷阱,而无需求助于大型、功能齐全的(反)序列化库。
另一方面,此crate没有处理平台之间编码和字节序差异的任何规定。因此,它完全不适用于处理外部数据,如文件内容或网络数据包。
示例
要开始使用此crate,只需做 extern crate plain;
。
如果您想使plain类型具有此crate中的方法,还包括 use plain.Plain;
。
然后只需标记正确的类型并使用它们即可。
extern crate plain;
use plain::Plain;
use std::mem;
#[repr(C)]
#[derive(Default)]
struct ELF64Header {
pub e_ident: [u8; 16],
pub e_type: u16,
pub e_machine: u16,
pub e_version: u32,
pub e_entry: u64,
pub e_phoff: u64,
pub e_shoff: u64,
pub e_flags: u32,
pub e_ehsize: u16,
pub e_phentsize: u16,
pub e_phnum: u16,
pub e_shentsize: u16,
pub e_shnum: u16,
pub e_shstrndx: u16,
}
// SAFE: ELF64Header satisfies all the requirements of `Plain`.
unsafe impl Plain for ELF64Header {}
impl ELF64Header {
fn from_bytes(buf: &[u8]) -> &ELF64Header {
plain::from_bytes(buf).expect("The buffer is either too short or not aligned!")
}
fn from_mut_bytes(buf: &mut [u8]) -> &mut ELF64Header {
plain::from_mut_bytes(buf).expect("The buffer is either too short or not aligned!")
}
fn copy_from_bytes(buf: &[u8]) -> ELF64Header {
let mut h = ELF64Header::default();
h.copy_from_bytes(buf).expect("The buffer is too short!");
h
}
}
# fn process_elf(elf: &ELF64Header) {}
// Conditional copying for ultimate hackery.
fn opportunistic_elf_processing(buf: &[u8]) {
if plain::is_aligned::<ELF64Header>(buf) {
// No copy necessary.
let elf_ref = ELF64Header::from_bytes(buf);
process_elf(elf_ref);
} else {
// Not aligned properly, copy to stack first.
let elf = ELF64Header::copy_from_bytes(buf);
process_elf(&elf);
}
}
#[repr(C)]
#[derive(Default, Copy, Clone)]
struct ArrayEntry {
pub name: [u8; 32],
pub tag: u32,
pub score: u32,
}
// SAFE: ArrayEntry satisfies all the requirements of `Plain`.
unsafe impl Plain for ArrayEntry {}
fn array_from_bytes(buf: &[u8]) -> &[ArrayEntry] {
// NOTE: length is not a concern here,
// since slice_from_bytes() can return empty slice.
match plain::slice_from_bytes(buf) {
Err(_) => panic!("The buffer is not aligned!"),
Ok(arr) => arr,
}
}
fn array_from_unaligned_bytes(buf: &[u8]) -> Vec<ArrayEntry> {
let length = buf.len() / mem::size_of::<ArrayEntry>();
let mut result = vec![ArrayEntry::default(); length];
(&mut result).copy_from_bytes(buf).expect("Cannot fail here.");
result
}
# fn main() {}
与pod
的比较
pod
是另一个创建用来帮助处理纯数据的crate。与 plain
相比,pod
的主要区别在于作用域。
plain
目前仅提供少量函数(方法包装器)以及其实现涉及非常少的非安全代码。它可以用于 no_std
代码。此外,它不涉及任何方式处理字节序,因此仅适用于某些类型的底层工作。
另一方面,pod
提供了各种方法的广泛工具箱,其中大多数可能对于某个特定用例是不必要的。它依赖于 std
以及其他crate,但除此之外,它还提供了处理字节序的工具。
简而言之,plain
要简单得多...