dfir_rs 0.16.0

DFIR runtime for Rust, used by Hydro.
Documentation
use dfir_rs::dfir_syntax;
use dfir_rs::util::collect_ready;
use dfir_rs::util::demux_enum::DemuxEnum;
use multiplatform_test::multiplatform_test;

#[multiplatform_test]
pub fn test_demux_enum_basic() {
    #[derive(DemuxEnum)]
    enum Shape {
        Square(f64),
        Rectangle { w: f64, h: f64 },
        Circle { r: f64 },
    }

    let mut df = dfir_syntax! {
        my_demux = source_iter([
            Shape::Square(9.0),
            Shape::Rectangle { w: 10.0, h: 8.0 },
            Shape::Circle { r: 5.0 },
        ]) -> demux_enum::<Shape>();

        my_demux[Square] -> for_each(drop);
        my_demux[Circle] -> for_each(drop);
        my_demux[Rectangle] -> for_each(drop);
    };
    df.run_available_sync();
}

#[multiplatform_test]
pub fn test_demux_enum() {
    let (out_send, out_recv) = dfir_rs::util::unbounded_channel();

    #[derive(DemuxEnum)]
    enum Shape {
        Square(f64),
        Rectangle { w: f64, h: f64 },
        Circle { r: f64 },
    }

    let mut df = dfir_syntax! {
        my_demux = source_iter([
            Shape::Square(9.0),
            Shape::Rectangle { w: 10.0, h: 8.0 },
            Shape::Circle { r: 5.0 },
        ]) -> demux_enum::<Shape>();

        my_demux[Square] -> map(|(s,)| s * s) -> out;
        my_demux[Circle] -> map(|(r,)| std::f64::consts::PI * r * r) -> out;
        my_demux[Rectangle] -> map(|(w, h)| w * h) -> out;

        out = union()
            -> map(|area| format!("{:.2}", area))
            -> for_each(|area_str| out_send.send(area_str).unwrap());
    };
    df.run_available_sync();

    let areas = collect_ready::<Vec<_>, _>(out_recv);
    assert_eq!(&["81.00", "78.54", "80.00"], &*areas);
}

#[multiplatform_test]
pub fn test_demux_enum_generic() {
    #[derive(DemuxEnum)]
    enum Shape<N> {
        Square(N),
        Rectangle { w: N, h: N },
        Circle { r: N },
    }

    fn test<N>(s: N, w: N, h: N, r: N, expected: &[&str])
    where
        N: 'static + Into<f64>,
    {
        let (out_send, out_recv) = dfir_rs::util::unbounded_channel();

        let mut df = dfir_syntax! {
            my_demux = source_iter([
                Shape::Square(s),
                Shape::Rectangle { w, h },
                Shape::Circle { r },
            ]) -> demux_enum::<Shape<N>>();

            my_demux[Square] -> map(|(s,)| s.into()) -> map(|s| s * s) -> out;
            my_demux[Circle] -> map(|(r,)| r.into()) -> map(|r| std::f64::consts::PI * r * r) -> out;
            my_demux[Rectangle] -> map(|(w, h)| w.into() * h.into()) -> out;

            out = union()
                -> map(|area| format!("{:.2}", area))
                -> for_each(|area_str| out_send.send(area_str).unwrap());
        };
        df.run_available_sync();

        let areas = collect_ready::<Vec<_>, _>(out_recv);
        assert_eq!(expected, &*areas);
    }
    test::<f32>(9., 10., 8., 5., &["81.00", "78.54", "80.00"]);
    test::<u32>(9, 10, 8, 5, &["81.00", "78.54", "80.00"]);
}

#[multiplatform_test]
fn test_zero_variants() {
    #[derive(DemuxEnum)]
    enum Never {}

    let mut df = dfir_syntax! {
        source_iter(std::iter::empty::<Never>()) -> demux_enum::<Never>();
    };
    df.run_available_sync();
}

#[multiplatform_test]
fn test_one_variant() {
    #[derive(DemuxEnum)]
    enum Request<T> {
        OnlyMessage(T),
    }

    let (out_send, out_recv) = dfir_rs::util::unbounded_channel();

    let mut df = dfir_syntax! {
        input = source_iter([Request::OnlyMessage("hi")]) -> demux_enum::<Request<&'static str>>();
        input[OnlyMessage] -> for_each(|(msg,)| out_send.send(msg).unwrap());
    };
    df.run_available_sync();

    assert_eq!(&["hi"], &*collect_ready::<Vec<_>, _>(out_recv));
}