Functional Weave
Code in TypeScript

logistics.incoterm-responsibility@1.0.1

impl/rust.rs

3,104 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::logistics_incoterm_responsibility_data::INCOTERMS;  ← this capability’s own data, compiled from data/incoterms.json into the same file by fune build

/// Where the seller delivers (and risk passes) under an Incoterms rule, and
/// which party pays for each stage, from the ICC rules for the edition named.
///
/// # Panics
/// Panics on an edition with no data or a rule that edition does not have.
pub fn incoterm_responsibility(rule: &str, edition: i64) -> IncotermResponsibility {
    let mut editions: Vec<i64> = Vec::new();
    for r in INCOTERMS {
        if !editions.contains(&r.edition) {
            editions.push(r.edition);
        }
    }
    if !editions.contains(&edition) {
        let list: Vec<String> = editions.iter().map(|e| e.to_string()).collect();
        panic!("no data for Incoterms {}: this version covers {}", edition, list.join(", "));
    }
    let row = match INCOTERMS.iter().find(|r| r.edition == edition && r.rule == rule) {
        Some(r) => r,
        None => {
            let rules: Vec<&str> = INCOTERMS.iter().filter(|r| r.edition == edition).map(|r| r.rule).collect();
            panic!("unknown Incoterms {} rule \"{}\": expected one of {}", edition, rule, rules.join(", "));
        }
    };
    IncotermResponsibility {
        rule: row.rule.to_string(),
        edition: row.edition,
        name: row.name.to_string(),
        any_mode: row.any_mode,
        delivery: row.delivery.to_string(),
        risk_passes_at_destination: row.risk_passes_at_destination,
        loading_at_origin: row.loading_at_origin.to_string(),
        export_clearance: row.export_clearance.to_string(),
        main_carriage: row.main_carriage.to_string(),
        insurance_by: row.insurance_by.map(|s| s.to_string()),
        insurance_cover: row.insurance_cover.map(|s| s.to_string()),
        unloading_at_destination: row.unloading_at_destination.to_string(),
        import_clearance: row.import_clearance.to_string(),
        import_duties: row.import_duties.to_string(),
    }
}

pub fn incoterm_responsibility_to_value(r: &IncotermResponsibility) -> Value {
    let opt = |v: &Option<String>| match v {
        Some(s) => Value::str(s),
        None => Value::Null,
    };
    Value::obj(vec![
        ("rule", Value::str(&r.rule)),
        ("edition", Value::Int(r.edition)),
        ("name", Value::str(&r.name)),
        ("anyMode", Value::Bool(r.any_mode)),
        ("delivery", Value::str(&r.delivery)),
        ("riskPassesAtDestination", Value::Bool(r.risk_passes_at_destination)),
        ("loadingAtOrigin", Value::str(&r.loading_at_origin)),
        ("exportClearance", Value::str(&r.export_clearance)),
        ("mainCarriage", Value::str(&r.main_carriage)),
        ("insuranceBy", opt(&r.insurance_by)),
        ("insuranceCover", opt(&r.insurance_cover)),
        ("unloadingAtDestination", Value::str(&r.unloading_at_destination)),
        ("importClearance", Value::str(&r.import_clearance)),
        ("importDuties", Value::str(&r.import_duties)),
    ])
}

pub fn fune_vector(args: &[Value]) -> Value {
    incoterm_responsibility_to_value(&incoterm_responsibility(args[0].as_str(), args[1].as_i64()))
}