use std::time::Duration;
use rust_expect::prelude::*;
use rust_expect::util::Backpressure;
#[tokio::main]
#[allow(clippy::too_many_lines)]
async fn main() -> Result<()> {
println!("rust-expect Large Output Handling Example");
println!("=========================================\n");
println!("1. Handling large output...");
let mut session = Session::spawn("/bin/sh", &[]).await?;
session
.expect_timeout(Pattern::shell_prompt(), Duration::from_secs(2))
.await?;
session
.send_line("for i in $(seq 1 100); do echo \"Line $i: Some sample output data\"; done")
.await?;
session
.expect_timeout(Pattern::shell_prompt(), Duration::from_secs(5))
.await?;
let buffer = session.buffer();
println!(" Buffer size: {} bytes", buffer.len());
println!(" Contains ~100 lines of output");
println!("\n2. Buffer management...");
session.clear_buffer();
println!(" Buffer cleared");
println!(
" Buffer size after clear: {} bytes",
session.buffer().len()
);
session.send_line("echo 'Fresh start'").await?;
session.expect("Fresh start").await?;
println!(" New output captured");
println!("\n3. Custom buffer configuration...");
let config = SessionConfig {
buffer: BufferConfig {
max_size: 1024 * 1024, search_window: Some(8192),
ring_buffer: true,
},
..Default::default()
};
let session2 = Session::spawn_with_config("/bin/sh", &[], config).await?;
println!(" Created session with 1MB buffer");
println!(
" Buffer max size: {} bytes",
session2.config().buffer.max_size
);
println!(
" Search window: {:?}",
session2.config().buffer.search_window
);
println!(" Ring buffer: {}", session2.config().buffer.ring_buffer);
drop(session2);
println!("\n4. Backpressure handling...");
let backpressure = Backpressure::new(1000);
println!(" Created backpressure controller: 1000 bytes max");
for i in 1..=5 {
let amount = 200; if backpressure.try_acquire(amount) {
println!(" Request {i}: acquired {amount} bytes");
} else {
println!(" Request {i}: buffer full");
}
}
backpressure.release(400);
println!(" Released 400 bytes");
if backpressure.try_acquire(200) {
println!(" After release: acquired 200 more bytes");
}
println!("\n5. Processing output incrementally...");
session
.send_line("for i in 1 2 3 4 5; do echo \"Chunk $i\"; sleep 0.1; done")
.await?;
let mut chunks_received = 0;
for _ in 0..5 {
match session
.expect_timeout("Chunk", Duration::from_millis(500))
.await
{
Ok(m) => {
chunks_received += 1;
println!(" Received: {}", m.matched.trim());
}
Err(_) => break,
}
}
println!(" Total chunks: {chunks_received}");
session
.expect_timeout(Pattern::shell_prompt(), Duration::from_secs(2))
.await?;
println!("\n6. Ring buffer for memory efficiency...");
let mut ring_buffer = RingBuffer::new(4096);
println!(
" Ring buffer created with {} byte max size",
ring_buffer.max_size()
);
ring_buffer.append(b"Hello, ");
ring_buffer.append(b"World!");
println!(" Written data, buffer len: {}", ring_buffer.len());
println!(" Ring buffers automatically discard old data when full");
println!("\n7. Buffer configuration options...");
let small_buffer = BufferConfig::new(1024).search_window(512).ring_buffer(true);
println!(
" Small buffer: {} bytes, window: {:?}",
small_buffer.max_size, small_buffer.search_window
);
let large_buffer = BufferConfig::new(10 * 1024 * 1024) .ring_buffer(false);
println!(
" Large buffer: {} MB, ring: {}",
large_buffer.max_size / 1024 / 1024,
large_buffer.ring_buffer
);
session.send_line("exit").await?;
session.wait().await?;
println!("\nLarge output handling examples completed successfully!");
Ok(())
}