flowstdlib 1.0.0

The standard library of functions and flows for 'flow' programs
Documentation
use flowcore::errors::Result;
use flowcore::flow_output;
use flowcore::RunAgain;
use flowmacro::flow_function;
use serde_json::{json, Value};

#[flow_function]
fn inner_bin_count(value: &Value, partial: &Value) -> Result<(Option<Value>, RunAgain)> {
    let mut bins = partial
        .as_array()
        .ok_or("Could not get bins as array")?
        .clone();

    if value.is_null() {
        return flow_output!("bins" => Value::Array(bins));
    }

    let idx = usize::try_from(value.as_u64().ok_or("Could not get value as u64")?)
        .map_err(|_| "Value too large")?;

    if let Some(bin) = bins.get_mut(idx) {
        let count = bin.as_u64().unwrap_or(0) + 1;
        *bin = json!(count);
    }

    flow_output!("partial" => Value::Array(bins))
}

#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::expect_used)]
mod test {
    use serde_json::json;

    use super::inner_bin_count;

    #[test]
    fn count_single_value() {
        let (result, _) = inner_bin_count(&json!(2), &json!([0, 0, 0, 0])).expect("failed");
        assert_eq!(
            *result
                .expect("no output")
                .pointer("/partial")
                .expect("no partial"),
            json!([0, 0, 1, 0])
        );
    }

    #[test]
    fn count_multiple() {
        let (result, _) = inner_bin_count(&json!(2), &json!([0, 0, 1, 0])).expect("failed");
        assert_eq!(
            *result
                .expect("no output")
                .pointer("/partial")
                .expect("no partial"),
            json!([0, 0, 2, 0])
        );
    }

    #[test]
    fn null_flushes_bins() {
        let (result, _) = inner_bin_count(&json!(null), &json!([3, 1, 2, 0])).expect("failed");
        assert_eq!(
            *result
                .expect("no output")
                .pointer("/bins")
                .expect("no bins"),
            json!([3, 1, 2, 0])
        );
    }
}