Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@

All notable changes to this project will be documented in this file.

## [Unreleased]

### Added
- `OneIo::to_lines_lossy` — lossy line iterator from any `Box<dyn Read + Send>`
- `read_lines_lossy` / `OneIo::read_lines_lossy` — line iteration with invalid UTF-8 replaced by `U+FFFD`
- `read_to_string_lossy` / `OneIo::read_to_string_lossy` / `read_to_string_lossy_async` — full-file read with lossy UTF-8
- `read_to_bytes` / `OneIo::read_to_bytes` / `read_to_bytes_async` — byte-perfect read without UTF-8 validation
- `--strict-utf8` CLI flag for strict UTF-8 validation in the CLI

### Changed
- CLI now defaults to lossy UTF-8 reading; no longer exits on invalid byte sequences
- Documentation examples updated to use lossy APIs

### Deprecated
- `read_lines` — use `read_lines_lossy` for lossy text, `read_to_bytes` for byte-perfect whole-file reads, or `get_reader` + `BufReader` for streaming byte processing
- `read_to_string` — use `read_to_string_lossy` or `read_to_bytes`
- `read_to_string_async` — use `read_to_string_lossy_async` or `read_to_bytes_async`

## v0.22.0 -- 2026-05-01

### Breaking changes
Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Read all content into a string (works with compression and remote files automati
```rust
use oneio;

let content = oneio::read_to_string("https://spaces.bgpkit.org/oneio/test_data.txt.gz")?;
let content = oneio::read_to_string_lossy("https://spaces.bgpkit.org/oneio/test_data.txt.gz")?;
println!("{}", content);
```

Expand All @@ -120,7 +120,7 @@ Read line by line:
```rust
use oneio;

let lines = oneio::read_lines("https://spaces.bgpkit.org/oneio/test_data.txt.gz")?
let lines = oneio::read_lines_lossy("https://spaces.bgpkit.org/oneio/test_data.txt.gz")?
.map(|line| line.unwrap())
.collect::<Vec<String>>();

Expand Down Expand Up @@ -151,7 +151,7 @@ writer.write_all(b"Hello, compressed world!")?;
drop(writer); // Important: close the writer

// Read it back
let content = oneio::read_to_string("output.txt.gz")?;
let content = oneio::read_to_string_lossy("output.txt.gz")?;
```

### Reusable OneIo Clients
Expand All @@ -171,8 +171,8 @@ let oneio = OneIo::builder()
.build()?;

// Reuse the same configuration for multiple requests
let content1 = oneio.read_to_string("https://api.example.com/data1.json")?;
let content2 = oneio.read_to_string("https://api.example.com/data2.json")?;
let content1 = oneio.read_to_string_lossy("https://api.example.com/data1.json")?;
let content2 = oneio.read_to_string_lossy("https://api.example.com/data2.json")?;
```

**Builder Methods:**
Expand Down Expand Up @@ -237,7 +237,7 @@ use oneio;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let content = oneio::read_to_string_async("https://example.com/data.json.gz").await?;
let content = oneio::read_to_string_lossy_async("https://example.com/data.json.gz").await?;

oneio::download_async(
"https://example.com/data.csv.gz",
Expand Down Expand Up @@ -270,7 +270,7 @@ s3_delete("my-bucket", "path/to/copy.txt")?;

// Read S3 directly using OneIO
let oneio = oneio::OneIo::new()?;
let content = oneio.read_to_string("s3://my-bucket/path/to/file.txt")?;
let content = oneio.read_to_string_lossy("s3://my-bucket/path/to/file.txt")?;

// Check existence and get metadata
if s3_exists("my-bucket", "path/to/file.txt")? {
Expand Down Expand Up @@ -327,7 +327,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
oneio::crypto::ensure_default_provider()?;

// Now all HTTPS/S3/FTP operations will work
let content = oneio::read_to_string("https://example.com/data.txt")?;
let content = oneio::read_to_string_lossy("https://example.com/data.txt")?;

Ok(())
}
Expand Down
6 changes: 3 additions & 3 deletions examples/async_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! Requires the "async" feature and an async runtime (tokio).

use oneio::get_reader_async;
use oneio::read_to_string_async;
use oneio::read_to_string_lossy_async;
use tokio::io::{AsyncReadExt, BufReader};

#[tokio::main]
Expand All @@ -15,9 +15,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// You can use a local file or a remote URL
let path = "tests/test_data.txt.gz";

// --- High-level API: read_to_string_async ---
// --- High-level API: read_to_string_lossy_async ---
println!("Reading file asynchronously (high-level): {}", path);
let content = read_to_string_async(path).await?;
let content = read_to_string_lossy_async(path).await?;
println!("File content (high-level):\n{}", content);

// --- Low-level API: get_reader_async ---
Expand Down
2 changes: 1 addition & 1 deletion examples/test_crypto_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {

// Test HTTPS download - crypto provider is already set up
println!("\nDownloading test file via HTTPS...");
let content = oneio::read_to_string("https://spaces.bgpkit.org/oneio/test_data.txt")?;
let content = oneio::read_to_string_lossy("https://spaces.bgpkit.org/oneio/test_data.txt")?;
println!("✓ Downloaded content:\n{}", content.trim());

println!("\n✓ All operations completed successfully!");
Expand Down
Loading