read_range
A simple, fast, and portable Rust crate for reading a specific range of bytes from a file. Provides both synchronous and asynchronous APIs with optional progress reporting.
Overview
read_range offers a robust and efficient way to read a segment of a file without needing to read the entire file into memory. It's built for performance and safety, especially in concurrent applications.
On Unix and Windows, it uses high-performance, platform-specific calls (pread on Unix / seek_read on Windows) that read from a specific offset without mutating the global file cursor. This makes it safe to read from the same file handle across multiple threads simultaneously. For other platforms, it uses a standard seek and read fallback.
Key Features
- Asynchronous & Synchronous: Provides both
asyncand blocking APIs to fit any application. - High Performance: Uses efficient positional I/O on supported platforms (Unix, Windows) to avoid file cursor contention.
- Concurrent-Safe: The primary
read_atstrategy is stateless and safe to use across multiple threads without locks. - Portable: Includes a fallback implementation for platforms without specialized positional read APIs.
- Progress Reporting: All API variants have a
_with_progressversion to easily integrate with UI components like progress bars. - Robust Error Handling: Distinguishes between recoverable I/O errors (like task cancellation) and unrecoverable bugs (like out-of-memory), providing a predictable and debuggable API contract.
Installation
Add read_range to your Cargo.toml:
The async API uses tokio. Enable with the default async feature (on by default):
= { = "0.2", = true } # async ON
# or disable:
# read_range = { version = "0.2", default-features = false } # sync-only
Usage
Basic Synchronous Read
The simplest way to use the crate is to perform a blocking read. This is ideal for command-line tools or simple scripts.
use ;
use ;
use NamedTempFile;
Asynchronous Read with Tokio
For non-blocking applications, use the async variants within a Tokio runtime.
use io;
use async_read_byte_range; // requires `features = ["async"]`
use NamedTempFile;
use ;
async
Asynchronous Read with Progress Reporting
For long-running reads, you can track progress by implementing the Progress trait.
use ;
use ;
use NamedTempFile;
use ;
// A simple progress tracker that prints updates.
async
API
The crate exposes four main functions:
read_byte_range(path, offset, len): Synchronously reads a byte range.read_byte_range_with_progress(path, offset, len, progress): Synchronously reads a byte range and reports progress.async_read_byte_range(path, offset, len): Asynchronously reads a byte range.async_read_byte_range_with_progress(path, offset, len, progress): Asynchronously reads a byte range and reports progress.
Error Handling Philosophy
This crate is designed for robustness and follows standard Rust error handling idioms.
- It returns
io::Resultfor all expected I/O failures, invalid arguments (e.g., a read range that would overflowu64), or graceful events like async task cancellation. - It panics only when a background task encounters an unrecoverable state, such as an out-of-memory error during buffer allocation. This "fail-fast" approach prevents your application from continuing in a corrupt state and makes critical bugs easier to diagnose. The panic is propagated from the background thread to the calling task.
Future Work
A streaming API that returns an impl Read or impl AsyncRead instead of a Vec<u8> is being considered for a future release. This would enable efficient processing of very large file segments in memory-constrained environments.
License
This project is licensed under the MIT license.