use scripty::*;
use std::fs::File;
use std::io::{BufReader, Cursor};
fn main() -> Result<()> {
println!("🔗 ReadExt: Fluent Reader-to-Command Piping");
println!("=============================================\n");
setup_sample_files()?;
println!("1. File-to-command piping:");
file_piping_examples()?;
println!("\n2. Memory-efficient streaming:");
streaming_examples()?;
println!("\n3. Working with different reader types:");
reader_types_examples()?;
println!("\n4. Advanced pipeline chaining:");
advanced_chaining_examples()?;
cleanup_sample_files()?;
println!("\n🎉 ReadExt examples completed!");
println!("💡 Key benefits:");
println!(" • Intuitive method chaining: reader.pipe(cmd)");
println!(" • Memory efficient streaming");
println!(" • Seamless integration with existing pipelines");
Ok(())
}
fn setup_sample_files() -> Result<()> {
let log_data = r#"2024-01-15 10:30:45 INFO Application started
2024-01-15 10:30:46 DEBUG Loading configuration
2024-01-15 10:30:47 INFO Configuration loaded successfully
2024-01-15 10:31:15 WARN Connection timeout, retrying...
2024-01-15 10:31:16 ERROR Failed to connect to database
2024-01-15 10:31:17 INFO Retrying database connection
2024-01-15 10:31:18 INFO Database connection established
2024-01-15 10:31:20 DEBUG Processing user request
2024-01-15 10:31:21 INFO Request processed successfully
2024-01-15 10:31:22 ERROR Invalid user credentials"#;
fs::write("sample_log.txt", log_data)?;
let numbers_data = "42\n17\n8\n23\n91\n6\n34\n15\n77\n2";
fs::write("numbers.txt", numbers_data)?;
let csv_data = "name,age,city\nAlice,25,Tokyo\nBob,30,London\nCharlie,35,Paris\nDiana,28,Berlin\nEve,22,Madrid";
fs::write("data.csv", csv_data)?;
Ok(())
}
fn cleanup_sample_files() -> Result<()> {
let _ = fs::remove_file("sample_log.txt");
let _ = fs::remove_file("numbers.txt");
let _ = fs::remove_file("data.csv");
Ok(())
}
fn file_piping_examples() -> Result<()> {
println!(" Direct file-to-command piping with ReadExt\n");
println!("📄 Basic file processing:");
println!(" Command: file.pipe(wc -l)");
let file = File::open("sample_log.txt")?;
let line_count = file.pipe(cmd!("wc", "-l")).output()?;
println!(" Log file has {} lines", line_count.trim());
println!("\n🔍 Error log filtering:");
println!(" Command: file.pipe(grep ERROR)");
let file = File::open("sample_log.txt")?;
let errors = file.pipe(cmd!("grep", "ERROR")).output()?;
println!(" ERROR entries found:");
for line in errors.lines() {
if !line.trim().is_empty() {
println!(" {}", line.trim());
}
}
println!("\n🧮 Numeric processing:");
println!(" Command: file.pipe(sort -n)");
let file = File::open("numbers.txt")?;
let sorted_numbers = file.pipe(cmd!("sort", "-n")).output()?;
println!(" Sorted numbers: {}", sorted_numbers.replace('\n', ", "));
Ok(())
}
fn streaming_examples() -> Result<()> {
println!(" Memory-efficient streaming with large data processing\n");
println!("📊 Buffered file processing:");
println!(" Using BufReader for optimal performance");
let file = File::open("sample_log.txt")?;
let buf_reader = BufReader::new(file);
let word_count = buf_reader.pipe(cmd!("wc", "-w")).output()?;
println!(" Total words in log: {}", word_count.trim());
println!("\n📈 Statistical analysis:");
println!(" Command: file.pipe(awk '{{sum += $1}} END {{print sum, NR, sum/NR}}')");
let file = File::open("numbers.txt")?;
let buf_reader = BufReader::new(file);
let stats = buf_reader
.pipe(cmd!("awk", "{sum += $1; count++} END {printf \"Sum: %d, Count: %d, Average: %.2f\\n\", sum, count, sum/count}"))
.output()?;
println!(" Statistics: {}", stats.trim());
println!("\n⚡ Streaming efficiency demonstration:");
println!(" Processing data without loading everything into memory");
let large_data = (1..=1000)
.map(|i| i.to_string())
.collect::<Vec<_>>()
.join("\n");
let large_data_bytes = large_data.into_bytes();
let cursor = Cursor::new(large_data_bytes);
let result = cursor
.pipe(cmd!("tail", "-5"))
.pipe(cmd!("head", "-3"))
.output()?;
println!(
" Last 5, then first 3 numbers: {}",
result.replace('\n', ", ")
);
Ok(())
}
fn reader_types_examples() -> Result<()> {
println!(" Working with different types of readers\n");
println!("🗂️ In-memory data processing:");
let data = b"zebra\napple\nbanana\ncherry\ndate";
let cursor = Cursor::new(data);
let sorted = cursor.pipe(cmd!("sort")).output()?;
println!(" Sorted fruits: {}", sorted.replace('\n', ", "));
println!("\n📝 Text data processing:");
let text_data = "Hello World\nRust is awesome\nPiping is powerful";
let cursor = Cursor::new(text_data.as_bytes());
let word_count = cursor.pipe(cmd!("wc", "-w")).output()?;
println!(" Total words: {}", word_count.trim());
println!("\n📊 CSV data analysis:");
println!(" Processing CSV file with header extraction");
let file = File::open("data.csv")?;
let header = file.pipe(cmd!("head", "-1")).output()?;
println!(" CSV header: {}", header.trim());
let file = File::open("data.csv")?;
let record_count = file
.pipe(cmd!("tail", "-n", "+2")) .pipe(cmd!("wc", "-l"))
.output()?;
println!(" Data records: {}", record_count.trim());
Ok(())
}
fn advanced_chaining_examples() -> Result<()> {
println!(" Advanced pipeline chaining with ReadExt\n");
println!("🔍 Complex log analysis pipeline:");
println!(" Command: file.pipe(grep -v DEBUG).pipe(cut -d' ' -f4).pipe(sort).pipe(uniq -c)");
let file = File::open("sample_log.txt")?;
let log_levels = file
.pipe(cmd!("grep", "-v", "DEBUG")) .pipe(cmd!("cut", "-d", " ", "-f", "4")) .pipe(cmd!("sort"))
.pipe(cmd!("uniq", "-c"))
.output()?;
println!(" Log level frequency (excluding DEBUG):");
for line in log_levels.lines() {
if !line.trim().is_empty() {
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 2 {
println!(" {}: {} occurrences", parts[1], parts[0]);
}
}
}
println!("\n🔄 Multi-stage data transformation:");
println!(" Command: file.pipe(tail -n +2).pipe(cut -d, -f2).pipe(sort -n).pipe(awk '...')");
let file = File::open("data.csv")?;
let age_stats = file
.pipe(cmd!("tail", "-n", "+2")) .pipe(cmd!("cut", "-d", ",", "-f", "2")) .pipe(cmd!("sort", "-n")) .pipe(cmd!("awk", "{sum+=$1; count++} END {printf \"Min: %d, Max: %d, Avg: %.1f\\n\", $1, max, sum/count} {if(NR==1) min=$1; max=$1} {if($1>max) max=$1}"))
.output()?;
println!(" Age statistics: {}", age_stats.trim());
println!("\n⏱️ Stream processing with immediate output:");
println!(" Processing numbers and showing running total");
let file = File::open("numbers.txt")?;
file.pipe(cmd!("awk", "{sum += $1; print \"Running total:\", sum}"))
.run()?;
Ok(())
}