Functional Weave
Code in Python

monitor.maintenance-window@1.0.0

impl/rust.rs

2,246 bytes · the Rust implementation · view raw

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

/// The window with start <= at < end. Half-open, so a window ending at 02:00
/// and the next starting at 02:00 never both apply. When several overlap, the
/// one that started first wins (ties: the first in the list), so the answer
/// does not depend on how the caller sorted them. Every window is checked,
/// not only the active ones: a backwards window is a config error that would
/// otherwise silently never apply.
///
/// # Panics
/// Panics on a window that does not end after it starts.
pub fn active_maintenance(windows: &[MaintenanceWindow], at: i64) -> Option<MaintenanceWindow> {
    let mut best: Option<&MaintenanceWindow> = None;
    for w in windows {
        if w.end <= w.start {
            panic!(
                "maintenance window \"{}\" must end after it starts: start {}, end {}",
                w.name, w.start, w.end
            );
        }
        if w.start <= at && at < w.end && best.map_or(true, |b| w.start < b.start) {
            best = Some(w);
        }
    }
    best.map(|b| MaintenanceWindow { name: b.name.clone(), start: b.start, end: b.end })
}

/// A `MaintenanceWindow` from its JSON form, for adapters of capabilities built on this one.
pub fn maintenance_window_from_value(v: &Value) -> MaintenanceWindow {
    MaintenanceWindow {
        name: v.get("name").as_str().to_string(),
        start: v.get("start").as_i64(),
        end: v.get("end").as_i64(),
    }
}

pub fn maintenance_windows_from_value(v: &Value) -> Vec<MaintenanceWindow> {
    v.as_arr().iter().map(maintenance_window_from_value).collect()
}

pub fn maintenance_window_to_value(w: &MaintenanceWindow) -> Value {
    Value::obj(vec![
        ("name", Value::str(&w.name)),
        ("start", Value::Int(w.start)),
        ("end", Value::Int(w.end)),
    ])
}

pub fn fune_vector(args: &[Value]) -> Value {
    let windows = maintenance_windows_from_value(&args[0]);
    let at = match &args[1] {
        Value::Int(i) => *i,
        Value::Float(f) => panic!("at must be a whole second, received {}", f),
        _ => panic!("at must be a whole second"),
    };
    match active_maintenance(&windows, at) {
        Some(w) => maintenance_window_to_value(&w),
        None => Value::Null,
    }
}