nodo_runtime 0.18.5

Runtime for NODO applications
Documentation
// Copyright 2025 David Weikersdorfer

use nodo::{core::AppMonotonicClock, prelude::*};

#[derive(Config, Default)]
struct MyConfig {
    #[mutable]
    pub threshold: f64,

    #[mutable]
    pub count: i64,

    #[mutable]
    pub text: String,

    pub immutable: i64,

    #[hidden]
    pub hidden: i64,

    pub foo: Foo,
}

#[derive(Default, Debug, PartialEq)]
struct Foo;

#[test]
fn test_config() {
    // Check that we only have the enums we expect
    // If there are any other variants this will not compile
    match MyConfigParameterKind::Threshold {
        MyConfigParameterKind::Threshold
        | MyConfigParameterKind::Count
        | MyConfigParameterKind::Text
        | MyConfigParameterKind::Immutable => {}
    }

    assert_eq!(
        MyConfig::list_parameters(),
        vec![
            (
                MyConfigParameterKind::Threshold,
                ParameterProperties {
                    dtype: ParameterDataType::Float64,
                    is_mutable: true
                }
            ),
            (
                MyConfigParameterKind::Count,
                ParameterProperties {
                    dtype: ParameterDataType::Int64,
                    is_mutable: true
                }
            ),
            (
                MyConfigParameterKind::Text,
                ParameterProperties {
                    dtype: ParameterDataType::String,
                    is_mutable: true
                }
            ),
            (
                MyConfigParameterKind::Immutable,
                ParameterProperties {
                    dtype: ParameterDataType::Int64,
                    is_mutable: false
                }
            ),
        ]
    );

    let mut config = MyConfig::default();

    assert_eq!(config.threshold, 0.0);
    assert_eq!(
        config.set_parameter(
            MyConfigParameterKind::Threshold,
            ParameterValue::Float64(0.5)
        ),
        Ok(())
    );
    assert_eq!(config.threshold, 0.5);

    assert_eq!(config.count, 0);
    assert_eq!(
        config.set_parameter(MyConfigParameterKind::Count, ParameterValue::Int64(42)),
        Ok(())
    );
    assert_eq!(config.count, 42);

    assert_eq!(config.text, "");
    assert_eq!(
        config.set_parameter(
            MyConfigParameterKind::Text,
            ParameterValue::String("hello".into())
        ),
        Ok(())
    );
    assert_eq!(config.text, "hello");

    assert_eq!(config.immutable, 0);
    assert_eq!(
        config.set_parameter(MyConfigParameterKind::Immutable, ParameterValue::Int64(42)),
        Err(ConfigSetParameterError::Immutable)
    );
    assert_eq!(config.immutable, 0);

    assert_eq!(config.hidden, 0);

    assert_eq!(
        config.set_parameter(MyConfigParameterKind::Threshold, ParameterValue::Int64(42)),
        Err(ConfigSetParameterError::InvalidType {
            expected: ParameterDataType::Float64,
            actual: ParameterDataType::Int64,
        })
    );

    assert_eq!(config.foo, Foo);
}

#[test]
fn test_config_aux() {
    let clock = AppMonotonicClock::new();

    let mut aux = MyConfigAux::default();
    assert_eq!(aux.is_dirty(), false);
    assert_eq!(aux.dirty(), &[] as &[MyConfigParameterKind]);

    aux.on_set_parameter(MyConfigParameterKind::Threshold, clock.now());
    assert_eq!(aux.is_dirty(), true);
    assert_eq!(aux.dirty(), &[MyConfigParameterKind::Threshold]);

    aux.on_post_step();
    assert_eq!(aux.is_dirty(), false);
    assert_eq!(aux.dirty(), &[] as &[MyConfigParameterKind]);

    aux.on_set_parameter(MyConfigParameterKind::Threshold, clock.now());
    aux.on_set_parameter(MyConfigParameterKind::Text, clock.now());
    assert_eq!(aux.is_dirty(), true);
    assert_eq!(
        aux.dirty(),
        &[
            MyConfigParameterKind::Threshold,
            MyConfigParameterKind::Text
        ]
    );
}