#pod #memory #memory-safe #ffi

无需std plain

一个小的Rust库,允许用户安全地重新解释某些类型的数据

4个版本 (2个重大更新)

使用旧的Rust 2015

0.2.3 2017年11月24日
0.2.2 2017年11月24日
0.2.1 2017年7月29日
0.1.0 2017年4月11日
0.0.2 2017年4月4日

#281 in 解析工具

Download history 118872/week @ 2024-03-14 126674/week @ 2024-03-21 119589/week @ 2024-03-28 162301/week @ 2024-04-04 128236/week @ 2024-04-11 140630/week @ 2024-04-18 126012/week @ 2024-04-25 132606/week @ 2024-05-02 129143/week @ 2024-05-09 136548/week @ 2024-05-16 128084/week @ 2024-05-23 146966/week @ 2024-05-30 128974/week @ 2024-06-06 136588/week @ 2024-06-13 131959/week @ 2024-06-20 104425/week @ 2024-06-27

530,967每月下载量
用于 981 个crate (23直接)

MIT/Apache

23KB
287 代码行

libplain

Build Status Current Crates.io Version Current Documentation

一个小的Rust库,允许用户安全地将字节序列解释为某些类型的结构。

此crate提供了一个不安全的特质 Plain,用户使用此特质标记对此库操作安全的类型。参见 Plain 的合同义务。

除此之外,此crate中的所有其他内容在Plain特质不在不允许的类型上实现的情况下(类似于标准库中的SendSync)都是完全安全的。

用途

在底层系统开发中,有时需要将内存位置解释为数据结构。此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 要简单得多...

无运行时依赖