#uninitialized-memory #memory #read-write #plain #ffi #utility #no-std

no-std memory_slice

在可能未初始化的内存上创建的内存切片,允许安全地进行借阅检查的读取、写入和重解释任何类型的数据

3个版本

0.1.0-preview32020年9月26日
0.1.0-preview2020年9月25日

#296 in 内存管理

MIT/Apache

36KB
436

LICENSE LICENSE Documentation Crates.io Version

Memory-Slice

memory_slice可以代理任何类型的数据,并提供一个API,允许用户读取、写入和借阅任何类型的数据。

功能

  • 使用对齐检查读取和写入任何类型的数据。
  • 在缓冲区中写入数据并获取一个智能指针,当智能指针被丢弃时,该智能指针将销毁缓冲区中的对象。
  • 使用静态借阅检查器确保缓冲区中任何借阅的数据上都不能进行写入操作。
  • 提供API以在堆栈上创建具有对齐要求的静态大小缓冲区。
  • 无std。

示例

任何类型的数据都可以被视为常量内存切片

use memory_slice::AsMemory;
let v: [u8;4] = [1,1,1,1];
//as_memory return a &memory_slice
assert_eq!(unsafe{v.as_memory().read::<i32>()},1 + (1<<8) + (1<<16) + (1<<24));

但只有不保留任何不变性的类型才能作为可变内存切片访问

这将编译

use memory_slice::AsMutMemory;
let mut v: [u8;4] = [1,1,1,1];
//as_memory return a &memory_slice
v.as_mut_memory().write(16 as u16);

这将不会编译

use memory_slice::AsMutMemory;
use std::string::String;
let mut v = String::new();
//as_memory return a &memory_slice
v.as_mut_memory().write(16 as u16); //compilation failure

可变内存切片可用于写入任何类型的信息,同时保留借阅规则。API还提供了一个智能指针,该指针将在内存切片上创建的值被丢弃时销毁该值

use memory_slice::{align,AsMutMemory,AsMemory};
// creates an array of 64 u8 aligned as 8: 
let mut buff = align!(8,[0 as u8;64]);

//the create an int inside the buffer and get a reference to it
let (padding, v1, remaining_buffer) = buff.as_mut_memory().write(42 as i32);
assert!(padding.is_empty());
//unsafe{buff[0]}; //error => cannot borrow buff as immutable

//use the remaining unitialized buffer to write an u64 in it:
let (padding, v2, remaining_buffer2) = remaining_buffer.write(42 as u64);
assert_eq!(padding.len(), 4);
//unsafe{remaing_buffer.read::<u8>()}; //error => cannot borrow remaining_buffer

//v1 and v2 are reference to the i32 and u64 created inside buff
assert_eq!(*v1 as u64, *v2);

{
    extern crate alloc;
    use alloc::borrow::ToOwned;

    //In what remains of the buffer, let's create a value that needs to be dropped:
    let (_padding, v3, _remaining) = remaining_buffer2.emplace("42".to_owned());

    //v3 is a smart pointer to the String created in the buffer that will drop
    //this string when it goes out of scope
    assert_eq!(*v1, v3.parse::<i32>().unwrap());
} //string refered by v3 is dropped

//buff is not anymore borrowed, so it is accessible:
assert_eq!(unsafe { buff.as_memory().read::<i32>() }, 42);

//memory slice can be indexed (!!less inoffensive than it looks)
unsafe{*buff.as_mut_memory()[2..4].as_mut_unchecked()=16 as u16};
assert_ne!(unsafe { buff.as_memory().read::<i32>() }, 42);

提供了一个名为buffer的宏来创建未初始化的缓冲区

use memory_slice::buffer;
// create an uninitialized buffer of 64 bytes aligned as 8.
let mut buff = buffer!(64,8);
// buffer are dereferencable as memory_slice

//the create an int inside the buffer and get a reference to it
buff.write(42 as i32);

依赖项

~1.5MB
~36K SLoC