Switchy Filesystem (switchy_fs)
Cross-platform filesystem abstraction with sync and async operations.
Overview
The switchy_fs package provides:
- Sync and Async APIs: Both synchronous and asynchronous filesystem operations
- Cross-platform: Abstraction over different filesystem implementations
- Feature-gated Backends: Standard library, Tokio, and simulator implementations
- File Operations: Create, read, write, seek, and delete operations
- Directory Operations: Create, remove, read, and walk directories with deterministic ordering
- Temporary Directories: Automatic cleanup of temporary directories
- Flexible Options: Configurable file open options
- Path Utilities: Check path existence across backends
Features
Operation Modes
- Synchronous: Blocking filesystem operations via
syncmodule - Asynchronous: Non-blocking operations via
unsyncmodule
Backend Implementations
- Standard Library:
std::fsbased implementation - Tokio:
tokio::fsbased async implementation - Simulator: Mock filesystem for testing
File Operations
- File Creation: Create new files with various options
- File Reading: Read file contents to string
- File Writing: Write data to files
- File Seeking: Random access file positioning
- Directory Management: Create, remove, read, and walk directories
- Directory Traversal: Sorted directory reading and recursive walking
- Path Checking: Check if files or directories exist
Open Options
- Create: Create file if it doesn't exist
- Append: Append to existing file content
- Read: Open file for reading
- Write: Open file for writing
- Truncate: Clear existing file content
Installation
Add this to your Cargo.toml:
[]
= { = "../fs" }
# With specific features
= {
path = "../fs",
= ["sync", "async", "std", "tokio"]
}
# For testing
= {
path = "../fs",
= ["simulator", "sync", "async"]
}
Usage
Synchronous File Operations
use ;
use ;
Asynchronous File Operations
use ;
use ;
use SeekFrom;
async
File Open Options
use OpenOptions;
// Create new file, fail if exists
let file = new
.create
.write
.open?;
// Open existing file for reading
let file = new
.read
.open?;
// Open file for appending
let file = new
.append
.write
.open?;
// Create or truncate file for writing
let file = new
.create
.write
.truncate
.open?;
// Read and write access
let file = new
.read
.write
.open?;
Directory Operations
use ;
use exists;
// Create nested directories
create_dir_all?;
// Check if path exists
if exists
// Read directory entries (sorted by filename)
let entries = read_dir_sorted?;
for entry in entries
// Recursively walk directory tree (sorted by path)
let all_entries = walk_dir_sorted?;
for entry in all_entries
// Remove directory and all contents
remove_dir_all?;
// Async versions
use ;
create_dir_all.await?;
remove_dir_all.await?;
Cross-module Compatibility
// Convert between sync and async options
use ;
let async_options = new
.create
.write;
// Convert to sync options
let sync_options: OpenOptions = async_options.into;
// Or use explicit conversion
let sync_options = async_options.into_sync;
Simulator Mode (Testing)
Simulator Real Filesystem Access
With the simulator-real-fs feature, you can temporarily access the real filesystem within simulator mode:
use ;
// In simulator mode, but need to access real filesystem temporarily
let real_data = with_real_fs.unwrap;
// Back to simulated filesystem
let sim_data = read_to_string?;
Seeding Simulator from Real Filesystem
When loading fixtures into the simulator, use the seeding APIs:
seed_from_real_fs(real_path, sim_path): Recursively copy a real filesystem path into a simulator pathseed_from_real_fs_same_path(path): Seed using the same path for both real and simulator locationsseed_relative_to(base, relative_paths): Seed multiple paths relative to a base directoryis_simulator_enabled(): Check whether the crate was compiled with simulator support
use ;
// Seed one path from real filesystem into a simulator path
seed_from_real_fs?;
// Seed multiple paths relative to a project root
seed_relative_to?;
Temporary Directories
The package provides temporary directory support that automatically cleans up when dropped:
use ;
// Create a temporary directory
let temp = tempdir?;
let path = temp.path;
// Use the directory
write?;
// Directory is automatically cleaned up when temp is dropped
// Create temp directory with prefix
let temp = with_prefix?;
// Create temp directory with suffix
let temp = with_suffix?;
// Create temp directory in specific location
let temp = tempdir_in?;
// Persist the directory (prevent automatic cleanup)
let kept_path = temp.keep;
Feature Flags
Operation Modes
sync: Enable synchronous filesystem operationsasync: Enable asynchronous filesystem operations
Backend Implementations
std: Use standard library filesystem implementationtokio: Use Tokio async filesystem implementationsimulator: Use mock filesystem for testingsimulator-real-fs: Enable real filesystem access within simulator mode usingwith_real_fs
Other Features
fail-on-warnings: Treat warnings as errors during compilation
Default features: async, simulator, std, sync, tokio
Backend Selection
The package automatically selects the appropriate backend based on enabled features:
- Simulator Mode: When
simulatorfeature is enabled, all operations use mock filesystem - Standard Library: When
stdfeature is enabled (and not simulator), usesstd::fs - Tokio: When
tokiofeature is enabled (and not simulator), usestokio::fs
Error Handling
use ;
use ErrorKind;
match new.read.open
Dependencies
- log: Logging facade for diagnostic messages
- switchy_async: Async I/O trait abstractions (optional)
- bytes: Byte buffer utilities for simulator backend (optional)
- scoped-tls: Thread-local storage for simulator real-fs mode (optional)
- tempfile: Temporary file management for standard library backend (optional)
- tokio: Async filesystem operations (optional)
Use Cases
- Configuration Files: Read and write application configuration
- Data Persistence: Store and retrieve application data
- Log Files: Append-only log file operations
- Temporary Directories: Create and manage temporary directories with automatic cleanup
- Testing: Mock filesystem operations in unit tests with simulator mode
- Cross-platform Applications: Unified filesystem interface across different backends
- Async Applications: Non-blocking filesystem operations with Tokio
- Deterministic Testing: Sorted directory reading and walking for reproducible test results