Releases: al8n/fs4
Releases · al8n/fs4
v1.1.0
Changes
- Consolidate
FileExtandAsyncFileExtinto single crate-root traits
(fs4::FileExt,fs4::AsyncFileExt) instead of generating a distinct
trait per backend module. The per-backend modules (fs4::tokio,
fs4::async_std,fs4::smol,fs4::fs_err2,fs4::fs_err3,
fs4::fs_err2_tokio,fs4::fs_err3_tokio) now re-export the unified
crate-root trait. Method-call sites that import the trait viause
continue to compile unchanged; code that named two backend traits as
distinct types will see them unify. - Add blanket impls
impl<F: FileExt + ?Sized> FileExt for &Fand
impl<F: AsyncFileExt + ?Sized> AsyncFileExt for &F, so the
extension methods are now callable through shared references. - Seal
FileExtandAsyncFileExtvia a privatesealed::Sealed
supertrait, so the set of implementing types is closed to the
concrete file types fs4 already supports (and references to them).
This locks in the freedom to add methods to either trait in future
minor releases without breaking downstream impls. - Add
DynAsyncFileExt, an object-safe mirror ofAsyncFileExtwhose
async methods returnBoxFuture<'_, T>(alias for
Pin<Box<dyn Future<Output = T> + Send + '_>>). Use it whenever
type erasure is needed (Box<dyn DynAsyncFileExt>,
&dyn DynAsyncFileExt); prefer the staticAsyncFileExtfor
generic code since it has no allocation or dynamic-dispatch
overhead. Every type implementingAsyncFileExtalso implements
DynAsyncFileExt, and the trait is sealed. - Mark the delegating methods
#[inline(always)](skipped under
tarpaulincoverage builds).
v1.0.0
1.0.0
Breakage
- Renamed
FileExt::lock_exclusive/AsyncFileExt::lock_exclusiveto
lock, matching the stabilized [std::fs::File::lock] API. - Renamed
FileExt::try_lock_exclusive/AsyncFileExt::try_lock_exclusive
totry_lock, matching [std::fs::File::try_lock]. - Changed the return type of
try_lockandtry_lock_sharedfrom
std::io::Result<bool>toResult<(), TryLockError>.Ok(())still
indicates the lock was acquired;Err(TryLockError::WouldBlock)now
indicates the lock is held by another handle. This matches the stable
[std::fs::File::try_lock] signature (Ok(false)was the nightly
shape prior to 1.89). - Removed the top-level
lock_contended_error()helper. Use
TryLockError::WouldBlockinstead. - Flattened the
fs_stdmodule: theFileExttrait for
std::fs::Filenow lives at the crate root. Update imports from
use fs4::fs_std::FileExt;touse fs4::FileExt;. All other
backends (fs_err2,fs_err3,tokio,smol,async_std,
fs_err2_tokio,fs_err3_tokio) remain nested, since each
defines its ownFileExt/AsyncFileExtover a different concrete
Filetype.
Additions
- New
fs4::TryLockErrorenum, mirroring [std::fs::TryLockError]
withError(io::Error)andWouldBlockvariants. Implements
Debug,Display,std::error::Error(withsource()exposing
the innerio::Error),From<io::Error>(kindWouldBlock
collapses into theWouldBlockvariant; everything else wraps into
Error), andFrom<TryLockError> for io::Error(WouldBlock
becomesio::Error::from(io::ErrorKind::WouldBlock);Error(inner)
passes through verbatim).
Fixes
- Fixed feature typos that made the crate fail to compile with only
fs-err2,fs-err3,fs-err2-tokio, orfs-err3-tokioenabled
(withoutsync/tokio).#[cfg(feature = "fs-err")]and
feature = "fs-err-tokio"both referenced feature names that do not
exist inCargo.toml. - On Windows, skip the internal
set_lencall when the file's existing
cluster-aligned allocation already coverslen. Avoids the Windows
buffered-I/O quirks observed when the end-of-file pointer is moved
inside an already-allocated cluster (#13). The trait doc now carves
this behavior out from the general "file size is at leastlen
bytes" contract. - Short-circuited
allocateon Unix when the file is already at least
lenbytes long. Fixes macOSfallocatespuriously returning
ENOSPCwhen re-callingallocate(len)on an existing file (#15). - Added
cygwinto theallocatetarget_osset so builds stop
failing with a missingsys::allocatesymbol on that target (#44). - Added
redoxandcygwinto the asyncallocatefallback branch
so it matches the sync variant (#43 follow-up). - Moved AIX from the async
fallocatebranch to theset_len
fallback branch, matching the sync implementation. - Trait docs now explicitly state that locks are released
automatically when the owning file handle is closed (#23). - Removed the stale trait-doc reference to non-existent cross-platform
tests inlib.rs(#16). - Mitigated #31 (compiler warning about name collisions with upcoming
std methods): because 1.0 renames the trait methods to match std
exactly,std::fs::File::lock/try_lock/unlock(stable in
Rust 1.89+) now win via inherent dispatch andunstable_name_collisions
no longer fires for std users on recent rustc. - Gated the
lock_impl!macro with#[allow(unused_macros)]so
cargo clippy --no-default-features(filesystem-stats-only build)
does not fail under-D warnings. - Removed dead duplicate macros
cfg_fs2_err/cfg_fs3_errfrom
lib.rs(unified withcfg_fs_err2/cfg_fs_err3). - Updated
html_root_urlto the 1.0.0 docs.rs path.
Dependency updates
- Bumped
windows-sysfrom 0.59 to 0.61.
Testing
- Removed all
#[bench]functions from the test harness. They
measured OS syscalls (flock,LockFileEx,fallocate,statvfs)
rather than fs4 code, and produced numbers dominated by the
underlying filesystem. Dropping them lets the crate build and test
on stable Rust (the bench harness was the only thing pinning
nightly via#![cfg_attr(test, feature(test))]).
rust-toolchain.tomlis nowstable. - Added regression tests:
allocate_preserves_eof_within_cluster— exercises the #13
precondition (cluster-alignedAllocationSizewith EOF inside
the cluster) and asserts EOF is not moved whenallocate(len)is
re-called withlen <= allocated_sizeon Windows.allocate_idempotent— exercises the #15 precondition (back-to-back
allocate(len)calls on macOS) to prevent a regression in the
short-circuit.- Seven
TryLockErrorunit tests covering variants,Display,
std::error::Error::source,From<io::Error>,From<TryLockError> for io::Error, and round-trip preservation ofErrorKind. FsStatsgetter + derive unit tests (previously every test
destructured the struct, so the four getter method bodies were
never executed and showed as uncovered).
- Fixed a long-standing macOS test failure: the cross-platform
filesystem_spacetest assertedavailable_space <= free_space,
which does not hold on macOS APFS. APFS counts purgeable space
(snapshots, cached data reclaimable on demand) inf_bavailbut
not inf_bfree, so the POSIX invariant is violated on every run.
The assertion is removed and the async variant now makes a single
statvfscall plus destructure instead of three separate calls
racing with concurrent filesystem activity from other tests.
CI / tooling
- New
.github/workflows/coverage.ymlworkflow: per-OS matrix
(ubuntu-latest, macos-latest, windows-latest) running
cargo tarpaulin --engine llvm --all-features --run-types tests --ignore-testson each runner and uploading per-OS reports to
Codecov with per-OS flags. Each runner--exclude-filesthe other
OS's sources so they do not register as 0/N uncovered lines. - The
crossjob now installs the MinGW-w64 toolchain when targeting
*-pc-windows-gnu.windows-sys0.61 invokesdlltoolduring
build, andubuntu-latestships only the x86_64 MinGW toolchain
by default. - README install snippets updated from
fs4 = { version = "0.13", ... }
tofs4 = { version = "1", ... }. - Housekeeping: added
.codecov.yml,rustfmt.toml(2-space indent,
explains the session-wide reformat), and
.github/workflows/loc.yml; removed the obsoletetea.yaml.