use flowcore::errors::{bail, Result};
use flowcore::flow_output;
use flowcore::RunAgain;
use flowmacro::flow_function;
use serde_json::{json, Value};
#[flow_function]
fn inner_range_split(inputs: &[Value]) -> Result<(Option<Value>, RunAgain)> {
let min_and_max = inputs
.first()
.ok_or("Could not get min_and_max")?
.as_array()
.ok_or("Could not get min and max array")?;
if min_and_max.len() != 2 {
bail!("Range (array/number) should have two values");
}
let min = min_and_max
.first()
.ok_or("Could not get min")?
.as_i64()
.ok_or("Could not get min")?;
let max = min_and_max
.get(1)
.ok_or("Could not get max")?
.as_i64()
.ok_or("Could not get max")?;
if min == max {
flow_output!("number" => json!(min))
} else {
let bottom: Vec<i64> = vec![min, ((max - min) / 2) + min];
let above_middle = ((max - min) / 2) + min + 1;
if above_middle == max {
flow_output!(
"bottom" => json!(bottom),
"number" => json!(max),
)
} else {
let top: Vec<i64> = vec![above_middle, max];
flow_output!(
"bottom" => json!(bottom),
"top" => json!(top),
)
}
}
}
#[cfg(test)]
#[allow(clippy::unwrap_used, clippy::expect_used)]
mod test {
use serde_json::{json, Value};
use super::inner_range_split;
#[test]
fn test_first_split() {
let range = vec![1, 10];
let (output, again) = inner_range_split(&[json!(range)]).expect("_range_split() failed");
let result = output.expect("Could not get value from output");
assert!(again);
assert_eq!(
result
.pointer("/bottom")
.expect("Could not get the /bottom from the output"),
&json!([1, 5])
);
assert_eq!(
result
.pointer("/top")
.expect("Could not get the /top from the output"),
&json!([6, 10])
);
}
#[test]
fn test_entire_range() {
let min = 1;
let max = 10;
let test_range: Vec<i32> = vec![min, max];
let test_range_json = json!(test_range);
let mut requires_further_splitting: Vec<Value> = vec![test_range_json];
let mut acquired_set: Vec<Value> = vec![];
while let Some(next) = requires_further_splitting.pop() {
println!("Splitting: {next:?}");
let (output, again) = inner_range_split(&[next]).expect("_range_split() failed");
assert!(again);
let result = output.expect("Could not get value from output");
if let Some(bottom) = result.pointer("/bottom") {
requires_further_splitting.push(bottom.clone());
}
if let Some(top) = result.pointer("/top") {
requires_further_splitting.push(top.clone());
}
if let Some(sequence) = result.pointer("/number") {
acquired_set.push(sequence.clone());
}
}
assert_eq!(acquired_set.len(), 10);
assert!(acquired_set.contains(&json!(1)));
assert!(acquired_set.contains(&json!(2)));
assert!(acquired_set.contains(&json!(3)));
assert!(acquired_set.contains(&json!(4)));
assert!(acquired_set.contains(&json!(5)));
assert!(acquired_set.contains(&json!(6)));
assert!(acquired_set.contains(&json!(7)));
assert!(acquired_set.contains(&json!(8)));
assert!(acquired_set.contains(&json!(9)));
assert!(acquired_set.contains(&json!(10)));
}
}