rust
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use futures::stream::Stream;
use crate::subscription::EventStream;
/// 将Stream转换为EventStream
pub fn from_stream<Message, S>(stream: S) -> EventStream<Message>
where
Message: 'static + Send,
S: Stream<Item = Message> + Send + 'static,
{
EventStream::from(Box::pin(stream))
}
/// 将Future转换为EventStream
pub fn from_future<Message, F>(future: F) -> EventStream<Message>
where
Message: 'static + Send,
F: Future<Output = Message> + Send + 'static,
{
from_stream(futures::stream::once(future))
}
/// 将多个EventStream合并为一个
pub fn merge<Message>(streams: Vec<EventStream<Message>>) -> EventStream<Message>
where
Message: 'static + Send,
{
if streams.is_empty() {
return EventStream::from(Box::pin(futures::stream::empty()));
}
let mut merged = streams.into_iter().map(Into::into).collect::<Vec<_>>();
EventStream::from(Box::pin(futures::stream::select_all(merged)))
}
/// 创建一个空的EventStream
pub fn empty<Message>() -> EventStream<Message>
where
Message: 'static + Send,
{
EventStream::from(Box::pin(futures::stream::empty()))
}
/// 创建一个只包含单个消息的EventStream
pub fn once<Message>(message: Message) -> EventStream<Message>
where
Message: 'static + Send,
{
from_future(async { message })
}
/// 创建一个周期触发的EventStream
pub fn interval<Message, F>(duration: std::time::Duration, f: F) -> EventStream<Message>
where
Message: 'static + Send,
F: Fn() -> Message + Send + Sync + 'static,
{
let stream = futures::stream::unfold((), move |_| async move {
tokio::time::sleep(duration).await;
Some((f(), ()))
});
EventStream::from(Box::pin(stream))
}
/// 将Iterator转换为EventStream
pub fn from_iter<Message, I>(iter: I) -> EventStream<Message>
where
Message: 'static + Send,
I: IntoIterator<Item = Message> + Send + 'static,
I::IntoIter: Send,
{
let stream = futures::stream::iter(iter);
EventStream::from(Box::pin(stream))
}
/// 创建一个可以动态发送消息的EventStream
pub fn channel<Message>(buffer: usize) -> (mpsc::Sender<Message>, EventStream<Message>)
where
Message: 'static + Send,
{
let (sender, receiver) = mpsc::channel(buffer);
(sender, EventStream::from(Box::pin(receiver)))
}
#[cfg(test)]
mod tests {
use super::*;
use futures::StreamExt;
#[tokio::test]
async fn test_from_stream() {
let stream = futures::stream::iter(vec![1, 2, 3]);
let mut event_stream = from_stream(stream);
assert_eq!(event_stream.next().await, Some(1));
assert_eq!(event_stream.next().await, Some(2));
assert_eq!(event_stream.next().await, Some(3));
assert_eq!(event_stream.next().await, None);
}
#[tokio::test]
async fn test_from_future() {
let future = async { 42 };
let mut event_stream = from_future(future);
assert_eq!(event_stream.next().await, Some(42));
assert_eq!(event_stream.next().await, None);
}
#[tokio::test]
async fn test_merge() {
let stream1 = from_iter(vec![1, 2, 3]);
let stream2 = from_iter(vec![4, 5, 6]);
let stream3 = from_iter(vec![7, 8, 9]);
let merged = merge(vec![stream1, stream2, stream3]);
let results: Vec<i32> = merged.collect().await;
// select_all会随机选择,所以只验证长度和包含的元素
assert_eq!(results.len(), 9);
for i in 1..=9 {
assert!(results.contains(&i));
}
}
#[tokio::test]
async fn test_empty() {
let mut empty_stream: EventStream<i32> = empty();
assert_eq!(empty_stream.next().await, None);
}
#[tokio::test]
async fn test_once() {
let mut once_stream = once(42);
assert_eq!(once_stream.next().await, Some(42));
assert_eq!(once_stream.next().await, None);
}
#[tokio::test]
async fn test_interval() {
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use tokio::time::timeout;
let counter = Arc::new(AtomicUsize::new(0));
let counter_clone = counter.clone();
let interval_stream = interval(
std::time::Duration::from_millis(10),
move || {
counter_clone.fetch_add(1, Ordering::SeqCst);
42
}
);
// 只取前3个值,避免无限等待
let mut limited_stream = interval_stream.take(3);
let results: Vec<i32> = limited_stream.collect().await;
assert_eq!(results, vec![42, 42, 42]);
assert_eq!(counter.load(Ordering::SeqCst), 3);
}
#[tokio::test]
async fn test_from_iter() {
let vec = vec![1, 2, 3, 4, 5];
let mut iter_stream = from_iter(vec);
for i in 1..=5 {
assert_eq!(iter_stream.next().await, Some(i));
}
assert_eq!(iter_stream.next().await, None);
}
#[tokio::test]
async fn test_channel() {
let (sender, mut event_stream) = channel(10);
// 发送消息
sender.send(1).await.unwrap();
sender.send(2).await.unwrap();
sender.send(3).await.unwrap();
// 由于channel是异步的,需要稍微等待一下
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
// 丢弃sender,关闭通道
drop(sender);
assert_eq!(event_stream.next().await, Some(1));
assert_eq!(event_stream.next().await, Some(2));
assert_eq!(event_stream.next().await, Some(3));
assert_eq!(event_stream.next().await, None);
}
}
文件说明
这是一个用于创建和管理 EventStream 的工具函数集合。EventStream 似乎是某个框架(可能是 Iced GUI 框架)中用于处理异步事件流的核心类型。
主要函数
| 函数 | 描述 | 使用场景 |
|---|---|---|
from_stream |
将普通Stream转换为EventStream | 适配外部Stream到框架 |
from_future |
将Future转换为单元素EventStream | 处理一次性异步操作 |
merge |
合并多个EventStream | 组合多个事件源 |
empty |
创建空EventStream | 默认值或条件分支 |
once |
创建包含单个消息的Stream | 立即触发的事件 |
interval |
创建周期性触发的Stream | 定时器、心跳、轮询 |
from_iter |
将Iterator转换为EventStream | 处理静态数据集合 |
channel |
创建可动态发送消息的Stream | 复杂事件生产场景 |
核心模式
所有函数都遵循一个统一模式:接收各种数据源(Stream、Future、Iterator、定时器等),统一包装为 EventStream 类型。这提供了:
- 统一接口:所有事件源都表现为同一种类型
- 组合能力:可以轻松合并、转换事件流
- 灵活性:支持多种事件生产方式
应用场景
这个模块通常用于:
- GUI应用:处理用户输入、系统事件
- 实时系统:处理数据流、定时任务
- 异步编程:统一处理各种异步数据源
- 事件驱动架构:作为事件总线的基础
通过提供这些工具函数,开发者可以专注于业务逻辑,而不必关心不同类型事件流的底层实现细节。