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
const UNITS: [(&str, i64); 4] = [("d", 86400), ("h", 3600), ("m", 60), ("s", 1)];
/// Seconds as "3h 12m". Starts at the largest non-zero unit and looks at
/// `max_units` consecutive units from there, leaving out the zero ones, so
/// 3605 s with two units is "1h", not "1h 0m" and not "1h 5s": the seconds
/// are beyond the precision asked for. Truncates, never rounds up, so a
/// duration is never shown longer than it was (86399 s is "23h", not "1d").
///
/// # Panics
/// Panics on negative seconds or max_units outside 1..=4.
pub fn format_duration(seconds: i64, max_units: i64) -> String {
if seconds < 0 {
panic!("seconds must not be negative, received {}", seconds);
}
if !(1..=4).contains(&max_units) {
panic!("maxUnits must be 1 to 4, received {}", max_units);
}
if seconds == 0 {
return "0s".to_string();
}
let mut first = 0usize;
while seconds / UNITS[first].1 == 0 {
first += 1;
}
let mut parts: Vec<String> = Vec::new();
let mut rest = seconds;
for (i, (label, size)) in UNITS.iter().enumerate() {
let n = rest / size;
rest -= n * size;
if i >= first && (i as i64) < first as i64 + max_units && n > 0 {
parts.push(format!("{}{}", n, label));
}
}
parts.join(" ")
}
pub fn fune_vector(args: &[Value]) -> Value {
let seconds = match &args[0] {
Value::Int(i) => *i,
Value::Float(f) => panic!("seconds must be a whole number, received {}", f),
_ => panic!("seconds must be a whole number"),
};
let max_units = match &args[1] {
Value::Int(i) => *i,
Value::Float(f) => panic!("maxUnits must be 1 to 4, received {}", f),
_ => panic!("maxUnits must be 1 to 4"),
};
Value::str(&format_duration(seconds, max_units))
}