### Blocking on an Async Future in Rust Source: https://github.com/smol-rs/futures-lite/blob/master/README.md This example demonstrates how to use `futures_lite::future::block_on` to run an asynchronous operation to completion on the current thread. It's useful for integrating async code into synchronous contexts or for simple async tasks. ```rust use futures_lite::future; fn main() { future::block_on(async { println!("Hello world!"); }) } ``` -------------------------------- ### Limit Stream Output with StreamExt::take, skip, take_while, skip_while Source: https://context7.com/smol-rs/futures-lite/llms.txt Details methods for controlling the number and conditions of items yielded by a stream. `take` and `skip` limit by count, while `take_while` and `skip_while` use a predicate to determine when to start or stop yielding items. ```rust use futures_lite::stream::{self, StreamExt}; // Assuming spin_on::spin_on is available for running async code # spin_on::spin_on(async { // Take first N items let first_two: Vec<_> = stream::iter(1..=5).take(2).collect().await; assert_eq!(first_two, vec![1, 2]); // Skip first N items let after_two: Vec<_> = stream::iter(1..=5).skip(2).collect().await; assert_eq!(after_two, vec![3, 4, 5]); // Take while predicate is true let small: Vec<_> = stream::iter(vec![1, 2, 5, 1]) .take_while(|x| *x < 3) .collect().await; assert_eq!(small, vec![1, 2]); // Skip while predicate is true let after_small: Vec<_> = stream::iter(vec![1, 2, 5, 1]) .skip_while(|x| *x < 3) .collect().await; assert_eq!(after_small, vec![5, 1]); # }); ``` -------------------------------- ### io::BufWriter - Buffered Asynchronous Writing in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Explains `BufWriter` from futures-lite, which adds buffering to any asynchronous writer. This enhances performance by accumulating writes in a buffer before flushing them to the underlying writer. The example shows writing and flushing data to a `Vec`. ```rust use futures_lite::io::{AsyncWriteExt, BufWriter}; # spin_on::spin_on(async { let mut output = Vec::new(); let mut writer = BufWriter::new(&mut output); writer.write_all(b"hello").await?; writer.write_all(b" world").await?; writer.flush().await?; assert_eq!(output, b"hello world"); # std::io::Result::Ok(() }); ``` -------------------------------- ### Importing commonly used traits with futures_lite::prelude in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Shows how to import all essential traits from `futures-lite` using the `prelude` module. This provides convenient access to extensions for `Future`, `Stream`, and various I/O traits. ```rust use futures_lite::prelude::*; // Now you have access to: // - Future, FutureExt // - Stream, StreamExt // - AsyncRead, AsyncReadExt (with std feature) // - AsyncWrite, AsyncWriteExt (with std feature) // - AsyncBufRead, AsyncBufReadExt (with std feature) // - AsyncSeek, AsyncSeekExt (with std feature) ``` -------------------------------- ### Using the ready! macro for Poll in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Demonstrates the `ready!` macro from `futures-lite`, which simplifies polling futures by unwrapping `Poll::Ready(T)` or returning `Poll::Pending`. This macro is commonly used within custom future implementations. ```rust use futures_lite::{future, prelude::*, ready}; use std::pin::Pin; use std::task::{Context, Poll}; fn do_poll(cx: &mut Context<'_>) -> Poll { let mut fut = future::ready(42); let fut = Pin::new(&mut fut); let num = ready!(fut.poll(cx)); Poll::Ready(num * 2) } ``` -------------------------------- ### Cursor I/O Operations in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Demonstrates asynchronous read, write, and seek operations on a `Cursor` using `futures-lite`. This snippet showcases basic I/O manipulation within an async context, handling data buffering and position tracking. ```rust use futures_lite::io::Cursor; use futures_lite::prelude::* use std::io::{SeekFrom, Write}; # spin_on::spin_on(async { let mut cursor = Cursor::new(vec![0u8; 10]); // Write at position 0 cursor.write_all(b"hello").await?; assert_eq!(cursor.position(), 5); // Seek back to start cursor.seek(SeekFrom::Start(0)).await?; // Read what we wrote let mut buf = vec![0u8; 5]; cursor.read_exact(&mut buf).await?; assert_eq!(&buf, b"hello"); # std::io::Result::Ok(()) }); ``` -------------------------------- ### Stack Pinning with pin! macro in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Illustrates the `pin!` macro from `futures-lite`, which pins a value on the stack. This is essential for working with futures that have `!Unpin` bounds, allowing them to be used in contexts requiring pinning without heap allocation. ```rust use futures_lite::{future, pin}; use std::future::Future; async fn example(f: impl Future) -> T { pin!(f); future::poll_fn(|cx| f.as_mut().poll(cx)).await } ``` -------------------------------- ### Combine Streams with StreamExt::chain and zip Source: https://context7.com/smol-rs/futures-lite/llms.txt Illustrates how to combine multiple streams. `chain` concatenates streams sequentially, while `zip` pairs corresponding items from two streams into tuples. This is useful for processing data from multiple sources. ```rust use futures_lite::stream::{self, StreamExt}; // Assuming spin_on::spin_on is available for running async code # spin_on::spin_on(async { // Chain: concatenate streams let s1 = stream::iter(vec![1, 2]); let s2 = stream::iter(vec![3, 4]); let chained: Vec<_> = s1.chain(s2).collect().await; assert_eq!(chained, vec![1, 2, 3, 4]); // Zip: pair items from two streams let nums = stream::iter(vec![1, 2, 3]); let chars = stream::iter(vec!['a', 'b', 'c']); let zipped: Vec<_> = nums.zip(chars).collect().await; assert_eq!(zipped, vec![(1, 'a'), (2, 'b'), (3, 'c')]); # }); ``` -------------------------------- ### Create Immediate or Pending Futures with futures_lite::future::ready and future::pending Source: https://context7.com/smol-rs/futures-lite/llms.txt Creates futures that either resolve immediately with a value (`ready`) or never resolve (`pending`). `ready` is useful for providing default or initial values, while `pending` can be used in scenarios like timeouts or race conditions where a future should not complete. ```rust use futures_lite::future::{self, FutureExt}; // spin_on is used in place of block_on for doctests # spin_on::spin_on(async { // A future that is immediately ready let ready_fut = future::ready(42); assert_eq!(ready_fut.await, 42); // A future that never resolves (useful for timeouts/races) let pending_fut = future::pending::(); // pending_fut.await would block forever # }); ``` -------------------------------- ### AsyncBufReadExt Methods - Reading Lines and Delimited Content in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Explains `AsyncBufReadExt` methods in futures-lite for reading lines and delimited content from asynchronous buffered readers. Includes reading lines as a stream and reading data until a specific delimiter is encountered. ```rust use futures_lite::io::{AsyncBufReadExt, BufReader}; use futures_lite::stream::StreamExt; # spin_on::spin_on(async { let input: &[u8] = b"line1\nline2\nline3\n"; let reader = BufReader::new(input); // Read lines as a stream let lines: Vec = reader.lines() .map(|r| r.unwrap()) .collect().await; assert_eq!(lines, vec!["line1", "line2", "line3"]); // Read until delimiter let input: &[u8] = b"hello;world;"; let mut reader = BufReader::new(input); let mut buf = Vec::new(); reader.read_until(b';', &mut buf).await?; assert_eq!(buf, b"hello;"); # std::io::Result::Ok(() }); ``` -------------------------------- ### Async Mapping with StreamExt::then Source: https://context7.com/smol-rs/futures-lite/llms.txt Shows how to apply an asynchronous transformation to each item in a stream using `StreamExt::then`. This is useful when the transformation itself involves asynchronous operations. ```rust use futures_lite::stream::{self, StreamExt}; use futures_lite::pin; // Assuming spin_on::spin_on is available for running async code # spin_on::spin_on(async { let s = stream::iter(vec![1, 2, 3]) .then(|x| async move { x * 2 }); pin!(s); assert_eq!(s.next().await, Some(2)); assert_eq!(s.next().await, Some(4)); assert_eq!(s.next().await, Some(6)); # }); ``` -------------------------------- ### AsyncWriteExt Methods - Writing to Asynchronous Sinks in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Covers the `AsyncWriteExt` methods in futures-lite for writing data to asynchronous sinks. Demonstrates writing a slice of bytes, writing all bytes from a slice, flushing the buffer, and closing the writer. ```rust use futures_lite::io::{AsyncWriteExt, Cursor}; # spin_on::spin_on(async { let mut buffer = vec![0u8; 20]; let mut writer = Cursor::new(&mut buffer[..]); // Write some bytes let n = writer.write(b"hello").await?; assert_eq!(n, 5); // Write all bytes writer.write_all(b" world").await?; // Flush to ensure data is written writer.flush().await?; // Close the writer writer.close().await?; # std::io::Result::Ok(() }); ``` -------------------------------- ### Create Single or Empty Streams using stream::once and stream::empty Source: https://context7.com/smol-rs/futures-lite/llms.txt Shows how to create streams that yield exactly one item (`stream::once`) or no items at all (`stream::empty`). Useful for representing simple or non-existent data sequences. ```rust use futures_lite::stream::{self, StreamExt}; // Assuming spin_on::spin_on is available for running async code # spin_on::spin_on(async { // Single item stream let mut s = stream::once(42); assert_eq!(s.next().await, Some(42)); assert_eq!(s.next().await, None); // Empty stream let mut empty = stream::empty::(); assert_eq!(empty.next().await, None); # }); ``` -------------------------------- ### Transform and Filter Streams with StreamExt::map, filter, filter_map Source: https://context7.com/smol-rs/futures-lite/llms.txt Demonstrates common stream transformations using `StreamExt` methods like `map` for item transformation, `filter` for conditional inclusion, and `filter_map` for combined transformation and filtering. These methods enable efficient data processing pipelines. ```rust use futures_lite::stream::{self, StreamExt}; // Assuming spin_on::spin_on is available for running async code # spin_on::spin_on(async { // Map: transform each item let doubled: Vec<_> = stream::iter(vec![1, 2, 3]) .map(|x| x * 2) .collect().await; assert_eq!(doubled, vec![2, 4, 6]); // Filter: keep items matching predicate let evens: Vec<_> = stream::iter(vec![1, 2, 3, 4, 5]) .filter(|x| x % 2 == 0) .collect().await; assert_eq!(evens, vec![2, 4]); // Filter map: transform and filter in one step let parsed: Vec = stream::iter(vec!["1", "two", "3"]) .filter_map(|s| s.parse().ok()) .collect().await; assert_eq!(parsed, vec![1, 3]); # }); ``` -------------------------------- ### StreamExt::enumerate and peekable - Enhanced Iteration in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Demonstrates how to add indices to streams using `enumerate` and how to peek at the next item without consuming it using `peekable` in Rust with futures-lite. ```rust use futures_lite::stream::{self, StreamExt}; # spin_on::spin_on(async { // Enumerate: add indices let indexed: Vec<_> = stream::iter(vec!['a', 'b', 'c']) .enumerate() .collect().await; assert_eq!(indexed, vec![(0, 'a'), (1, 'b'), (2, 'c')]); // Peekable: look at next item without consuming let mut stream = stream::iter(1..=3).peekable(); assert_eq!(stream.peek().await, Some(&1)); assert_eq!(stream.peek().await, Some(&1)); // Still there assert_eq!(stream.next().await, Some(1)); // Now consumed assert_eq!(stream.peek().await, Some(&2)); # }); ``` -------------------------------- ### Async Closure Comparison: futures vs futures-lite Source: https://github.com/smol-rs/futures-lite/blob/master/FEATURES.md Demonstrates the difference in how `all` combinators handle closures in the `futures` and `futures-lite` crates. `futures-lite` uses regular closures for simplicity, while `futures` requires closures returning futures. ```rust // In `futures`, the `all` combinator takes a closure returning a future. my_stream.all(|x| async move { x > 5 }).await; // In `futures-lite`, the `all` combinator just takes a closure. my_stream.all(|x| x > 5).await; ``` -------------------------------- ### io::BufReader - Buffered Asynchronous Reading in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Introduces `BufReader` from futures-lite for adding buffering to any asynchronous reader, improving performance by reducing the number of underlying read calls. It demonstrates reading lines from a buffer. ```rust use futures_lite::io::{AsyncBufReadExt, BufReader}; # spin_on::spin_on(async { let input: &[u8] = b"hello\nworld\n"; let mut reader = BufReader::new(input); let mut line = String::new(); reader.read_line(&mut line).await?; assert_eq!(line, "hello\n"); # std::io::Result::Ok(() }); ``` -------------------------------- ### AsyncReadExt Methods - Reading from Asynchronous Sources in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Details various methods provided by `AsyncReadExt` in futures-lite for reading data from asynchronous sources. Includes reading into a buffer, reading an exact number of bytes, reading all remaining data, and reading data into a string. ```rust use futures_lite::io::{AsyncReadExt, Cursor}; # spin_on::spin_on(async { let mut reader = Cursor::new(b"hello world"); // Read into buffer let mut buf = vec![0u8; 5]; let n = reader.read(&mut buf).await?; assert_eq!(&buf[..n], b"hello"); // Read exact number of bytes reader.read_exact(&mut buf).await?; assert_eq!(&buf, b" worl"); // Read to end let mut reader = Cursor::new(b"hello"); let mut contents = Vec::new(); reader.read_to_end(&mut contents).await?; assert_eq!(contents, b"hello"); // Read to string let mut reader = Cursor::new(b"hello"); let mut contents = String::new(); reader.read_to_string(&mut contents).await?; assert_eq!(contents, "hello"); # std::io::Result::Ok(() }); ``` -------------------------------- ### Create Infinite Streams using stream::repeat and stream::repeat_with Source: https://context7.com/smol-rs/futures-lite/llms.txt Illustrates the creation of infinite streams that continuously repeat a value (`stream::repeat`) or generate values using a closure (`stream::repeat_with`). These are often used with `.take()` to limit their output. ```rust use futures_lite::stream::{self, StreamExt}; // Assuming spin_on::spin_on is available for running async code # spin_on::spin_on(async { // Repeat same value let mut s = stream::repeat(7).take(3); assert_eq!(s.collect::>().await, vec![7, 7, 7]); // Repeat with closure let mut counter = 0; let mut s = stream::repeat_with(|| { counter += 1; counter }).take(3); assert_eq!(s.collect::>().await, vec![1, 2, 3]); # }); ``` -------------------------------- ### Generate Stateful Streams with stream::unfold Source: https://context7.com/smol-rs/futures-lite/llms.txt Explains how to create streams dynamically using `stream::unfold`, which takes a seed value and an asynchronous closure to generate stream items and the next state. This is powerful for complex data generation. ```rust use futures_lite::stream::{self, StreamExt}; // Assuming spin_on::spin_on is available for running async code # spin_on::spin_on(async { let s = stream::unfold(0, |n| async move { if n < 3 { Some((n * 2, n + 1)) // (yield_value, next_state) } else { None // End stream } }); let v: Vec = s.collect().await; assert_eq!(v, [0, 2, 4]); # }); ``` -------------------------------- ### Splitting Stream into Read/Write Halves with io::split in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Demonstrates how to use `futures_lite::io::split` to divide a single asynchronous stream into independent read and write components. This is particularly useful for handling bidirectional communication protocols. ```rust use futures_lite::io::{self, AsyncReadExt, AsyncWriteExt, Cursor}; # spin_on::spin_on(async { let stream = Cursor::new(vec![0u8; 100]); let (mut reader, mut writer) = io::split(stream); // Can now use reader and writer independently // (useful for bidirectional streams like TCP) # std::io::Result::Ok(()) }); ``` -------------------------------- ### Selecting the First Completed Future: futures vs futures-concurrency Source: https://github.com/smol-rs/futures-lite/blob/master/FEATURES.md Illustrates how to implement a `select!`-like behavior using `futures-concurrency`'s `race()` combinator, comparing it to the `select!` macro in the `futures` crate. ```rust let (a, b, c) = /* assume these are all futures */; // futures let x = select! { a_res = a => a_res + 1, _ = b => 0, c_res = c => c_res + 3, }; // futures-concurrency let x = ( async move { a.await + 1 }, async move { b.await; 0 }, async move { c.await + 3 } ).race().await; ``` -------------------------------- ### Create Stream from Iterator using stream::iter Source: https://context7.com/smol-rs/futures-lite/llms.txt Demonstrates how to create a stream from a standard Rust iterator using `futures_lite::stream::iter`. This allows for asynchronous processing of sequential data. ```rust use futures_lite::stream::{self, StreamExt}; // Assuming spin_on::spin_on is available for running async code # spin_on::spin_on(async { let mut s = stream::iter(vec![1, 2, 3]); assert_eq!(s.next().await, Some(1)); assert_eq!(s.next().await, Some(2)); assert_eq!(s.next().await, Some(3)); assert_eq!(s.next().await, None); # }); ``` -------------------------------- ### Map Future Output with Async/Await (Rust) Source: https://github.com/smol-rs/futures-lite/blob/master/FEATURES.md Demonstrates how to achieve the functionality of the futures::FutureExt::map combinator using async/await syntax in Rust. This approach avoids the need for a dedicated combinator by awaiting the future within an async block and then processing its result. ```Rust let my_future = async { 1 }; // Add one to the result of `my_future`. let mapped_future = async move { my_future.await + 1 }; // In a real scenario, you would await mapped_future here. // assert_eq!(mapped_future.await, 2); ``` -------------------------------- ### StreamExt::flat_map and flatten - Handling Nested Streams in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Shows how to flatten nested stream structures in Rust. `flat_map` maps each item to a stream and then flattens the resulting streams, while `flatten` directly flattens a stream of streams. ```rust use futures_lite::stream::{self, StreamExt}; # spin_on::spin_on(async { // Flat map: map to streams and flatten let words = stream::iter(vec!["hello", "world"]); let chars: String = words .flat_map(|s| stream::iter(s.chars())) .collect().await; assert_eq!(chars, "helloworld"); // Flatten: flatten nested streams let nested = stream::iter(vec![ stream::iter(vec![1, 2]), stream::iter(vec![3, 4]), ]); let flat: Vec<_> = nested.flatten().collect().await; assert_eq!(flat, vec![1, 2, 3, 4]); # }); ``` -------------------------------- ### Concurrent Future Execution: futures vs futures-concurrency Source: https://github.com/smol-rs/futures-lite/blob/master/FEATURES.md Compares the `join!` macro from the `futures` crate with the `join()` method from the `futures-concurrency` crate for waiting on multiple futures simultaneously. ```rust let (a, b, c) = /* assume these are all futures */; // futures let (x, y, z) = join!(a, b, c); // futures-concurrency use futures_concurrency::prelude::*; let (x, y, z) = (a, b, c).join().await; ``` -------------------------------- ### Implementing Async Operations with futures-lite's `then` and `all` Source: https://github.com/smol-rs/futures-lite/blob/master/FEATURES.md Shows how to achieve functionality similar to `futures`' `all` with an async function using `futures-lite`'s `then` combinator followed by `all`. This pattern is used when a direct async closure is needed. ```rust // In `futures`. my_stream.all(|x| my_async_fn(x)).await; // In `futures-lite`, use `then` and pass the result to `all`. my_stream.then(|x| my_async_fn(x)).all(|pass| pass).await; ``` -------------------------------- ### Select First Ready Future with futures_lite::future::or Source: https://context7.com/smol-rs/futures-lite/llms.txt Returns the result of the first future that completes. If both futures complete at the same time, the first future (`a` in `future::or(a, b)`) is preferred. This is useful for implementing fallback mechanisms or default values. ```rust use futures_lite::future::{self, pending, ready}; # spin_on::spin_on(async { // First future wins if ready assert_eq!(future::or(ready(1), ready(2)).await, 1); // Falls back to second if first is pending assert_eq!(future::or(pending(), ready(2)).await, 2); # }); ``` -------------------------------- ### io::Cursor - In-Memory Asynchronous I/O in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Introduces `Cursor` from futures-lite, which provides asynchronous reading and writing capabilities for in-memory byte buffers. It supports standard I/O traits and seeking within the buffer. ```rust use futures_lite::io::{AsyncReadExt, AsyncWriteExt, AsyncSeekExt, Cursor, SeekFrom}; ``` -------------------------------- ### stream::or and stream::race - Merging Streams in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Illustrates merging two asynchronous streams using `stream::or` which prefers the first stream when both are ready, and `stream::race` which randomly chooses between streams when both are ready in Rust. ```rust use futures_lite::stream::{self, StreamExt, once, pending}; # spin_on::spin_on(async { // Or: prefer first stream when both ready assert_eq!(stream::or(once(1), once(2)).next().await, Some(1)); assert_eq!(stream::or(pending(), once(2)).next().await, Some(2)); // Race: randomly choose when both ready let result = stream::race(once(1), once(2)).next().await; assert!(result == Some(1) || result == Some(2)); # }); ``` -------------------------------- ### Aggregate Stream Items with StreamExt::fold and collect Source: https://context7.com/smol-rs/futures-lite/llms.txt Demonstrates methods for aggregating stream items into a single result. `fold` reduces the stream to a single value using an accumulator, while `collect` gathers all items into a collection like a `Vec`. `count` is also shown for simply counting items. ```rust use futures_lite::stream::{self, StreamExt}; // Assuming spin_on::spin_on is available for running async code # spin_on::spin_on(async { // Fold: reduce to single value let sum = stream::iter(vec![1, 2, 3, 4]) .fold(0, |acc, x| acc + x) .await; assert_eq!(sum, 10); // Collect: gather into collection let items: Vec<_> = stream::iter(1..=3).collect().await; assert_eq!(items, vec![1, 2, 3]); // Count items let count = stream::iter(vec![1, 2, 3]).count().await; assert_eq!(count, 3); # }); ``` -------------------------------- ### Utility Readers/Writers (empty, repeat, sink) in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Showcases `futures_lite::io` utility functions: `empty` (always returns EOF), `repeat` (infinite stream of a byte), and `sink` (discards all written data). These are helpful for testing and specific I/O scenarios. ```rust use futures_lite::io::{self, AsyncReadExt, AsyncWriteExt}; # spin_on::spin_on(async { // Empty reader (always returns EOF) let mut reader = io::empty(); let mut buf = vec![0u8; 10]; let n = reader.read(&mut buf).await?; assert_eq!(n, 0); // Repeat reader (infinite stream of same byte) let mut reader = io::repeat(b'x'); let mut buf = vec![0u8; 5]; reader.read_exact(&mut buf).await?; assert_eq!(&buf, b"xxxxx"); // Sink writer (discards all data) let mut writer = io::sink(); writer.write_all(b"discarded").await?; # std::io::Result::Ok(()) }); ``` -------------------------------- ### Stream Copy with io::copy in Rust Source: https://context7.com/smol-rs/futures-lite/llms.txt Illustrates copying data from an asynchronous reader to an asynchronous writer using `futures_lite::io::copy`. This function is useful for efficiently transferring data between streams without loading the entire content into memory. ```rust use futures_lite::io::{self, BufReader, BufWriter}; # spin_on::spin_on(async { let input: &[u8] = b"hello world"; let reader = BufReader::new(input); let mut output = Vec::new(); let writer = BufWriter::new(&mut output); let bytes_copied = io::copy(reader, writer).await?; assert_eq!(bytes_copied, 11); # std::io::Result::Ok(()) }); ``` -------------------------------- ### Combine Futures with futures_lite::future::zip Source: https://context7.com/smol-rs/futures-lite/llms.txt Waits for two futures to complete simultaneously. It returns a tuple containing the results of both futures once they have both finished. If either future returns an error, `zip` does not propagate it directly but waits for both to complete. ```rust use futures_lite::future; # spin_on::spin_on(async { let a = async { 1 }; let b = async { "hello" }; let (num, text) = future::zip(a, b).await; assert_eq!(num, 1); assert_eq!(text, "hello"); # }); ``` -------------------------------- ### AndThen Future Operation with Async/Await (Rust) Source: https://github.com/smol-rs/futures-lite/blob/master/FEATURES.md Illustrates how to implement the functionality of the futures::FutureExt::and_then combinator using async/await syntax in Rust. This method chains operations on futures that return a Result, avoiding the need for the TryFutureExt trait. ```Rust let my_future = async { Ok(2) }; let and_then = async move { let x = my_future.await; x.and_then(|x| Ok(x + 1)) }; // In a real scenario, you would await and_then here. // assert_eq!(and_then.await.unwrap(), 3); ``` -------------------------------- ### Combine Fallible Futures with futures_lite::future::try_zip Source: https://context7.com/smol-rs/futures-lite/llms.txt Combines two fallible futures (those that return `Result`). It waits for both to complete successfully, returning a tuple of their `Ok` values. If either future returns an `Err`, `try_zip` immediately returns that error without waiting for the other future to complete. ```rust use futures_lite::future; # spin_on::spin_on(async { let a = async { Ok::(1) }; let b = async { Ok::(2) }; match future::try_zip(a, b).await { Ok((x, y)) => assert_eq!((x, y), (1, 2)), Err(e) => println!("Error: {}", e), } // With an error let c = async { Ok::(1) }; let d = async { Err::("failed") }; let result = future::try_zip(c, d).await; assert_eq!(result, Err("failed")); # }); ``` -------------------------------- ### Cooperative Yielding with futures_lite::future::yield_now Source: https://context7.com/smol-rs/futures-lite/llms.txt Allows the current asynchronous task to yield control back to the executor. This enables other pending tasks to make progress, preventing starvation and improving overall responsiveness in concurrent applications. ```rust use futures_lite::future; # spin_on::spin_on(async { for step in 0..3 { println!("step {}", step); // Give other tasks a chance to run future::yield_now().await; } # }); ``` -------------------------------- ### Select First Ready Future Fairly with futures_lite::future::race Source: https://context7.com/smol-rs/futures-lite/llms.txt Returns the result of the first future that completes. Unlike `or`, if both futures complete simultaneously, `race` chooses one of them randomly. This is useful for scenarios like implementing timeouts where fairness is desired. ```rust use futures_lite::future::{self, pending, ready}; # spin_on::spin_on(async { // One of these will win (randomly chosen if both ready) let result = future::race(ready(1), ready(2)).await; assert!(result == 1 || result == 2); // Useful for timeouts assert_eq!(future::race(ready(1), pending()).await, 1); # }); ``` -------------------------------- ### Boxing Futures for Trait Implementation (Rust) Source: https://github.com/smol-rs/futures-lite/blob/master/FEATURES.md Shows a workaround for returning futures from trait methods when the future's type is not known at compile time, a common issue when using async blocks. This involves boxing the future to create a dynamic dispatch object, though it may introduce overhead. ```Rust use std::pin::Pin; use futures_lite::Future; // Assume Service trait and MyService struct are defined elsewhere // trait Service { type Future: Future; fn call(&mut self) -> Self::Future; } // struct MyService; // impl Service for MyService { // type Future = Pin>>; // // fn call(&mut self) -> Self::Future { // async { 1 + 1 }.boxed_local() // } // } ``` -------------------------------- ### Panic Safety for Futures with FutureExt::catch_unwind Source: https://context7.com/smol-rs/futures-lite/llms.txt Provides a mechanism to catch panics that occur during the execution of an asynchronous future. If a panic occurs, `catch_unwind` returns it as an `Err` variant, preventing the entire program from crashing and allowing for graceful error handling. ```rust use futures_lite::future::FutureExt; ``` -------------------------------- ### Create Futures from Callbacks with futures_lite::future::poll_fn Source: https://context7.com/smol-rs/futures-lite/llms.txt Constructs a future from a closure that manually polls its state. The closure receives a `Context` and must return a `Poll` enum (`Ready` or `Pending`). This is useful for integrating existing polling logic into the async ecosystem. ```rust use futures_lite::future; use std::task::{Context, Poll}; # spin_on::spin_on(async { let mut counter = 0; let result = future::poll_fn(|_cx| { counter += 1; if counter >= 3 { Poll::Ready(counter) } else { Poll::Ready(counter) // For demo, return immediately } }).await; assert!(result >= 1); # }); ``` -------------------------------- ### Block on a Future with futures_lite::future::block_on Source: https://context7.com/smol-rs/futures-lite/llms.txt Blocks the current thread until a given future completes. This is useful for integrating asynchronous code into synchronous contexts. It takes an async block or future as input and returns its resolved value. ```rust use futures_lite::future; fn main() { let result = future::block_on(async { // Perform async operations let a = 10; let b = 20; a + b }); assert_eq!(result, 30); println!("Result: {}", result); } ``` -------------------------------- ### Type Erasure for Futures with FutureExt::boxed Source: https://context7.com/smol-rs/futures-lite/llms.txt Allows boxing a future, effectively erasing its concrete type. This is crucial when you need to store futures of different types in the same collection (e.g., a `Vec`) or pass them around generically without knowing their exact type at compile time. ```rust use futures_lite::future::{self, FutureExt, Boxed}; # spin_on::spin_on(async { let f1: Boxed = async { 1 + 2 }.boxed(); let f2: Boxed = future::ready(10).boxed(); // Can now store in same collection let futures: Vec> = vec![f1, f2]; # }); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.