datastar 0.4.0

Datastar SDK for Rust
Documentation
use {
    asynk_strim::{Yielder, stream_fn},
    core::{convert::Infallible, error::Error, time::Duration},
    datastar::{
        prelude::PatchElements,
        warp::{ReadSignals, read_signals},
    },
    serde::Deserialize,
    tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt},
    warp::{Filter, filters::sse::Event},
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    tracing_subscriber::registry()
        .with(
            tracing_subscriber::EnvFilter::try_from_default_env()
                .unwrap_or_else(|_| format!("{}=debug", env!("CARGO_CRATE_NAME")).into()),
        )
        .with(tracing_subscriber::fmt::layer())
        .init();

    let index = warp::path::end()
        .and(warp::get())
        .map(|| warp::reply::html(include_str!("hello-world.html")));

    let hello_world = warp::path("hello-world")
        .and(warp::get())
        .and(read_signals::<Signals>())
        .map(|ReadSignals(signals): ReadSignals<Signals>| {
            let stream = stream_fn(
                move |mut yielder: Yielder<Result<Event, Infallible>>| async move {
                    for i in 0..MESSAGE.len() {
                        let elements = format!("<div id='message'>{}</div>", &MESSAGE[0..i + 1]);
                        let patch = PatchElements::new(elements);
                        let sse_event = patch.write_as_warp_sse_event();

                        yielder.yield_item(Ok(sse_event)).await;
                        tokio::time::sleep(Duration::from_millis(signals.delay)).await;
                    }
                },
            );
            warp::sse::reply(warp::sse::keep_alive().stream(stream))
        });

    let routes = index.or(hello_world);

    tracing::debug!("listening on 127.0.0.1:3000");
    warp::serve(routes).run(([127, 0, 0, 1], 3000)).await;

    Ok(())
}

const MESSAGE: &str = "Hello, world!";

#[derive(Deserialize)]
pub struct Signals {
    pub delay: u64,
}