【Iced】stream.rs文件

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 类型。这提供了:

  1. 统一接口:所有事件源都表现为同一种类型
  2. 组合能力:可以轻松合并、转换事件流
  3. 灵活性:支持多种事件生产方式

应用场景

这个模块通常用于:

  • GUI应用:处理用户输入、系统事件
  • 实时系统:处理数据流、定时任务
  • 异步编程:统一处理各种异步数据源
  • 事件驱动架构:作为事件总线的基础

通过提供这些工具函数,开发者可以专注于业务逻辑,而不必关心不同类型事件流的底层实现细节。

相关推荐
Kapaseker2 小时前
精通 Rust 宏 — 包装新类型
rust
飞函安全2 小时前
Vite 8.0:Rust.bundle,性能提升10-30倍
开发语言·人工智能·rust
奋斗中的小猩猩14 小时前
OpenClaw不安全,Rust写的ZeroClaw给出满意答案
安全·rust·openclaw·小龙虾
海奥华215 小时前
Rust初步学习
开发语言·学习·rust
VermouthSp17 小时前
上下文切换
linux·rust
小杍随笔1 天前
【Rust 1.94.0 正式发布:数组窗口、Cargo 配置模块化、TOML 1.1 全面升级|开发者必看】
开发语言·后端·rust
敬业小码哥2 天前
记一次:clion使用rust插件配置环境并开发
学习·rust
NGINX开源社区2 天前
NGINX 引入对 ACME 协议的原生支持
nginx·rust
Rust语言中文社区2 天前
【Rust日报】 CEL与Rust实现接近原生速度的解释执行
开发语言·后端·rust