Releases: bgpkit/oneio
Releases · bgpkit/oneio
v0.21.0
Breaking changes
OneIoErroris now#[non_exhaustive];matchexpressions without a wildcard_arm will fail to compileOneIoBuilder::header()now accepts typedHeaderName/HeaderValue(infallible) instead of(K, V) -> Result<Self>OneIoBuilder::user_agent()now accepts a typedHeaderValue(infallible) instead ofV -> Result<Self>oneio::download()no longer accepts anOption<reqwest::blocking::Client>parameteroneio::remotemodule is nowpub(crate);create_client_with_headersis deprecated (useOneIo::builder().header_str())ProgressReaderandProgressCallbackare no longer part of the public API
Changed
- Flattened module layout:
src/oneio/sub-directory removed; all modules are now atsrc/level OneIoandOneIoBuilderare now the primary API surface; free-standing functions delegate to a shared default client- Compression detection strips URL query parameters and fragments before reading the file extension
download_with_retry()uses exponential backoff between retry attempts (100ms × 2^attempt, capped at 6400ms)- Stream cache writes to disk via
std::io::copyinstead of buffering the full payload in memory download_async()now preserves raw bytes, matchingdownload()- Default blocking HTTP clients are reused across reads and content-length probes
- Stateless read and download helpers now delegate to a reusable
OneIoclient internally - S3 status failures now use structured errors instead of string parsing
- S3 readers now stream data through a bounded channel instead of materializing the full object in memory
Added
OneIoBuilder::header_str(name, value)— string convenience for adding headers (panics on invalid input, matching reqwest convention)OneIoBuilder::configure_http(f)— escape hatch for setting anyreqwest::blocking::ClientBuilderoptionOneIoBuilder::timeout(),connect_timeout()— request and connect timeoutsOneIoBuilder::proxy(),no_proxy()— proxy configurationOneIoBuilder::redirect()— redirect policyOneIoBuilder::add_root_certificate_pem(),add_root_certificate_der()— load CA certs from raw bytesOneIo::get_reader_with_type(path, compression)— explicit compression override, useful for URLs with query parametersOneIo::from_client(client)— construct aOneIofrom an existingreqwest::blocking::ClientOneIoError::NetworkWithContext— network errors now carry the URL that failedOneIoError::InvalidHeader,OneIoError::InvalidCertificate— specific error variants for header and certificate construction failuresONEIO_CA_BUNDLEenvironment variable — path to a PEM file added to the HTTP trust store on startupget_cache_reader()free-standing shortcut kept at crate root for convenience- Added
bzip2_decompressbenchmark coverage - Added a benchmark helper script for comparing gzip backend feature flags and bz2 decompression
- Added reusable
OneIoandOneIoBuilderAPIs for sharing headers and TLS certificate configuration across requests
CLI
- Added
-H/--headerflag for custom HTTP headers ("Name: Value"or"Name:Value"), can be repeated - Added
--compressionflag to override compression detection (gz, bz2, lz4, xz, zst); no effect with--download - Added progress bar for
--downloadands3 download, shown when stderr is a terminal; uses spinner when file size is unknown - Added
s3 download <BUCKET> <S3_PATH> [--outfile]subcommand - Fixed S3 upload syntax:
oneio s3 upload <LOCAL_FILE> <BUCKET> <S3_PATH>(local file is now the first positional arg under the subcommand) - Terminal detection uses
std::io::IsTerminalfrom the standard library; no extra dependency needed - Added
indicatifto theclifeature for progress bars
Bug fixes
- LZ4 compressed writes were silently truncated:
lz4::Encoderhas noDropimpl and requires an explicitfinish()call to write the end-of-stream marker. Fixed with aLz4Writerwrapper that callsfinish()on drop.
Documentation
lib.rsdocstring documents thenative-tlsfeature as the fix for Cloudflare WARP and corporate proxy environmentsONEIO_ACCEPT_INVALID_CERTSandONEIO_CA_BUNDLEenvironment variables documented at crate root
v0.20.1
Changed
rustlsfeature now enables bothrustls-tls-native-rootsandrustls-tls-webpki-rootsfor reqwest- Provides support for system certificates (including those installed by Cloudflare WARP or corporate VPNs)
- Falls back to bundled Mozilla certificates in minimal environments
- Both certificate stores are merged, providing maximum compatibility
v0.20.0
Added
- New
cryptomodule withensure_default_provider()helper function to initialize rustls crypto providers- Automatically tries AWS-LC first, then falls back to ring
- Called automatically from all HTTPS/S3/FTP code paths
- Can be called explicitly at startup for better control over initialization
- Fully thread-safe and idempotent
- Prevents "Could not automatically determine the process-level CryptoProvider" panic
- GitHub Copilot custom instructions file (
.github/copilot-instructions.md) documenting development practices
Changed
- All HTTPS, S3, and FTP operations now automatically initialize the rustls crypto provider on first use
- Added comprehensive documentation and examples for crypto provider initialization
rustlsfeature now explicitly includesdep:rustls_sysdependency- Simplified redundant feature flag checks (since
https→rustls, only checkrustls) - Split CI workflow: formatting check now runs as separate independent job for faster feedback
- Updated
remote_file_exists()to useensure_default_provider()helper
v0.19.2
Changed
- Updated
flate2dependency minimum version to1.1.0to include more recent fixes forzlib-rsbackend. - Add more backends for
flate2:gz-zlib-ngfeature forflate2/zlib-rs-nggz-zlib-cloudflarefeature forflate2/cloudflare_zlib
v0.19.1
Yanked due to bug for flate2 version below 1.1. Use 0.19.2 or above instead
Changed
- Gzip backend selection via feature flags:
- Default feature
gzswitched to use flate2 with thegz-zlib-rsbackend for improved performance. - New selectors and aliases:
gz-zlib-rs— enablesflate2/zlib-rs(Rust, fast)gz-miniz— enablesflate2/miniz_oxide(pure Rust, most portable)
- Disabled
flate2default-features to allow explicit backend choice.
- Default feature
Added
- Criterion benchmark
benches/gzip_decompress.rsto measure gzip decompression throughput across backends.
Usage
- Default (zlib-rs):
- cargo build
- cargo bench --bench gzip_decompress --features gz
- zlib-rs:
- cargo build --no-default-features --features gz-zlib-rs
- cargo bench --bench gzip_decompress --no-default-features --features gz-zlib-rs
- miniz_oxide (explicit):
- cargo build --no-default-features --features gz-miniz
- cargo bench --bench gzip_decompress --no-default-features --features gz-miniz
v0.19.0
Breaking Changes
Feature Flag Simplification
- Removed complex nested feature structure (
lib-core,remote,compressions) - Introduced flat structure:
gz,bz,lz,xz,zstd,http,ftp,s3,async - Changed default features from
["lib-core", "rustls"]to["gz", "bz", "http"]
Migration guide:
# Before (v0.18.x)
oneio = { version = "0.18", features = ["lib-core", "rustls"] }
# After (v0.19.0)
oneio = { version = "0.19", features = ["gz", "bz", "http"] }Error System Consolidation
- Simplified from 10+ error variants to 3 essential categories:
Io(std::io::Error)- File system errorsNetwork(Box<dyn Error>)- Network/remote errorsNotSupported(String)- Feature is not compiled or unsupported operation
Removed Components
- Removed
build.rs- No longer needed with simplified feature structure - Removed
OneIOCompressiontrait - Replaced with direct function calls
New Features
Progress Tracking
- Added
get_reader_with_progress()for tracking download/read progress - Works with both known and unknown file sizes
- Tracks raw bytes read before decompression
- Callback-based API:
|bytes_read, total_bytes| { ... }
Async Support (Feature: async)
- Added
get_reader_async(),read_to_string_async(),download_async() - True async support for HTTP and local files
- Compression support for gzip, bzip2, and zstd via async-compression
- LZ4 and XZ return
NotSupportederrors (no native async support) - FTP/S3 protocols return clear "not supported" errors
CLI Enhancements
- Added LZ/XZ compression support to CLI tool
- Fixed typos in CLI option descriptions
Improvements
Code Quality
- Replaced unsafe
unwrap()calls in path parsing with safe alternatives - Improved FTP login and file operation error handling
- Simplified HTTP stream error mapping
- Enhanced LZ4 error handling with better context
- Removed
eprintlnfrom library code in progress tracking
S3 Improvements
- Replaced fragile string matching with HTTP status code parsing in
s3_exists() - Fixed S3 upload hanging on non-existent files (issue #48)
- Made S3 documentation tests conditional on s3 feature
Testing and Examples
- Tests now work with any feature combination, including no features
- Updated progress tracking example to use indicatif
- Replaced unreliable
httpbin.orgendpoint with stablespaces.bgpkit.orgendpoint - Fixed doctest compilation with appropriate
ignoreflags
Documentation
- Updated lib.rs documentation for v0.19 changes
- Clarified
httpvshttpsfeature distinctions:http- HTTP-only support (no TLS)https- HTTP/HTTPS with rustls (equivalent tohttp+rustls)- Custom TLS: Use
http+rustlsorhttp+native-tls
- Regenerated README from lib.rs documentation
- Added clear migration guide and feature explanations
Dependencies
Updated
- Upgraded bzip2 to 0.6.0
- Added indicatif to dev-dependencies
Added (for async feature)
- tokio
- async-compression
- futures
Code Simplification
- Removed trait-based compression system in favor of direct function calls
- Eliminated nested feature dependencies with a flat structure
- Simplified async implementation without spawn_blocking patterns
- Streamlined error types from 10+ variants to 3 categories
v0.18.2
Hot Fix
- Make
rustls_sysdependency optional and exclude fromrustlsfeature flag
v0.18.1
✨ Added
- New build script: Added
build.rsto enforce that at least one TLS backend (rustlsornative-tls) is enabled
if any of the remote features (http,ftp, orremote) are enabled. - Module documentation: Added detailed Rust doc comments to the compression modules (gzip, bzip2, lz4, xz, zstd) and
utils.rsfor improved usability and understanding. get_protocolfunction: Utility for extracting protocol from file paths, now used across remote file access
functions.
🛠️ Changed
- Feature dependencies: The
ftpfeature now explicitly depends on thehttpfeature inCargo.toml. - Error handling: Updated
OneIoErrorenum to more accurately gate error variants with corresponding features (
http,ftp). - Module structure:
compressionsis now a public module.- Refactored how the crate distinguishes between local and remote file access, using
get_protocol. get_reader_rawand related functions now determine protocol and select the appropriate file reader accordingly.
- Compression interface:
- Added a unified trait
OneIOCompressionandget_compression_reader/get_compression_writerutilities for
consistent handling of all supported compression algorithms. - Updated file open logic to use these helpers based on file suffix.
- Added a unified trait
🧹 Cleaned up and Improved
- Removed legacy or redundant code paths (e.g.,
get_reader_raw_remote, old error gates). - Moved protocol detection and remote file reading logic into more modular and maintainable forms.
- Several function signatures and internal APIs have been updated for clarity and maintainability.
v0.18.0
Highlights
- split
remotefeatures intohttpandftp, allowing users who only need HTTP or FTP support to use the
corresponding feature flag- in most cases, users will likely not need to use the
ftpfeature
- in most cases, users will likely not need to use the
- add
create_client_with_headersfunction to allow creating areqwest::blocking::Clientwith custom headers- this simplifies the process of creating a client with custom headers for HTTP requests
- this also allows users to create custom clients without importing
reqwestcrate directly
- add
rustls_sysdependency to supportrustlsas the default TLS backend
Documentation improvements
- update examples on custom HTTP request function
oneio::get_http_readerto usecreate_client_with_headers
v0.17.0
Highlights
- add support for
zstd(zstandard) compression - allow setting
ONEIO_ACCEPT_INVALID_CERTS=trueto disable SSL checking - revised custom HTTP request function
oneio::get_http_readerto allow specifying customrequest::blocking::Client
for any request customizations to allow specifying customrequest::blocking::Clientfor any request customizations.
Breaking changes
- rename
oneio::get_remote_readertooneio::get_http_reader - rename
get_remote_ftp_rawtoget_ftp_reader_raw - change signatures of
oneio::download,oneio::download_with_retry,oneio::get_http_reader's optional HashMap
parameter for headers to optionalreqwest::blocking::Client.