use wdl_ast::Diagnostic;
use super::CallContext;
use super::Callback;
use super::Function;
use super::Signature;
use crate::Value;
use crate::diagnostics::function_call_failed;
const FUNCTION_NAME: &str = "select_first";
fn select_first(context: CallContext<'_>) -> Result<Value, Diagnostic> {
debug_assert!(!context.arguments.is_empty() && context.arguments.len() < 3);
let array = context.arguments[0]
.value
.as_array()
.expect("argument should be an array");
let has_default = context.arguments.len() >= 2;
match array.as_slice().iter().find(|v| !v.is_none()) {
Some(v) => Ok(v.clone()),
None if has_default => Ok(context.arguments[1].value.clone()),
None if array.is_empty() => Err(function_call_failed(
FUNCTION_NAME,
"array is empty",
context.arguments[0].span,
)),
None => Err(function_call_failed(
FUNCTION_NAME,
"array contains only `None` values",
context.arguments[0].span,
)),
}
}
pub const fn descriptor() -> Function {
Function::new(
const {
&[Signature::new(
"(array: Array[X], <default: X>) -> X",
Callback::Sync(select_first),
)]
},
)
}
#[cfg(test)]
mod test {
use pretty_assertions::assert_eq;
use wdl_ast::version::V1;
use crate::v1::test::TestEnv;
use crate::v1::test::eval_v1_expr;
#[tokio::test]
async fn select_first() {
let env = TestEnv::default();
let diagnostic = eval_v1_expr(&env, V1::One, "select_first([])")
.await
.unwrap_err();
assert_eq!(
diagnostic.message(),
"call to function `select_first` failed: array is empty"
);
let value = eval_v1_expr(&env, V1::One, "select_first([], 1)")
.await
.unwrap();
assert_eq!(value.unwrap_integer(), 1);
let diagnostic = eval_v1_expr(&env, V1::One, "select_first([None, None, None])")
.await
.unwrap_err();
assert_eq!(
diagnostic.message(),
"call to function `select_first` failed: array contains only `None` values"
);
let value = eval_v1_expr(&env, V1::One, "select_first([None, None, None], 12345)")
.await
.unwrap();
assert_eq!(value.unwrap_integer(), 12345);
let value = eval_v1_expr(&env, V1::One, "select_first([1, None, 3])")
.await
.unwrap();
assert_eq!(value.unwrap_integer(), 1);
let value = eval_v1_expr(&env, V1::One, "select_first([None, 2, 3])")
.await
.unwrap();
assert_eq!(value.unwrap_integer(), 2);
let value = eval_v1_expr(&env, V1::One, "select_first([None, None, 3])")
.await
.unwrap();
assert_eq!(value.unwrap_integer(), 3);
let value = eval_v1_expr(&env, V1::One, "select_first([None, 2, None], 12345)")
.await
.unwrap();
assert_eq!(value.unwrap_integer(), 2);
let value = eval_v1_expr(&env, V1::One, "select_first([1, 2, 3])")
.await
.unwrap();
assert_eq!(value.unwrap_integer(), 1);
}
}