Functional Weave
Code in Rust

legal.limitation-date@1.0.1

impl/rust.rs

3,218 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
use super::dates_add_days::parse_iso_date;  ← from dates.add-days ^1.0.0 · built alongside by fune
use super::dates_add_months::add_months;  ← from dates.add-months ^1.0.0 · built alongside by fune
use super::legal_limitation_date_data::{LIMITATION_PERIODS, LIMITATION_PERIODS_HISTORY};  ← this capability’s own data, compiled from data/limitation-periods.json into the same file by fune build

/// The last day to bring a claim: the anniversary of the accrual date (or the
/// later date of knowledge) the period's number of years on, the accrual day
/// itself excluded, and the month's last day where no anniversary exists.
///
/// # Panics
/// Panics on an unknown claim type, a bad date, an accrual date before the
/// data, or a knowledge date for a claim type that does not run from knowledge.
pub fn limitation_date(claim_type: &str, accrual_date: &str, knowledge_date: Option<&str>) -> LimitationPeriod {
    parse_iso_date(accrual_date);
    let rows: Vec<_> = LIMITATION_PERIODS.iter().filter(|r| r.claim_type == claim_type).collect();
    if rows.is_empty() {
        let mut known: Vec<&str> = Vec::new();
        for r in LIMITATION_PERIODS {
            if !known.contains(&r.claim_type) {
                known.push(r.claim_type);
            }
        }
        panic!("unknown claim type \"{}\": expected one of {}", claim_type, known.join(", "));
    }
    let rule = match rows
        .iter()
        .find(|r| accrual_date >= r.valid_from && r.valid_to.map_or(true, |to| accrual_date <= to))
    {
        Some(r) => *r,
        None => {
            let earliest = rows.iter().map(|r| r.valid_from).min().unwrap();
            if LIMITATION_PERIODS_HISTORY != "full" && accrual_date < earliest {
                panic!(
                    "no limitation rule for {} accruing on {}: this build was installed with history={}, so it only carries rules from {}. Reinstall with history=full for older claims.",
                    claim_type, accrual_date, LIMITATION_PERIODS_HISTORY, earliest
                );
            }
            panic!("no limitation rule for {} accruing on {}", claim_type, accrual_date);
        }
    };
    let mut runs_from = accrual_date;
    if let Some(knowledge) = knowledge_date {
        if !rule.from_knowledge {
            panic!("a {} claim runs from accrual under {}; knowledgeDate must be null", claim_type, rule.section);
        }
        parse_iso_date(knowledge);
        if knowledge > accrual_date {
            runs_from = knowledge;
        }
    }
    // The corresponding date rule: the anniversary, clamped to the month end.
    let expiry = add_months(runs_from, rule.years * 12);
    LimitationPeriod {
        claim_type: claim_type.to_string(),
        years: rule.years,
        section: rule.section.to_string(),
        runs_from: runs_from.to_string(),
        expiry,
    }
}

pub fn limitation_period_to_value(p: &LimitationPeriod) -> Value {
    Value::obj(vec![
        ("claimType", Value::str(&p.claim_type)),
        ("years", Value::Int(p.years)),
        ("section", Value::str(&p.section)),
        ("runsFrom", Value::str(&p.runs_from)),
        ("expiry", Value::str(&p.expiry)),
    ])
}

pub fn fune_vector(args: &[Value]) -> Value {
    let knowledge = if args[2].is_null() { None } else { Some(args[2].as_str()) };
    limitation_period_to_value(&limitation_date(args[0].as_str(), args[1].as_str(), knowledge))
}