Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
use super::funejson::Value; ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::dates_age::age; ← from dates.age ^1.0.0 · built alongside by fune
/// The policyholder's age on the inception date and the band it falls in.
///
/// Age is completed years by dates.age, so a 29 February birthday ages on
/// 1 March in other years. The bands are checked before use: youngest first,
/// inclusive at both ends, no overlaps, and only the last may be open-ended.
/// An age no band covers is an error, not the nearest band.
///
/// # Panics
/// Panics on malformed bands, dates dates.age refuses, or an age no band covers.
pub fn age_band(birth_date: &str, inception_date: &str, bands: &[AgeBand]) -> AgeBanding {
if bands.is_empty() {
panic!("bands must not be empty");
}
let mut previous_max: i64 = -1;
for (i, band) in bands.iter().enumerate() {
if band.min_age < 0 {
panic!("minAge must be a whole number of 0 or more, received {}", band.min_age);
}
if band.max_age.is_none() && i != bands.len() - 1 {
panic!("only the last band may have no maxAge: \"{}\" is not last", band.label);
}
if let Some(max) = band.max_age {
if max < band.min_age {
panic!("maxAge must be a whole number no less than minAge in band \"{}\"", band.label);
}
}
if band.min_age <= previous_max {
panic!(
"bands must be youngest first and not overlap: \"{}\" starts at {}",
band.label, band.min_age
);
}
previous_max = band.max_age.unwrap_or(i64::MAX);
}
let years = age(birth_date, inception_date);
for band in bands {
if years >= band.min_age && band.max_age.map_or(true, |max| years <= max) {
return AgeBanding {
age: years,
label: band.label.clone(),
};
}
}
panic!("no band for age {}", years)
}
pub fn fune_vector(args: &[Value]) -> Value {
let bands: Vec<AgeBand> = args[2]
.as_arr()
.iter()
.map(|b| {
if let Value::Float(f) = b.get("minAge") {
panic!("minAge must be a whole number of 0 or more, received {}", f);
}
if let Value::Float(_) = b.get("maxAge") {
panic!("maxAge must be a whole number no less than minAge in band \"{}\"", b.get("label").as_str());
}
AgeBand {
label: b.get("label").as_str().to_string(),
min_age: b.get("minAge").as_i64(),
max_age: if b.get("maxAge").is_null() { None } else { Some(b.get("maxAge").as_i64()) },
}
})
.collect();
let result = age_band(args[0].as_str(), args[1].as_str(), &bands);
Value::obj(vec![("age", Value::Int(result.age)), ("label", Value::str(&result.label))])
}