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

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

相关推荐
对象存储与RustFS5 小时前
HelixDB 上手:Agent 记忆新方案,基于 RustFS 对象存储,附完整 docker-compose 部署示例
后端·rust·开源
Amos_Web5 小时前
Rspack 源码解析(二十):Typed Hook 系统如何靠宏生成
前端·rust·前端框架
Source.Liu6 小时前
【A11】拆分前端,实现多页面方案
前端·rust
Kapaseker7 小时前
别只会 unwrap():Rust Result 的几种实用写法
rust
DongQiShanRen18 小时前
玄龙(上):TICK 主循环——意识心跳怎么跳
linux·jvm·数据库·人工智能·数据挖掘·rust
编程序的员19 小时前
使用OpenTelemetry来监控Rust应用
运维·rust·monitoring·opentelemetry
对象存储与RustFS1 天前
JuiceFS + 对象存储:把 S3 变成 POSIX 文件系统实测
后端·rust·开源
遇码1 天前
侧边栏一开,AI 画的东西就被挡住了:给白板画布加「真实可见区」计算和相机补偿
人工智能·ai·rust
geovindu1 天前
rust: Borg Pattern(续)
开发语言·后端·设计模式·rust·博格模式
轻舟技术A2 天前
Pi 的 Rust 实现来了:rpi,不止一个终端 Agent
开发语言·后端·rust