Hone logo
Hone
Problems

Building a Simple Async Data Processor with Rust Streams

Asynchronous programming in Rust, particularly with async streams, allows for efficient handling of data that arrives over time without blocking the main thread. This challenge will guide you through creating a basic asynchronous data processing pipeline, demonstrating how to generate, transform, and consume data asynchronously.

Problem Description

Your task is to implement a Rust program that simulates processing a stream of data asynchronously. You will need to:

  1. Create an asynchronous stream that generates a sequence of numbers.
  2. Transform this stream by applying a function to each element.
  3. Consume the transformed stream and print each element.

This exercise will involve using the futures and tokio crates to manage asynchronous operations and streams.

Key Requirements

  • Stream Generation: Implement a custom Stream that yields u32 values.
  • Stream Transformation: Use stream.map() to transform each u32 into its double.
  • Stream Consumption: Iterate over the transformed stream asynchronously and print each doubled number.
  • Asynchronous Runtime: Utilize tokio as the asynchronous runtime.

Expected Behavior

The program should start, generate numbers from 0 up to a certain limit, double each number, and print the doubled numbers to the console, each on a new line.

Edge Cases to Consider

  • What happens if the stream generation is very slow? (Though for this basic example, we'll simulate quick generation.)
  • How do you correctly handle the end of the stream?

Examples

Example 1:

Input: Stream generates numbers from 0 to 4.
Output:
0
2
4
6
8
Explanation: The stream generates 0, 1, 2, 3, 4. Each number is doubled (0*2=0, 1*2=2, etc.) and printed.

Example 2:

Input: Stream generates numbers from 0 to 2.
Output:
0
2
4
Explanation: The stream generates 0, 1, 2. Each number is doubled (0*2=0, 1*2=2, 2*2=4) and printed.

Constraints

  • The stream should generate at most 100 numbers (from 0 to 99).
  • The numbers generated will be unsigned 32-bit integers (u32).
  • The transformation function should be simple multiplication by 2.
  • The output should be printed to standard output.
  • Your solution must use the tokio runtime and the futures crate.

Notes

  • You'll need to add tokio and futures to your Cargo.toml dependencies.
  • Consider using tokio::time::sleep to simulate some work if you want to observe the asynchronous nature more clearly, although it's not strictly required for the core functionality.
  • The futures crate provides the Stream trait and various combinator methods like map.
  • Remember to use #[tokio::main] to set up the asynchronous entry point for your application.
  • The futures::stream::StreamExt trait provides useful extension methods for streams.
Loading editor...
rust