diff --git a/Cargo.lock b/Cargo.lock index b64ac42c..3bd74507 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,21 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "ahash" version = "0.8.11" @@ -120,21 +105,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" -[[package]] -name = "backtrace" -version = "0.3.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -158,12 +128,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bytes" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" - [[package]] name = "cassowary" version = "0.3.0" @@ -179,12 +143,6 @@ dependencies = [ "rustversion", ] -[[package]] -name = "cc" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaff6f8ce506b9773fa786672d63fc7a191ffea1be33f72bbd4aeacefca9ffc8" - [[package]] name = "cfg-if" version = "1.0.0" @@ -344,101 +302,6 @@ dependencies = [ "libc", ] -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - [[package]] name = "hashbrown" version = "0.14.5" @@ -455,12 +318,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "indexmap" version = "2.2.6" @@ -569,15 +426,6 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - [[package]] name = "mio" version = "0.8.11" @@ -634,25 +482,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.19.0" @@ -698,18 +527,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "predicates" version = "3.1.0" @@ -826,12 +643,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - [[package]] name = "rustlings" version = "6.1.0" @@ -840,7 +651,6 @@ dependencies = [ "assert_cmd", "clap", "crossterm", - "futures", "hashbrown", "notify-debouncer-mini", "os_pipe", @@ -849,7 +659,6 @@ dependencies = [ "rustlings-macros", "serde", "serde_json", - "tokio", "toml_edit", ] @@ -959,31 +768,12 @@ dependencies = [ "libc", ] -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - [[package]] name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "stability" version = "0.2.1" @@ -1045,36 +835,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" -[[package]] -name = "tokio" -version = "1.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-macros" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "toml_datetime" version = "0.6.6" diff --git a/Cargo.toml b/Cargo.toml index c61478ce..6356f68b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,9 +48,6 @@ include = [ [dependencies] anyhow = "1.0.86" -tokio = { version = "1.0", features = ["full"] } -futures = "0.3" - clap = { version = "4.5.9", features = ["derive"] } crossterm = "0.27.0" hashbrown = "0.14.5" diff --git a/dev/Cargo.toml b/dev/Cargo.toml index 11b3fcde..9d0abe9e 100644 --- a/dev/Cargo.toml +++ b/dev/Cargo.toml @@ -192,8 +192,6 @@ bin = [ { name = "async1_sol", path = "../solutions/24_async/async1.rs" }, { name = "async2", path = "../exercises/24_async/async2.rs" }, { name = "async2_sol", path = "../solutions/24_async/async2.rs" }, - { name = "async3", path = "../exercises/24_async/async3.rs" }, - { name = "async3_sol", path = "../solutions/24_async/async3.rs" }, ] [package] diff --git a/exercises/24_async/README.md b/exercises/24_async/README.md index 1e31ca19..a22fc671 100644 --- a/exercises/24_async/README.md +++ b/exercises/24_async/README.md @@ -18,4 +18,3 @@ Navigate the complexities of error handling in async code. Understand how errors - [Learn more about async programming in Rust](https://doc.rust-lang.org/book/ch16-00-concurrency.html) - [Deep dive into handling concurrency](https://doc.rust-lang.org/book/ch16-02-message-passing.html) -- [Advanced async patterns](https://tokio.rs/tokio/tutorial) diff --git a/exercises/24_async/async1.rs b/exercises/24_async/async1.rs index 2e741594..8c2c3dba 100644 --- a/exercises/24_async/async1.rs +++ b/exercises/24_async/async1.rs @@ -1,30 +1,22 @@ -// This program creates multiple asynchronous tasks that each simulate a long-running operation -// using `async` and `await`. Each task will return how much time it took to complete. -// The program should wait until all the tasks have finished and should collect their return values into a vector. - +use async_std::task; use std::time::{Duration, Instant}; -use tokio::time::{sleep, Duration}; -async fn perform_task(id: usize) -> u128 { +async fn run_async_task(id: usize) -> u128 { let start = Instant::now(); - // Simulate async work using sleep - tokio::time::sleep(Duration::from_millis(250)).await; + // TODO: Replace the synchronous sleep with an asynchronous sleep. + task::sleep(Duration::from_millis(250)).await; println!("Task {id} done"); start.elapsed().as_millis() } -async fn main_async() { - let mut handles = Vec::new(); +async fn main() { + let mut tasks = Vec::new(); + for i in 0..10 { - let handle = perform_task(i); - handles.push(handle); + // TODO: Push new asynchronous tasks into the vector. } - let mut results = Vec::new(); - for handle in handles { - // TODO: Use `.await` to collect the results of all tasks into the `results` vector. - // Remember to handle each async task using the appropriate syntax for awaiting. - } + // TODO: Wait for all tasks to complete and collect their results. if results.len() != 10 { panic!("Oh no! Some task isn't done yet!"); @@ -36,6 +28,7 @@ async fn main_async() { } } +// Main function that starts the async main function using `task::block_on`. fn main() { - block_on(main_async()); + task::block_on(main()); } diff --git a/exercises/24_async/async2.rs b/exercises/24_async/async2.rs index dbc32c41..ca02d41d 100644 --- a/exercises/24_async/async2.rs +++ b/exercises/24_async/async2.rs @@ -1,31 +1,60 @@ -// This program demonstrates the transformation of a synchronous function into an asynchronous one. -// The original function performs a time-consuming operation, which we'll simulate with a sleep. -// You need to convert this function to use async/await syntax and understand how it improves the responsiveness of the application. +use async_std::task; +use std::time::{Duration, Instant}; +use std::fmt; -use std::time::Duration; -use futures::executor::block_on; // This is for running the async main function in this educational context. - -// Synchronous version of a function that simulates a long-running operation -fn calculate_value_synchronously() -> i32 { - println!("Starting synchronous calculation..."); - std::thread::sleep(Duration::from_secs(2)); // Simulating a long-running task - println!("Synchronous calculation done."); - 42 // returns a computed value +#[derive(Debug)] +enum TaskError { + Timeout, + Other(String), } -// TODO: Convert this function to async version -async fn calculate_value_asynchronously() -> i32 { - +impl fmt::Display for TaskError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + TaskError::Timeout => write!(f, "Task timed out"), + TaskError::Other(ref err) => write!(f, "Other error: {}", err), + } + } } -async fn main_async() { - println!("Calling synchronous function:"); - let sync_result = calculate_value_synchronously(); - println!("Result from synchronous function: {}", sync_result); +// TODO: Define an asynchronous function that may return an error. +async fn run_async_task(id: usize) -> Result { + let start = Instant::now(); + // Simulate a possible failure + if id == 5 { + // Simulate a timeout error + task::sleep(Duration::from_millis(100)).await; + return Err(TaskError::Timeout); + } else if id == 8 { + // Simulate another type of error + return Err(TaskError::Other("Unexpected error".to_string())); + } - // TODO: Call the async function here and print its result + // Normal operation with async sleep + task::sleep(Duration::from_millis(250)).await; + println!("Task {id} done"); + Ok(start.elapsed().as_millis()) } +async fn main() { + let mut tasks = Vec::new(); + + // TODO: Create and store asynchronous tasks in the `tasks` vector. + for i in 0..10 { + tasks.push(run_async_task(i)); } + + // TODO: Wait for all tasks to complete and collect their results, handling errors appropriately. + + // Process results + for (i, result) in results.into_iter().enumerate() { + match result { + Ok(duration) => println!("Task {i} took {duration}ms"), + Err(e) => println!("Task {i} failed with error: {}", e), + } + } +} + +// Main function that starts the async main function using `task::block_on`. fn main() { - block_on(main_async()); + task::block_on(main()); } diff --git a/exercises/24_async/async3.rs b/exercises/24_async/async3.rs deleted file mode 100644 index 64507971..00000000 --- a/exercises/24_async/async3.rs +++ /dev/null @@ -1,40 +0,0 @@ -// This program demonstrates error handling in asynchronous Rust code. We will simulate a function that can fail, -// and you will handle the error appropriately in an asynchronous context. - -use std::time::Duration; -use futures::executor::block_on; // For running the async main function in this educational context. -use tokio; // We use tokio for the async functionality. -use anyhow::{Result, anyhow}; // To simplify error handling - -// Asynchronous function that might fail -async fn might_fail(id: u32) -> Result { - if id % 2 == 0 { - tokio::time::sleep(Duration::from_millis(500)).await; - Ok(id) - } else { - tokio::time::sleep(Duration::from_millis(500)).await; - Err(anyhow!("Failed on odd id")) - } -} - -async fn main_async() { - let ids = [1, 2, 3, 4, 5]; - let mut results = Vec::new(); - - for id in ids { - // TODO: Handle the potential error here using appropriate async error handling methods. - // Consider using match or Result combinators like `map_err` or `and_then`. - } - - // Display results - for result in results { - match result { - Ok(num) => println!("Processed number: {}", num), - Err(e) => println!("Error occurred: {}", e), - } - } -} - -fn main() { - block_on(main_async()); -} diff --git a/rustlings-macros/info.toml b/rustlings-macros/info.toml index 752f5f4e..eb0ed5bb 100644 --- a/rustlings-macros/info.toml +++ b/rustlings-macros/info.toml @@ -1209,16 +1209,10 @@ Add `AsRef` or `AsMut` as a trait bound to the functions.""" name = "async1" dir = "24_async" hint = """ -Use `.await` to collect the results of all tasks into the `results` vector.""" +Push new asynchronous tasks into the vector.""" [[exercises]] name = "async2" dir = "24_async" hint = """ -Synchronous version of a function that simulates a long-running operation""" - -[[exercises]] -name = "async3" -dir = "24_async" -hint = """ -Consider using match or Result combinators like `map_err` or `and_then`.""" +Wait for all tasks to complete and collect their results, handling errors appropriately.""" diff --git a/solutions/24_async/async1.rs b/solutions/24_async/async1.rs index 62e8ffa0..6ac41582 100644 --- a/solutions/24_async/async1.rs +++ b/solutions/24_async/async1.rs @@ -1,30 +1,25 @@ -// This program creates multiple asynchronous tasks that each simulate a long-running operation -// using `async` and `await`, and each task will return how much time it took to complete. -// The program should wait until all the tasks have finished and should collect their return values into a vector. - +// Importing necessary modules from async-std to handle asynchronous tasks. +use async_std::task; use std::time::{Duration, Instant}; -use tokio::time::{sleep, Duration}; -async fn perform_task(id: usize) -> u128 { +async fn run_async_task(id: usize) -> u128 { let start = Instant::now(); - // Simulate async work using sleep - tokio::time::sleep(Duration::from_millis(250)).await; + // Simulate work by sleeping, but now this is asynchronous sleep. + task::sleep(Duration::from_millis(250)).await; println!("Task {id} done"); start.elapsed().as_millis() } -async fn main_async() { - let mut handles = Vec::new(); +async fn main() { + let mut tasks = Vec::new(); + + // Create asynchronous tasks for i in 0..10 { - let handle = perform_task(i); - handles.push(handle); + tasks.push(run_async_task(i)); } - let mut results = Vec::new(); - for handle in handles { - // Use `.await` to collect the results of all tasks into the `results` vector. - results.push(handle.await); - } + // Wait for all tasks to complete and collect their results. + let results = futures::future::join_all(tasks).await; if results.len() != 10 { panic!("Oh no! Some task isn't done yet!"); @@ -36,7 +31,7 @@ async fn main_async() { } } -#[tokio::main] -async fn main() { - main_async().await; -} \ No newline at end of file +// Main function now starts the async main function using `task::block_on`. +fn main() { + task::block_on(main()); +} diff --git a/solutions/24_async/async2.rs b/solutions/24_async/async2.rs index 4167f452..5c5725f3 100644 --- a/solutions/24_async/async2.rs +++ b/solutions/24_async/async2.rs @@ -1,37 +1,60 @@ -// This program demonstrates the transformation of a synchronous function into an asynchronous one. -// The original function performs a time-consuming operation, which we'll simulate with a sleep. -// You need to convert this function to use async/await syntax and understand how it improves the responsiveness of the application. +use async_std::task; +use std::time::{Duration, Instant}; +use std::fmt; -use std::time::Duration; -use futures::executor::block_on; // This is for running the async main function in this educational context. -use tokio; // We use tokio for the async sleep functionality. - -// Synchronous version of a function that simulates a long-running operation -fn calculate_value_synchronously() -> i32 { - println!("Starting synchronous calculation..."); - std::thread::sleep(Duration::from_secs(2)); // Simulating a long-running task - println!("Synchronous calculation done."); - 42 // returns a computed value +// 自定义错误类型 +#[derive(Debug)] +enum TaskError { + Timeout, + Other(String), } -// Converted to async version -async fn calculate_value_asynchronously() -> i32 { - println!("Starting asynchronous calculation..."); - tokio::time::sleep(Duration::from_secs(2)).await; // Using Tokio's async sleep - println!("Asynchronous calculation done."); - 42 // returns a computed value +impl fmt::Display for TaskError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + TaskError::Timeout => write!(f, "Task timed out"), + TaskError::Other(ref err) => write!(f, "Other error: {}", err), + } + } } -async fn main_async() { - println!("Calling synchronous function:"); - let sync_result = calculate_value_synchronously(); - println!("Result from synchronous function: {}", sync_result); +async fn run_async_task(id: usize) -> Result { + let start = Instant::now(); + // Simulate a possible failure + if id == 5 { + // Simulate a timeout error + task::sleep(Duration::from_millis(100)).await; + return Err(TaskError::Timeout); + } else if id == 8 { + // Simulate another type of error + return Err(TaskError::Other("Unexpected error".to_string())); + } - println!("Calling asynchronous function:"); - let async_result = calculate_value_asynchronously().await; - println!("Result from asynchronous function: {}", async_result); + // Normal operation with async sleep + task::sleep(Duration::from_millis(250)).await; + println!("Task {id} done"); + Ok(start.elapsed().as_millis()) } +async fn main() { + let mut tasks = Vec::new(); + + for i in 0..10 { + tasks.push(run_async_task(i)); + } + + let results: Vec> = futures::future::join_all(tasks).await; + + // Process results + for (i, result) in results.into_iter().enumerate() { + match result { + Ok(duration) => println!("Task {i} took {duration}ms"), + Err(e) => println!("Task {i} failed with error: {}", e), + } + } +} + +// Main function that starts the async main function using `task::block_on`. fn main() { - block_on(main_async()); + task::block_on(main()); } diff --git a/solutions/24_async/async3.rs b/solutions/24_async/async3.rs deleted file mode 100644 index 1a133b54..00000000 --- a/solutions/24_async/async3.rs +++ /dev/null @@ -1,43 +0,0 @@ -// This program demonstrates error handling in asynchronous Rust code. We simulate a function that can fail, -// and handle the error appropriately in an asynchronous context. - -use std::time::Duration; -use futures::executor::block_on; // For running the async main function in this educational context. -use tokio; // We use tokio for the async functionality. -use anyhow::{Result, anyhow}; // To simplify error handling - -// Asynchronous function that might fail -async fn might_fail(id: u32) -> Result { - if id % 2 == 0 { - tokio::time::sleep(Duration::from_millis(500)).await; - Ok(id) - } else { - tokio::time::sleep(Duration::from_millis(500)).await; - Err(anyhow!("Failed on odd id")) - } -} - -async fn main_async() { - let ids = [1, 2, 3, 4, 5]; - let mut results = Vec::new(); - - for id in ids { - let result = might_fail(id).await; - match result { - Ok(num) => results.push(Ok(num)), - Err(e) => results.push(Err(e)), - } - } - - // Display results - for result in results { - match result { - Ok(num) => println!("Processed number: {}", num), - Err(e) => println!("Error occurred: {}", e), - } - } -} - -fn main() { - block_on(main_async()); -}