Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
pi_async_fs
pi_async_fs 是一个运行时无关的异步目录、文件与字节 I/O 库。公共接口只使用
标准 Future、futures_core::Stream、拥有型资源和明确的缓冲区合同;调用方可以
在自己的异步执行环境中等待这些 Future 和推动这些 Stream,而不需要把某一种
异步运行时的专用类型写入业务接口。
当前版本提供可直接使用的本地文件系统适配器 LocalFileNamespace 和
LocalFile,支持 Windows、Linux 以及 Linux tmpfs。远端定位符和统一定位符的
类型形状已经公开,但远端文件系统适配器尚未提供;不要在生产代码中调用
RemoteLocator 的占位方法,也不要把 FileLocator::Remote 交给本地适配器。
主要功能
- 查询文件、目录、符号链接以及可移植元信息;
- 查询路径所属 Windows 卷或 Linux 挂载文件系统的候选可用空间;
- 惰性枚举目录直接子项,以及按深度限制递归遍历目录后代;
- 严格创建目录、递归创建目录层级、严格创建文件;
- 进程内安全删除文件或空目录,以及显式的未协调删除;
- 严格不替换改名和严格不替换复制;
- 固定窗口随机读取、固定窗口顺序读取和有上限的增长式读取;
- 严格文件尾部追加、全文件覆盖和只允许缩短的截断;
- 指定非空半开范围的只读或读写内存映射(MMAP);
- 普通文件刷新和读写映射刷新;
- 同一进程内、跨独立文件资源和线程的冲突操作协调;
- 显式、合作式的跨进程协调能力;
- 写入失败时返还原始缓冲区,并同时报告可证明的传输进度和目标状态。
当前版本不提供文件变化监听、remove_dir_all、替换式改名、顺序写、任意偏移的
普通写、目录树事务或远端对象存储能力。remove_dir 只删除空目录。
工具链与依赖
当前唯一支持并用于验收的工具链是 nightly-2026-06-25。本功能库不提供
rust-toolchain.toml,也不在 Cargo.toml 中固定 rust-version;请显式使用:
cargo +nightly-2026-06-25 build --locked
基本依赖可以写为:
[]
= "0.1.0"
= "0.1.1"
若调用方需要使用本文的 BytesMut 或 Stream 扩展示例,再直接加入对应依赖:
= "1.12"
= "2.6"
跨线程安全前置条件
最终应用的完整依赖图不得为 pi_atom 使用的同一份 pi_share 启用 rc feature。
该组合不在本库支持范围内,可能使安全 Rust 中并发使用远端名称类型失去线程安全
保证。Cargo 会合并同版本依赖的 feature,本库不能仅通过自己的 feature 表阻止
下游启用它;依赖、feature、目标平台或锁定版本发生变化后,请检查实际解析图:
cargo tree -e features -i pi_share
受支持的依赖图只允许相应的 pi_share/default,不能包含 pi_share/rc。
使用模型
本库把“通过位置管理名称空间”和“操作一个已打开文件”分成两个公共接口:
FileNamespace接收定位符,负责查询、枚举、创建、删除、改名、复制和打开;FileIo操作已经打开的文件,负责读取、追加、覆盖、截断、映射和刷新;FileAccessMode在打开或创建时为资源指定唯一角色;- 同一文件需要不同角色时,分别打开多个独立、不可克隆的文件资源;
- 完成写入后,需要何种持久性保证由调用方通过显式刷新表达。
LocalFileNamespace::new() 返回轻量、可克隆且 Send + Sync 的本地 namespace
入口。同一进程中它的所有实例和克隆遵守相同的公开协调语义。LocalFile 是拥有型
活动资源,不实现 Clone、Copy 或 Default;需要第二个资源时必须再次调用
open,不能复制一个已经打开的资源。
所有异步方法返回 Send Future。Future 可以在其借用生命周期内在线程之间迁移,
但接口不会替调用方启动或选择异步运行时。从未被轮询的 Future 不产生文件系统
副作用;一个操作开始后再丢弃 Future 不等于撤销或回滚该操作。
快速开始:追加、刷新和读取
下面的函数严格新建文件,追加完整内容,显式刷新,再通过独立读取资源读取文件头。 函数本身可以由调用方选择的任意兼容执行器驱动。
use PathBuf;
use ;
async
公共类型总览
核心接口、适配器与异步流
| 类型 | 中文名称 | 作用与使用位置 |
|---|---|---|
FileNamespace |
文件命名空间接口 | 通过定位符查询和修改名称空间,并创建独立文件资源;包含 5 个关联类型和 22 个异步方法 |
FileIo |
已打开文件输入输出接口 | 操作一个已经绑定访问角色的文件资源;包含 15 个异步方法,没有关联类型 |
LocalFileNamespace |
本地文件命名空间 | 内置的 FileNamespace<Locator = PathBuf, File = LocalFile> 适配器;可克隆、可跨线程共享 |
LocalFile |
本地文件资源 | 只能由 LocalFileNamespace 交付的不可克隆文件资源;满足 FileIo + Send + Sync |
BoxDirectoryStream<'a, L> |
装箱目录项流 | 默认的 Send 浅层目录流,每项为 pi_result::Result<DirectoryEntry<L>> |
BoxWalkStream<'a, L> |
装箱递归遍历流 | 默认的 Send 递归流,每项为 pi_result::Result<WalkEntry<L>> |
定位符、目录项和元信息
| 类型 | 中文名称 | 作用与关键边界 |
|---|---|---|
RemoteLocator |
远端定位符 | 拥有型、受校验的层级 URL;当前仅保留公共类型,行为等待远端批次 |
RemoteLocatorError |
远端定位符错误 | 表达 URL 无效、非层级、本地协议、凭据、查询串或片段等输入问题 |
FileLocator |
文件定位符 | NativePath(PathBuf) 或 Remote(RemoteLocator) 的统一位置枚举;本地适配器直接使用 PathBuf |
EntryName |
目录项名称 | Native(OsString) 无损保存本地名称,Remote(Atom) 保存远端名称 |
DirectoryEntry<L> |
目录项 | 包含直接名称、完整定位符和可选类型提示;不是打开文件,也不会自动加载完整元信息 |
FileType |
文件类型 | 表达普通文件、目录、符号链接、远端对象、设备、FIFO、套接字、其它或未知 |
PortablePermissions |
可移植权限摘要 | 用 Option<bool> 表达只读和可执行状态;未知不等于 false,也不替代 ACL 或平台权限模型 |
FileTimes |
文件时间快照 | 分别保存可选的创建、修改、访问和元信息变化时间;仅表示观察值,不证明因果顺序 |
ResourceVersion<L> |
资源版本令牌 | 把定位符与后端给出的不透明字节令牌绑定;不是时间戳,也不能跨 namespace 比较新旧 |
FileMetadata<L> |
文件元信息快照 | 聚合类型、可选长度、权限、时间和可选版本;返回后可以立即因外部变化而过期 |
AvailableSpace |
可用空间快照 | 一次查询得到的候选可用字节数;不是配额、预留或后续写入成功保证 |
DirectoryEntry 的公开字段是:
name: EntryName:相对于被枚举目录的直接子项名称;locator: L:可交回同一逻辑 namespace 的完整定位符;file_type_hint: Option<FileType>:枚举时得到的轻量提示,可能缺失或过期。
完整元信息必须通过 metadata(&entry.locator) 或
symlink_metadata(&entry.locator) 延迟查询。不要把 file_type_hint 当作后续操作的
原子前置条件。
FileMetadata 的公开字段是:
file_type: FileType;byte_len: Option<u64>,其中Some(0)是已知空内容,None是未知或不适用;permissions: PortablePermissions;times: FileTimes;version: Option<ResourceVersion<L>>。
其它拥有公开字段的数据类型如下:
| 字段 | 类型 | 语义 |
|---|---|---|
PortablePermissions::read_only |
Option<bool> |
明确只读、明确非只读或未知/不适用 |
PortablePermissions::executable |
Option<bool> |
明确可执行、明确不可执行或未知/不适用 |
FileTimes::created |
Option<SystemTime> |
后端可靠提供的创建或出生时间;Unix ctime 不属于本字段 |
FileTimes::modified |
Option<SystemTime> |
内容最后修改时间快照 |
FileTimes::accessed |
Option<SystemTime> |
后端可靠提供的最后访问时间快照 |
FileTimes::metadata_changed |
Option<SystemTime> |
元信息最后变化时间快照,与创建时间不同 |
WalkOptions::depth_limit |
WalkDepthLimit |
本次递归遍历允许产生的最大后代深度 |
WalkEntry::entry |
DirectoryEntry<L> |
当前递归遍历项目 |
WalkEntry::depth |
NonZeroUsize |
相对遍历根的深度,直接子项为 1,根本身不产生 |
主要值枚举
| 类型 | 公开变体 | 使用说明 |
|---|---|---|
EntryName |
Native(OsString)、Remote(Atom) |
本地名称不要求 UTF-8;远端名称不是跨进程序列化格式 |
FileLocator |
NativePath(PathBuf)、Remote(RemoteLocator) |
只表示位置种类,不表示目标存在或已经打开 |
FileType |
RegularFile、Directory、SymbolicLink、RemoteObject、BlockDevice、CharacterDevice、Fifo、Socket、Other、Unknown |
Other 表示已知但未单列的种类;Unknown 表示无法可靠分类 |
FileFlushMode |
Data、DataAndMetadata |
后者请求更强的普通文件刷新等级;两者都不刷新父目录或映射脏页 |
WalkDepthLimit |
Unlimited、Limited { max_depth } |
max_depth 是包含式上限;零表示不产生任何后代 |
CrossProcessCoordinationRoot |
FileParent、Custom(PathBuf) |
Custom 必须使用非空绝对路径,并在首次协调操作前配置 |
输入校验错误枚举均为 #[non_exhaustive]:
| 类型 | 当前公开变体 |
|---|---|
RemoteLocatorError |
InvalidUrl { source }、NonHierarchical、FileScheme、Credentials、Query、Fragment |
MmapRangeError |
Empty { at }、Reversed { start, end_exclusive } |
ReadTargetRegionError |
ExcludedStartOverflow、IncludedEndOverflow、Reversed { start, end_exclusive }、OutOfBounds { start, end_exclusive, initialized_len } |
ReadGrowthLimitError |
FinalLengthOverflow { current_len, max_additional_bytes } |
访问模式、范围和读取结果
| 类型 | 中文名称 | 作用与关键边界 |
|---|---|---|
FileAccessMode |
文件访问模式 | 为一个文件资源选择唯一角色,防止读取、追加、覆盖、截断和映射权限被含糊组合 |
FileFlushMode |
文件刷新模式 | Data 请求数据刷新;DataAndMetadata 还请求文件自身必要元信息刷新 |
MmapRange |
内存映射范围 | 经过校验的非空文件半开区间 [start, end) |
MmapRangeError |
映射范围错误 | Empty 表示空范围,Reversed 表示起点大于排他终点 |
ReadTargetRegion |
读取目标区域 | 指定固定读取要覆盖的、已经初始化的目标缓冲区范围 |
ReadTargetRegionError |
读取目标区域错误 | 表达端点换算溢出、反向范围或超出已初始化目标长度 |
ReadGrowthLimit |
读取增长上限 | 限制一次增长读取最多向目标尾部新增多少有效字节 |
ReadGrowthLimitError |
读取增长上限错误 | 表达当前长度与新增上限相加发生 usize 溢出 |
ReadGrowthOutcome |
读取增长结果 | EndOfFile 表示已观察到 EOF;LimitReached 表示本轮预算用尽 |
WalkDepthLimit |
遍历深度上限 | Unlimited 或包含式 Limited { max_depth };零深度产生空流 |
WalkOptions |
遍历选项 | 当前公开字段 depth_limit 控制递归深度 |
WalkEntry<L> |
递归遍历项 | 把 DirectoryEntry<L> 与相对根的非零深度绑定;直接子项深度为 1 |
ReadTargetRegion 描述的是目标缓冲区范围,不是文件范围。它支持 Rust 常见的
Range、RangeInclusive、RangeFrom、RangeTo、RangeToInclusive 和
RangeFull 转换;full() 表示目标当前全部已初始化字节。固定读取不会把
Vec 或 BytesMut 的备用容量视为已初始化内存,也不会自动扩大目标长度。
缓冲区能力和映射句柄
| 类型 | 中文名称 | 作用与关键边界 |
|---|---|---|
DetachableWriteBuffer |
可脱离写入缓冲区 | 写入源能力;提供连续只读字节视图,并能在需要时得到独立存活的 Detached 及配对 Recovery |
GrowableReadBuffer |
可增长读取缓冲区 | 增长读取目标的语义标记;当前内置支持 Vec<u8> 和 bytes::BytesMut |
ReadMmapHandle |
只读映射句柄 | 可克隆、Send + Sync 的透明只读范围守卫;通过 as_bytes() 取得零字节复制视图 |
ReadWriteMmapHandle |
读写映射句柄 | 不可克隆、Send 但非 Sync;通过独占借用修改并显式刷新映射内容 |
DetachableWriteBuffer 不要求 Clone、Sync 或外层值为 'static。它具有:
pub trait DetachableWriteBuffer: AsRef<[u8]> + Sized {
type Detached: AsRef<[u8]> + 'static;
type Recovery;
fn try_detach(
self,
) -> pi_result::RawResult<
(Self::Detached, Self::Recovery),
BufferFailure<Self>,
>;
fn recover_from_detached(
detached: Self::Detached,
recovery: Self::Recovery,
) -> Self;
}
GrowableReadBuffer 没有新增方法或关联类型。它在
AsRef<[u8]> + bytes::BufMut 之上承诺:旧内容保持为前缀,新读取的字节只提交到
逻辑尾部,提交后 AsRef<[u8]> 能看到完整已初始化内容。
失败、进度和状态证据
| 类型 | 中文名称 | 作用 |
|---|---|---|
TransferProgress |
传输进度证据 | 表达精确字节数、可靠下界或未知进度 |
BufferFailure<B> |
缓冲区可恢复失败 | 追加失败时返回统一错误、原始 B 和传输进度 |
OverwriteTargetEvidence |
覆盖目标状态证据 | 表达目标未变、是精确输入前缀、已开始变化或未知 |
OverwriteFailure<B> |
覆盖写失败 | 返回错误、原始 buffer、进度和目标状态证据 |
CreateTargetEvidence |
创建目标状态证据 | 表达本操作未创建、已经创建或无法确认 |
CrossProcessCreateSuccess<A, F> |
协调创建成功结果 | 同时拥有跨进程 authority 和首个文件资源 |
CreateFailure |
单目标创建失败 | 返回错误和目标创建状态证据 |
CreateDirectoriesFailure<L> |
目录层级创建失败 | 返回错误、已确认创建的定位符和状态不确定的定位符 |
RemoveTargetEvidence |
删除目标状态证据 | 表达名称未被本操作移除、已移除或未知 |
RemoveFailure |
删除失败 | 返回错误和删除状态证据 |
RenameCommitEvidence |
改名提交证据 | 表达名称切换未提交、已提交或未知 |
RenameFailure |
改名失败 | 返回错误和改名提交证据 |
CopyTargetEvidence |
复制目标发布证据 | 表达最终目标确定未发布,或发布状态未知及对应内容长度 |
CopyStagingEvidence |
复制临时资产证据 | 表达本操作未创建、已清理、已知仍存在或状态未知 |
CopyOutcome |
复制成功结果 | 保存成功发布内容的字节长度 |
CopyFailure |
复制失败 | 返回错误、最终目标证据和复制临时资产证据 |
状态和进度枚举的当前公开变体如下。它们均为 #[non_exhaustive],调用方必须保留
通配分支,以便兼容未来新增的、更精确的证据:
| 类型 | 公开变体及含义 |
|---|---|
TransferProgress |
Exact { bytes }:精确完成量;AtLeast { bytes }:可靠下界;Unknown:没有可靠下界 |
OverwriteTargetEvidence |
Unchanged:本操作未改变;ExactInputPrefix { bytes }:完整目标是输入的精确前缀;MutationStarted:已经开始变化;Unknown:无法证明 |
CreateTargetEvidence |
NotCreatedByOperation、CreatedByOperation、Unknown |
RemoveTargetEvidence |
NotRemovedByOperation、RemovedByOperation、Unknown |
RenameCommitEvidence |
NotRenamedByOperation、RenamedByOperation、Unknown |
CopyTargetEvidence |
NotPublishedByOperation;PublicationUnknown { content_byte_len } |
CopyStagingEvidence |
NotCreatedByOperation、CreatedThenRemovedByOperation、KnownPresentAtCompletion、Unknown |
ReadGrowthOutcome |
EndOfFile { appended_bytes };LimitReached { appended_bytes } |
证据只表示“本次操作返回时能够可靠证明什么”,不是对外部世界的永久快照。
Unknown 不表示副作用一定发生,也不表示一定没有发生;调用方必须重新查询相关
位置。所有标为 #[non_exhaustive] 的公开枚举都应使用通配分支匹配。
跨进程协调类型
| 类型或函数 | 中文名称 | 作用与关键边界 |
|---|---|---|
CrossProcessCoordinationRoot |
跨进程协调根策略 | FileParent 使用目标父目录策略;Custom(PathBuf) 指定所有协调操作共同使用的绝对根位置 |
CrossProcessFileAuthority |
跨进程文件授权 | 不透明、拥有型能力值,绑定一个具体目标实例;不是操作系统访问权限,也不能序列化后交给其它进程 |
set_cross_process_coordination_root |
设置协调根策略 | 在首次协调操作前设置一次;相同值重复设置成功,不同值冲突,不提供重置 |
跨进程保证是合作式合同:所有会影响目标身份、长度、内容、映射或名称的相关进程 都必须遵守同一套公共协调入口,并选择实际指向同一协调位置的根策略。库外句柄、 不合作程序、不同库副本、硬链接别名旁路或不一致的根配置不受 authority 强制约束。
FileAccessMode 能力矩阵
每个文件资源在完整生命周期内只有一个模式。打开 Overwrite 或 Truncate 资源
本身不会修改文件;只有显式调用相应方法才产生副作用。
| 模式 | 允许的主要 FileIo 方法 |
明确不允许 |
|---|---|---|
Read |
byte_len、六种固定或增长读取 |
追加、覆盖、截断、映射、普通文件刷新 |
Append |
byte_len、append、flush |
普通读取、覆盖、截断、映射 |
Overwrite |
byte_len、overwrite_all、flush |
普通读取、追加、截断、映射 |
ReadMmap |
byte_len、只读映射创建 |
普通读取、写入、截断、读写映射、普通文件刷新 |
ReadWriteMmap |
byte_len、只读或读写映射创建 |
普通读取、普通写入、截断、普通文件刷新 |
Truncate |
byte_len、truncate、flush |
读取、追加、覆盖、映射、扩容 |
访问模式不表示跨进程协调等级。同一模式既可用于普通资源,也可用于通过 authority 打开的协调资源;具体应调用哪组映射方法由资源来源决定。
FileIo 方法说明
| 方法签名摘要 | 中文名称 | 成功结果与使用语义 |
|---|---|---|
byte_len(&self) -> Result<u64> |
查询字节长度 | 返回一次 u64 长度快照;不是版本、锁或后续读取保证 |
read_at(&self, offset, &mut B, target) -> Result<usize> |
固定随机短读 | 从绝对偏移读入目标窗口,允许短读,返回实际字节数;不改变顺序游标 |
read_exact_at(&self, offset, &mut B, target) -> Result<()> |
固定随机精确读 | 只有完整填满目标窗口才成功;不改变顺序游标 |
read_to_end_at(&self, offset, &mut B, limit) -> Result<ReadGrowthOutcome> |
增长随机读 | 从绝对偏移向目标尾部追加,直到 EOF 或本次上限;不改变顺序游标 |
read(&mut self, &mut B, target) -> Result<usize> |
固定顺序短读 | 从当前逻辑游标读取,允许短读,并按成功提交量推进游标 |
read_exact(&mut self, &mut B, target) -> Result<()> |
固定顺序精确读 | 填满目标窗口才成功,并以本次方法合同提交游标变化 |
read_to_end(&mut self, &mut B, limit) -> Result<ReadGrowthOutcome> |
增长顺序读 | 从当前逻辑游标向目标尾部增长,直到 EOF 或本次上限 |
append(&mut self, B) -> RawResult<(), BufferFailure<B>> |
严格尾部追加 | 成功时把输入全部追加到调用时的文件尾;普通失败返回原始 B 和进度 |
overwrite_all(&mut self, B) -> RawResult<(), OverwriteFailure<B>> |
全文件覆盖 | 成功后文件内容和长度与输入完全一致;空输入产生空文件 |
truncate(&mut self, new_len) -> Result<()> |
缩短文件 | 只允许 new_len 不大于操作时观察到的当前长度;不写入内容,也不允许扩容 |
unsafe map_read_only_uncoordinated(&self, range) -> Result<ReadMmapHandle> |
未协调只读映射 | 仅在调用方自行满足所有库外并发安全前提时使用 |
map_read_only(&self, range) -> Result<ReadMmapHandle> |
协调式只读映射 | 只适用于通过有效 authority 打开的文件资源 |
unsafe map_read_write_uncoordinated(&self, range) -> Result<ReadWriteMmapHandle> |
未协调读写映射 | 在调用方承担外部前提后返回独占可写透明句柄 |
map_read_write(&self, range) -> Result<ReadWriteMmapHandle> |
协调式读写映射 | 只适用于通过有效 authority 打开的文件资源 |
flush(&mut self, mode) -> Result<()> |
刷新普通文件 | 等待请求的普通文件刷新边界;不刷新 MMAP 脏页,也不刷新父目录 |
固定读取的 B 满足:
B: AsMut<[u8]> + Send + ?Sized + 'a
增长读取的 B 满足:
B: GrowableReadBuffer + Send + 'a
追加和覆盖的 B 满足:
B: DetachableWriteBuffer + Send + 'a
B::Detached: Send
B::Recovery: Send + 'a
FileNamespace 关联类型和方法说明
关联类型
| 关联类型 | 默认类型 | 作用 |
|---|---|---|
Locator |
FileLocator |
namespace 接受的位置值;要求可克隆、可调试、判等、排序、哈希及 Send + Sync + 'static |
CrossProcessAuthority |
CrossProcessFileAuthority |
本地或后端定义的不透明跨进程授权;要求 Debug + Display + Send + Sync + 'static |
File |
无 | 每次成功创建或打开交付的独立 FileIo + 'static 资源 |
DirectoryStream<'a> |
BoxDirectoryStream<'a, Locator> |
read_dir 的流;每项为 Result<DirectoryEntry<Locator>>,流为 Send + 'a |
WalkStream<'a> |
BoxWalkStream<'a, Locator> |
walk 的流;每项为 Result<WalkEntry<Locator>>,流为 Send + 'a |
查询和流
| 方法 | 中文名称 | 成功结果与使用语义 |
|---|---|---|
metadata(&locator) -> Result<FileMetadata<Locator>> |
跟随链接查询元信息 | 返回最终解析目标的拥有型快照;不存在和无法查询是错误 |
symlink_metadata(&locator) -> Result<FileMetadata<Locator>> |
不跟随末级链接查询元信息 | 返回最终名称条目自身的快照,可用于观察悬空链接 |
try_exists(&locator) -> Result<bool> |
探测目标存在性 | 只有权威确认不存在才返回 Ok(false);权限、路径或后端错误返回 Err |
available_space(&locator) -> Result<AvailableSpace> |
查询候选可用空间 | 返回目标所属存储作用域的一次字节快照;要求定位符当前存在且可访问 |
read_dir(locator) -> Result<DirectoryStream<'a>> |
枚举直接子项 | 按值取得根位置,返回惰性目录流;根本身不产生,顺序和快照均不保证 |
walk(locator, options) -> Result<WalkStream<'a>> |
递归遍历后代 | 返回带深度的惰性流;根不产生,不跟随目录符号链接递归,不保证遍历顺序 |
创建、删除、改名和复制
| 方法 | 中文名称 | 成功结果与使用语义 |
|---|---|---|
create_dir(&locator) -> RawResult<(), CreateFailure> |
严格创建单层目录 | 父目录必须存在,最终位置必须不存在;失败返回创建证据 |
create_dir_all(&locator) -> RawResult<(), CreateDirectoriesFailure<Locator>> |
递归创建目录层级 | 已存在目录可复用;失败不自动回滚此前已创建的目录,并返回两类位置清单 |
remove_file(&locator) -> RawResult<(), RemoveFailure> |
进程内安全删除文件 | 有活动文件资源、映射或冲突操作时拒绝;成功只解除名称绑定 |
remove_file_uncoordinated(&locator) -> RawResult<(), RemoveFailure> |
未协调删除文件 | 不检查或等待本库中的活动资源;仍遵守所在平台的删除结果 |
remove_dir(&locator) -> RawResult<(), RemoveFailure> |
进程内安全删除空目录 | 只删除空目录,并与同一名称条目的冲突 namespace 操作协调 |
remove_dir_uncoordinated(&locator) -> RawResult<(), RemoveFailure> |
未协调删除空目录 | 不取得本库的进程内安全保证;仍只允许删除空目录 |
rename(&source, &destination) -> RawResult<(), RenameFailure> |
严格不替换改名 | 目标必须不存在;不降级为复制再删除,也不提供 replace |
copy_new(&source, &destination) -> RawResult<CopyOutcome, CopyFailure> |
严格不替换复制 | 目标必须不存在;成功目标具有完整复制内容,不复制权限、时间、ACL 或扩展属性 |
打开和跨进程协调
| 方法 | 中文名称 | 成功结果与使用语义 |
|---|---|---|
open(&locator, access) -> Result<File> |
打开现有文件 | 返回绑定唯一访问模式的独立文件资源;打开覆盖或截断模式本身不修改内容 |
create_new(&locator, access) -> RawResult<File, CreateFailure> |
严格新建文件 | 仅在最终位置不存在时创建空文件并返回首个资源;失败返回创建证据 |
unsafe create_new_coordinated(locator, access) -> RawResult<CrossProcessCreateSuccess<Authority, File>, CreateFailure> |
协调式严格新建 | 在调用方承担跨进程合作前提后,返回 authority 和首个独立文件资源 |
unsafe establish_cross_process_authority(&locator) -> Result<Authority> |
为现有文件建立授权 | 在调用方承担合作前提后,为当前目标实例返回不透明 authority |
open_with_cross_process_authority(&authority, access) -> Result<File> |
使用授权打开文件 | 不再接收 locator;返回继续受同一跨进程合同约束的独立文件资源 |
remove_file_with_cross_process_authority(&authority) -> RawResult<(), RemoveFailure> |
使用授权删除文件 | 只删除 authority 精确绑定的目标实例;有合作式冲突时立即拒绝 |
unsafe resume_coordinated_file_removal(&locator) -> RawResult<(), RemoveFailure> |
恢复未完成的协调删除 | 只用于所有内存 authority 已消失后的恢复路径;不能用来开始一次普通新删除 |
Namespace 组合示例
下面的示例覆盖递归创建目录、严格新建文件、查询元信息和空间、严格改名,以及
进程内安全删除。每个专用失败载体都必须先拆出统一错误,不能当作普通
pi_result::Error 静默丢弃其状态证据。
use PathBuf;
use ;
async
公共构造器与访问器说明
下表覆盖当前所有公共固有函数、固有方法和两个公共自由函数。失败载体的
into_parts 均消费自身并按照对应 new 的参数顺序返还全部资产。
| 类型或函数 | 公共成员 | 说明 |
|---|---|---|
LocalFileNamespace |
new() |
取得本地 namespace;不打开文件,也不执行文件操作 |
set_local_blocking_capacity |
(NonZeroUsize) -> pi_result::Result<()> |
设置进程级本地阻塞准入容量;相同值可重复设置,不同值冲突 |
set_cross_process_coordination_root |
(CrossProcessCoordinationRoot) -> pi_result::Result<()> |
设置一次性跨进程协调根策略;不提供重置 |
AvailableSpace |
new、available_bytes |
构造快照或读取其 u64 字节数 |
MmapRange |
new、start、end_exclusive、len |
校验、检查非空半开文件范围;也支持 TryFrom<Range<u64>> |
ReadTargetRegion |
new、full、start、end_exclusive、resolve |
构造逻辑目标区域,并按具体缓冲区初始化长度解析为安全 Range<usize> |
ReadGrowthLimit |
new、max_additional_bytes、checked_final_len |
构造增长预算、读取预算、受检计算最大最终长度 |
ReadGrowthOutcome |
appended_bytes、is_end_of_file、is_limit_reached |
统一读取成功结果中的新增量和停止原因 |
RemoteLocator |
new、as_url、as_str、into_url |
校验构造、借用或取回 URL;当前行为等待远端批次 |
DirectoryEntry<L> |
new(name, locator, file_type_hint) |
按公开字段顺序构造拥有型目录项 |
ResourceVersion<L> |
new、locator、token、into_parts |
绑定位置和不透明 Arc<[u8]> 令牌,或借用/拆解它们 |
FileMetadata<L> |
new(file_type, byte_len, permissions, times, version) |
按公开字段顺序构造元信息快照 |
WalkDepthLimit |
maximum_depth |
Unlimited 返回 None,有限深度返回 Some(max_depth) |
WalkOptions |
new(depth_limit) |
显式构造遍历选项;没有隐式默认深度 |
WalkEntry<L> |
new(entry, depth)、into_parts |
组合或拆解拥有型目录项与非零相对深度 |
TransferProgress |
minimum_bytes、exact_bytes、is_exact、is_uncertain |
在不误解下界或未知值的情况下读取进度证据 |
BufferFailure<B> |
new、error、buffer、progress、into_parts |
借用失败信息,或一次性取回错误、原始 buffer 和进度 |
OverwriteFailure<B> |
new、error、buffer、progress、target_evidence、into_parts |
借用或取回覆盖错误的全部四项资产 |
CrossProcessCreateSuccess<A, F> |
new、authority、file、file_mut、into_parts |
同时管理 authority 和首个文件资源,或消费后分别取得所有权 |
CreateFailure |
new、error、target_evidence、into_parts |
借用或取回创建错误和目标证据 |
CreateDirectoriesFailure<L> |
new、error、confirmed_created、uncertain_targets、into_parts |
借用或取回递归创建的错误及两组位置清单 |
RemoveFailure |
new、error、target_evidence、into_parts |
借用或取回删除错误和目标证据 |
RenameFailure |
new、error、commit_evidence、into_parts |
借用或取回改名错误和提交证据 |
CopyOutcome |
new、content_byte_len |
构造成功值或读取已发布内容长度 |
CopyFailure |
new、error、target_evidence、staging_evidence、into_parts |
借用或取回复制错误及两类状态证据 |
ReadMmapHandle |
range、len、as_bytes |
查询逻辑范围和长度,或借用只读映射字节 |
ReadWriteMmapHandle |
range、len、as_bytes、as_bytes_mut、flush |
查询范围、读取、独占修改和刷新映射内容 |
PortablePermissions、FileTimes、WalkOptions、WalkEntry、DirectoryEntry 和
FileMetadata 的字段本身就是公共数据面;读取这些字段不执行 I/O。具体资源类
型、权限、时间和版本仍然只是对应查询时的快照。
常用转换和能力 trait
| 类型 | 公共转换或能力 |
|---|---|
EntryName |
From<OsString>、From<&OsStr>、From<pi_atom::Atom> |
RemoteLocator |
AsRef<Url>、TryFrom<Url>、FromStr、From<RemoteLocator> for Url;当前行为等待远端批次 |
FileLocator |
From<PathBuf>、From<&Path>、From<RemoteLocator>、TryFrom<Url> |
MmapRange |
TryFrom<Range<u64>> |
ReadTargetRegion |
TryFrom<Range<usize>>、TryFrom<RangeInclusive<usize>>、From<RangeFrom<usize>>、From<RangeTo<usize>>、TryFrom<RangeToInclusive<usize>>、From<RangeFull> |
ReadMmapHandle |
AsRef<[u8]>、DetachableWriteBuffer、Clone + Send + Sync |
ReadWriteMmapHandle |
AsMut<[u8]> + Send,明确不实现 Clone 和 Sync |
CrossProcessCoordinationRoot |
Default,默认值为 FileParent |
值类型按各自字段能力提供 Debug、Display、判等、排序或哈希;失败载体和泛型
记录只有在其类型参数满足相应约束时才获得条件实现。格式化文本只供人阅读,不是
稳定序列化协议;排序只为集合和确定性输出服务,不表示权限强弱、版本新旧或操作
优先级。
Buffer 支持矩阵
写入源
调用时的 B |
是否内置支持 | 需要复制字节的典型情况 |
|---|---|---|
Vec<u8> |
是 | 否 |
Box<[u8]> |
是 | 否 |
Arc<[u8]> |
是 | 否 |
Cow<'a, [u8]> |
是 | borrowed 变体在需要脱离借用期时需要复制 |
bytes::Bytes |
是 | 否 |
bytes::BytesMut |
是 | 否 |
&[u8]、&Vec<u8>、&Box<[u8]> |
是 | 在需要脱离借用期时复制 |
&Arc<[u8]>、&bytes::Bytes |
是 | 不复制字节,但会取得临时共享所有权 |
&Cow<'_, [u8]>、&bytes::BytesMut |
是 | 在需要脱离借用期时复制 |
ReadMmapHandle、&ReadMmapHandle |
是 | 不复制映射字节;不能作为自身底层文件的写入源 |
数组没有单独实现 DetachableWriteBuffer;可以把数组借用为 &[u8]。第三方类型
不会仅因为实现 AsRef<[u8]> 自动成为合法写入源,还必须可靠实现
DetachableWriteBuffer 的脱离、配对恢复和字节等价合同。
读取目标
| 类型 | 固定读取目标 | 增长读取目标 | 备注 |
|---|---|---|---|
[u8]、&mut [u8]、[u8; N] |
是 | 否 | 固定读取只覆盖已初始化范围 |
Vec<u8> |
是 | 是 | 固定读取不改变长度;增长读取向尾部追加 |
Box<[u8]> |
是 | 否 | 固定长度 |
bytes::BytesMut |
是 | 是 | 固定读取覆盖当前初始化内容,增长读取可以扩容 |
ReadWriteMmapHandle |
是 | 否 | 不能把同一文件的可写映射作为该文件普通读取目标 |
Arc<[u8]>、bytes::Bytes、ReadMmapHandle |
否 | 否 | 只读视图不能作为读取目标 |
读取示例
固定随机读取和有上限增长读取
use PathBuf;
use ;
async
ReadGrowthOutcome::LimitReached 不证明文件还有下一字节,也不证明已经 EOF;它只
证明本轮允许新增的字节预算已经用尽。若调用方要继续读取,应使用新的明确上限
再次调用,而不是改成无界增长。
随机读取不会改变文件资源的顺序游标。顺序读取使用 &mut self,每个独立打开的
资源都有自己的逻辑读取位置;不要从一个资源的读取位置推断另一个资源的位置。
目录流示例
use PathBuf;
use StreamExt;
use ;
async
async
目录流的创建错误由建立流的 Future 返回;建立成功后发现的错误作为流项目返回。
一个流只允许由一个消费者按标准 Stream 规则推动,不保证 Sync、Unpin、
固定顺序或目录快照。枚举期间并发创建、删除或改名不会由目录流自动互斥,因此
项目可能反映不同观察时刻;需要一致快照的业务必须在更高层建立相应协议。
写入失败恢复示例
成功追加返回 (),不返回原始 buffer;普通失败通过 BufferFailure<B> 返还调用
时的原始 B。取消 Future 没有失败值交付通道,因此不能依赖取消取回 buffer。
use ;
async
TransferProgress 的语义如下:
Exact { bytes }:已经确认恰好传输了该字节数;AtLeast { bytes }:只能确认至少传输了该字节数,实际值可能更大;Unknown:无法给出可靠下界。
覆盖失败还必须同时检查 OverwriteTargetEvidence:
Unchanged:本操作没有改变目标;ExactInputPrefix { bytes }:目标完整内容可证明为输入的精确前缀;MutationStarted:目标已经开始变化,但无法给出精确内容;Unknown:目标状态无法可靠证明。
取回原始 buffer 只解决资产所有权问题,不证明写操作没有产生副作用。除非进度和 目标证据都允许,否则不能从头盲目重试追加或覆盖。
覆盖、刷新和缩短示例
覆盖与截断使用不同的资源角色。覆盖成功后内容精确等于输入;截断只缩短长度, 不能用来扩容,也不接收新内容。
use PathBuf;
use ;
async
内存映射使用
MmapRange 只接受非空半开区间 [start, end)。例如 [0, 4096) 包含偏移
0..=4095;相邻范围 [0, 4096) 与 [4096, 8192) 不相交。
- 同一文件可以同时存在任意数量的不相交映射;
- 任意相交范围都会被拒绝,不区分只读或读写权限;
- 活动映射与同文件普通读取、覆盖、截断、普通文件刷新和安全删除互斥;
- 已经建立的映射可以与之后开始的严格尾部追加并存;
- 正在执行追加时不能同时建立新映射;
- 后续追加不会扩大既有映射的范围;
- 映射字节只能通过透明句柄访问;
ReadWriteMmapHandle::flush刷新映射修改,FileIo::flush不会替代它;Drop释放句柄拥有的公开资源,但不会隐式刷新修改。
普通资源只能调用两个 unsafe ..._uncoordinated 映射入口。它们的 unsafe 表示
调用方必须保证其它进程和所有库外访问不会破坏文件长度、身份及映射安全;它不
表示调用方可以绕过本库公开声明的同进程冲突规则。安全的 map_read_only 和
map_read_write 只接受通过有效跨进程 authority 打开的资源。
协调式只读映射示例
use PathBuf;
use ;
async
ReadMmapHandle::as_bytes() 返回的切片只在句柄借用期间有效。克隆只读句柄得到的
是同一个逻辑映射的共享读取能力,不是另一次范围申请。最后一个克隆释放后,该
逻辑映射不再可访问。
ReadWriteMmapHandle 可以整体移动到另一个线程,但不能共享并发写,也不能克隆。
修改必须使用 as_bytes_mut(),需要可观察的刷新结果时必须显式等待 flush()。
严格复制、改名和删除
copy_new
- 目标必须不存在,存在任意条目都会失败;
- 成功时最终目标具有本次操作承诺的完整内容;
- 不替换现有目标;
- 不复制权限、时间、ACL、扩展属性、备用数据流或后端专有元信息;
- 源文件并发变化时,不提供内容版本快照保证;
- 失败时分别检查
CopyTargetEvidence和CopyStagingEvidence; - 暂不保证掉电、操作系统崩溃或硬件故障边界上的发布原子性。
use PathBuf;
use ;
async
rename
rename 只提供严格不替换的名称切换。目标存在、跨越不支持的存储作用域或平台
拒绝改名时返回错误;不会自动降级为复制后删除。默认改名不与已经打开的普通内容
资源或活动映射建立额外互斥,平台对占用中的对象有额外限制时,以明确错误返回。
删除
remove_file 和 remove_dir 是进程内安全入口:遇到本库已知的冲突资源或操作时
立即失败,不等待调用方释放资源。remove_dir 及其未协调版本都只删除空目录。
remove_file_uncoordinated 和 remove_dir_uncoordinated 不检查本库的活动资源和
namespace 冲突。它们仍是内存安全的 Rust API,但调用方必须自行承担操作排序;
删除成功只表示名称绑定已解除,不保证底层数据立即物理删除、空间立即回收或所有
既有平台句柄立即失效。
跨进程协调使用边界
调用方可以在第一次协调操作前设置进程级根策略:
use PathBuf;
use ;
Custom 必须是非空绝对路径。成功设置只表示配置被接受,不证明目录当前存在、
可访问或适合目标环境;这些条件会在实际建立 authority 时报告。首次协调操作后
配置被冻结,相同表示可以幂等重复设置,不同表示返回冲突。
两个建立 authority 的函数是 unsafe:
create_new_coordinated为尚不存在的目标建立协调关系并严格创建文件;establish_cross_process_authority为已存在文件建立协调关系。
unsafe 的原因是 Rust 类型系统无法验证其它进程、库外文件句柄和部署配置是否
遵守合作合同。建立成功后,通过 open_with_cross_process_authority 得到的文件
资源可以调用不带 unsafe 的协调式映射方法;这不会让普通 open、普通删除或
普通资源自动获得跨进程保证。
CrossProcessFileAuthority 不实现 Clone 或 Copy。旧 authority 不能用于同名
删除后重新创建的新文件,也不能用于另一个 namespace 或另一个目标。协调式删除
必须调用 remove_file_with_cross_process_authority;正常业务路径不要调用仅供恢复
未完成删除使用的 resume_coordinated_file_removal。
本地阻塞准入容量
set_local_blocking_capacity(NonZeroUsize) 设置本库公开定义的进程级本地阻塞工作
在途容量。容量同时计算已经获准等待执行和正在执行的相关工作;达到上限时,尚未
提交的调用返回 ErrorKind::ResourceExhausted,而不是无限等待。
use NonZeroUsize;
use set_local_blocking_capacity;
首次显式配置或首次相关操作会冻结该进程级值。相同值可幂等重复设置,不同值返回
Conflict,运行期间不能重置。未显式设置时当前版本采用 1000;该默认值不是稳定
常量,需要稳定部署预算的应用应主动设置。这个数值不是线程数、文件句柄数或全部
异步任务数,也不改变其它工作来源的并行度。
并发、生命周期和取消
同一文件的主要并发规则
这些规则按实际文件对象生效,而不是只比较路径文本;不同路径和硬链接可能仍然 指向同一文件。
| 操作组合 | 公开语义 |
|---|---|
| 多个普通只读操作 | 可以并发;顺序读取仍要求各自资源的独占借用 |
| 多个追加调用 | 可以从独立资源发起,但同一文件的完整调用不会让字节互相穿插 |
| 已建立映射与之后的追加 | 可以并存;追加不扩大映射范围 |
| 正在执行的追加与新映射建立 | 不能同时进入 |
| 多个不相交映射 | 可以并存 |
| 任意相交映射 | 拒绝,不区分权限 |
| 活动映射与普通读取、覆盖、截断、文件刷新或安全删除 | 拒绝 |
| 覆盖或截断与其它内容操作 | 按其排它语义拒绝冲突调用 |
| 默认改名与已打开文件或映射 | 本库不额外互斥;是否成功仍受平台约束 |
| namespace 元信息查询与内容操作 | 可以并存,但查询结果只是瞬时快照 |
不要通过克隆或复制一个已打开文件资源创建并发通道。需要多个角色或线程独立操作
同一文件时,每个通道都应从同一个逻辑 namespace 独立 open,并保留各自资源的
所有权边界。
Future 和 Stream 生命周期
- 返回 Future 的生命周期与其所借用的 namespace、文件资源、定位符或 buffer
一致,不要求调用方把所有输入都提升为
'static; - Future 为
Send不等于资源可以被克隆,也不等于同一 Future 可以并发轮询; - 从未轮询的 Future 没有文件副作用;
- 操作开始后取消不保证回滚,也不会产生可供调用方接收的成功值、失败证据或原始 写入 buffer;
- 目录 Stream 可以整体在线程之间移动,但只能由一个消费者按固定规则轮询;
- 映射切片的生命周期绝不能超过透明映射句柄。
错误、幂等性和持久性
普通错误使用 pi_result::Result<T>。需要返还调用方资产或副作用证据的方法使用
pi_result::RawResult<T, E>,其中 E 是本库的专用失败载体。调用方应同时检查:
error()或into_parts()返回的统一错误;- 原始 buffer 或其它拥有型资产;
- 传输进度;
- 创建、删除、改名、复制或覆盖的状态证据。
不要解析 Display 或 Debug 文本建立程序逻辑;应使用错误分类、枚举变体和公开
访问器。可报告的输入、能力、角色、冲突和 I/O 失败均通过返回值表达,不应依赖
panic 处理正常错误。
幂等性边界:
- 查询可以重复调用,但外部状态变化时结果可以不同;
- 相同的全局配置值可以幂等重复设置;
create_new、create_dir、append、rename和copy_new不是无条件幂等操作;create_dir_all可能在失败前已经创建一部分目录;- 失败证据为
Unknown时必须重新观察,不能假定原请求可安全重试; - 刷新可以重复请求,但每次只对调用时已经可见的相应修改建立保证。
写入、覆盖或截断成功只表示相应普通文件操作成功完成,不自动等于强持久化。
普通文件使用 FileIo::flush(FileFlushMode);映射修改使用
ReadWriteMmapHandle::flush()。两类刷新都不承诺父目录名称变更已经同步,也不保证
掉电、操作系统崩溃、失信存储控制器、介质损坏或硬件故障后的绝对存续。
注意事项与使用禁忌
- 不要用“先
try_exists、再创建/改名”模拟原子不替换;直接使用create_new、rename或copy_new。 - 不要把
try_exists的查询结果、元信息、长度、可用空间或目录项类型提示当作 后续操作的锁或稳定前置条件。 - 不要把
ReadTargetRegion当成文件范围;它只描述目标缓冲区中的初始化区域。 - 不要把
ReadGrowthLimit当成最终 buffer 长度;它限制本次调用的新增量。 - 不要把短读当成错误;需要完整窗口时使用
read_exact或read_exact_at。 - 不要把备用容量当作已经初始化的读取目标;固定读取不会写入未初始化容量。
- 不要从取回原始 buffer 推导写操作没有副作用,也不要忽略
TransferProgress。 - 不要把
AtLeast当作精确进度,不要把Unknown当作零进度。 - 不要忽略覆盖、创建、删除、改名和复制失败中的状态证据。
- 不要用顺序读取位置或“定位到尾部”模拟严格追加。
- 不要把
truncate用于扩容;它只允许缩短。需要新完整内容时使用overwrite_all。 - 不要让同一文件的映射作为该文件自身的追加、覆盖或普通读取 buffer。
- 不要通过映射句柄以外的引用、裸地址或其它资源访问映射范围。
- 不要依赖映射句柄
Drop或文件资源Drop自动刷新。 - 不要把
FileIo::flush当作映射刷新,也不要把映射刷新当作普通文件刷新。 - 不要从路径字符串相等或不等推导文件身份;路径别名和硬链接可能指向同一对象。
- 不要把普通资源的同进程协调描述成跨进程安全。
- 不要在无法满足所有外部合作前提时调用任何
unsafe协调或未协调映射入口。 - 不要把 authority 当作可序列化的跨进程令牌、系统权限或永久锁。
- 不要把未协调删除解释为立即物理删除或既有句柄立即失效。
- 不要假定
read_dir或walk产生稳定顺序或目录快照。 - 不要对一个 Stream 并发轮询,也不要让映射切片比句柄存活更久。
- 不要为
pi_atom使用的同一份pi_share启用rcfeature。 - 不要调用当前尚不可用的远端定位符行为或假定本地适配器接受 URL。
构建与验证
建议使用与当前支持边界一致的串行单 crate 命令:
cargo +nightly-2026-06-25 test --locked --all-features -- --test-threads=1
cargo +nightly-2026-06-25 test --release --locked --all-features -- --test-threads=1
cargo +nightly-2026-06-25 clippy --locked --all-targets --all-features -- -D warnings
RUSTDOCFLAGS="-D warnings" cargo +nightly-2026-06-25 doc --locked --all-features --no-deps
需要查看每个公开枚举变体、字段、泛型约束和完整签名时,可生成并打开本库 Rustdoc:
cargo +nightly-2026-06-25 doc --locked --all-features --no-deps --open
许可证
MIT