Skip to content

Instantly share code, notes, and snippets.

@RandyMcMillan
Last active March 12, 2025 17:58
Show Gist options
  • Save RandyMcMillan/04f5ee116ef1d5bb026afa8aaa53149b to your computer and use it in GitHub Desktop.
Save RandyMcMillan/04f5ee116ef1d5bb026afa8aaa53149b to your computer and use it in GitHub Desktop.
tokio_async_command
// Cargo.toml
// [package]
// name = "tokio_async_command"
// version = "0.1.0"
// edition = "2021"
//
// [dependencies]
// tokio = { version = "1.44.0", features = ["full"] }
use tokio::io::{AsyncBufReadExt, BufReader};
use tokio::process::Command;
use tokio::spawn;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut child = Command::new("ls")
.arg("-l")
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.spawn()?;
let stdout = child.stdout.take().expect("stdout was not configured");
let stderr = child.stderr.take().expect("stderr was not configured");
let stdout_reader = BufReader::new(stdout);
let stderr_reader = BufReader::new(stderr);
let stdout_handle = spawn(async move {
let mut lines = stdout_reader.lines();
while let Some(line) = lines.next_line().await.unwrap_or(Some("0".to_string())) {
println!("{}", line);
}
});
let stderr_handle = spawn(async move {
let mut lines = stderr_reader.lines();
while let Some(line) = lines.next_line().await.unwrap_or(Some("0".to_string())) {
eprintln!("stderr: {}", line);
}
});
let _status = child.wait().await?;
stdout_handle.await?;
stderr_handle.await?;
//println!("Exited with status: {}", _status);
let option_handle = spawn(async move {
process_options(Some(10), Some("hello".to_string()));
});
option_handle.await?;
let option_handle = spawn(async move {
process_options(Some(20), None);
});
option_handle.await?;
let option_handle = spawn(async move {
process_options(None, Some("world".to_string()));
});
option_handle.await?;
Ok(())
}
#[allow(unused_assignments)]
fn process_options(mut opt1: Option<i32>, mut opt2: Option<String>) {
let mut o1 = opt1.clone();
let mut o2 = opt2.clone();
while o1.is_some() || o2.is_some() {
match (o1.take(), o2.take()) {
(Some(val1), Some(val2)) => {
//prints twice - once for each option
println!("Both Some: {}, {}", val1, val2);
// process both values
}
(Some(val1), None) => {
println!("Opt1 Some: {}", val1);
// process opt1
}
(None, Some(val2)) => {
println!("Opt2 Some: {}", val2);
// process opt2
}
(None, None) => {
//should not happen since we already checked is_some() above.
}
}
// o1 = opt1;
// o2 = opt2;
opt1 = None;
opt2 = None;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment