18 个版本
0.6.3 | 2024年3月14日 |
---|---|
0.5.1 | 2022年4月2日 |
0.5.0 | 2021年12月24日 |
0.4.4 | 2021年2月20日 |
0.1.3 | 2019年2月9日 |
#111 in 文件系统
2,737 每月下载量
在 2 crates 中使用
150KB
2K SLoC
vmap-rs
跨平台库,用于快速、安全的内存映射I/O和无边界环形缓冲区。
该库定义了一个方便的API,用于使用宿主虚拟内存系统读写文件,以及分配内存和创建环形内存区域。API的设计旨在最小化映射系统调用的频率,同时仍保持安全访问。关键的是,它从不尝试拥有用于映射的 File
对象。也就是说,它永远不会克隆它或以任何方式保留它。虽然这给API带来了一些影响(例如,.flush()
),但它不会通过 File
的泄露抽象在克隆后关闭时引发库外部的bug。
Map
和 MapMut
类型是分配虚拟内存区域的主要方式,无论是文件还是匿名。通常,Map::with_options()
和 MapMut::with_options()
用于指定映射要求。有关更多信息,请参阅 Options
。
类型 MapMut
维护了映射内存的内部可变性,而 Map
是只读的。然而,在指定适当的 Options
后,可以在这些类型之间进行转换(.into_map_mut()
和 .into_map()
)。
此外,在 vmap::io
模块中提供了各种缓冲区实现。结构体 Ring
和 InfiniteRing
使用跨平台的优化环形内存映射来消除大多数环形缓冲区常见的边界问题。这确保了底层字节数组的所有范围都可以被视为一个单一的字节切片,即使值绕回缓冲区的开始处也是如此。结构体 BufReader
和 BufWriter
使用 Ring
作为底层层来实现缓冲输入/输出。
有关详细信息,请参阅 文档!
示例
use vmap::Map;
use std::{fs, str};
let path = "example";
// Write some test data
fs::write(&path, b"this is a test")?;
// Map the first 4 bytes
let (map, file) = Map::with_options().len(4).open(&path)?;
assert_eq!(Ok("this"), str::from_utf8(&map[..]));
// Reuse the file to map a different region
let map = Map::with_options().offset(10).len(4).map(&file)?;
assert_eq!(Ok("test"), str::from_utf8(&map[..]));
如果正确打开,可以将 Map
移动到 MapMut
,并对底层文件进行修改
use vmap::Map;
use std::{fs, str};
let path = "example";
// Write some test data
fs::write(&path, b"this is a test")?;
// Open with write permissions so the Map can be converted into a MapMut
let (map, file) = Map::with_options().write().len(14).open(&path)?;
assert_eq!(Ok("this is a test"), str::from_utf8(&map[..]));
// Move the Map into a MapMut
// ... we could have started with MapMut::with_options()
let mut map = map.into_map_mut()?;
map[..4].clone_from_slice(b"that");
// Flush the changes to disk synchronously
map.flush(&file, Flush::Sync)?;
// Move the MapMut back into a Map
let map = map.into_map()?;
assert_eq!(Ok("that is a test"), str::from_utf8(&map[..]));
环形缓冲区
vmap
库包含一个 Ring
,它构建了一个环形内存分配,其中值可以从缓冲区末尾绕回到开始的连续内存地址。类似地,InfiniteRing
允许写入覆盖读取。
use vmap::io::{Ring, SeqWrite};
use std::io::{BufRead, Read, Write};
let mut buf = Ring::new(4000).unwrap();
let mut i = 1;
// Fill up the buffer with lines.
while buf.write_len() > 20 {
write!(&mut buf, "this is test line {}\n", i)?;
i += 1;
}
// No more space is available.
assert!(write!(&mut buf, "this is test line {}\n", i).is_err());
let mut line = String::new();
// Read the first line written.
let len = buf.read_line(&mut line)?;
assert_eq!(line, "this is test line 1\n");
line.clear();
// Read the second line written.
let len = buf.read_line(&mut line)?;
assert_eq!(line, "this is test line 2\n");
// Now there is enough space to write more.
write!(&mut buf, "this is test line {}\n", i)?;
依赖关系
~240KB