#未初始化内存 #内存安全 #切片 #可能未初始化 #缓冲区 #初始化 #特质

无 std uninit-tools

一个允许在安全代码中完全处理未初始化内存的 crate

7 个版本

0.0.7 2021 年 4 月 27 日
0.0.6 2021 年 4 月 11 日

2619Rust 模式

每月 21 下载

MIT 许可证

125KB
2K SLoC

示例

一个类似于 Read 的特质实现,以更好地支持未初始化内存。


use std::mem::MaybeUninit;

use uninit_tools::buffer::{Buffer, BufferRef};
use uninit_tools::traits::Initialize;

pub trait MyRead {
    // NOTE: The function does not return any count, since the buffer keeps track of that.
    //
    // Rather than using `&mut Buffer<T>` directly, we use `BufferRef<'_, T>` to prevent the
    // caller from replacing the buffer that is being filled with something different. It also
    // gives the `Read` implementor a reduced subset of the functionality, to that it cannot
    // for example read the bytes that are already written into the buffer.
    fn read<'buffer, T>(&mut self, buffer: BufferRef<'buffer, T>) -> io::Result<()>
    where
        T: Initialize<Item = u8>,
    ;
}

impl MyRead for &[u8] {
    fn read<'buffer, T>(&mut self, mut buffer: BufferRef<'buffer, T>) -> io::Result<()>
    where
        T: Initialize<Item = u8>,
    {
        // Get the minimum number of bytes to copy. Note that it will panic if the source slice
        // were to overflow, as with the regular `copy_from_slice` function for regular slices.
        let min = std::cmp::min(self.len(), buffer.remaining());

        // Advance the buffer by simply copying the source slice.
        buffer.append(&self[..min]);

        Ok(())
    }
}


// NOTE: The `Initialize` trait is implemented for arrays of all sizes, thanks to const
// generics.
let array = [MaybeUninit::uninit(); 32];
let len = array.len();
let mut buf = Buffer::uninit(array);

let original_stupid_text: &[u8] = b"copying is expensive!";
let mut stupid_text = original_stupid_text;

// Read as many bytes as possible.
stupid_text.read(buf.by_ref())?;

// Note that while we cannot do anything useful with the rest of the buffer, we can still use
// it as the destination of even more I/O, or simply check its length like we do here.
assert_eq!(buf.remaining(), len - original_stupid_text.len());



请注意,这可能不是 Read 特质的最佳实现,但它确实表明未初始化内存的处理可以完全在安全代码中完成,且相对方便。

(如果将其纳入 std::io::Read,可能会有一个更简单的 unsafe 函数,默认使用更安全的包装器。)

依赖