tiger_lib/vic3/
validate.rs

1//! Validation functions that are useful for more than one data module in vic3.
2
3use crate::block::Block;
4use crate::context::ScopeContext;
5use crate::everything::Everything;
6use crate::item::Item;
7use crate::report::{ErrorKey, Severity, err, warn};
8use crate::scopes::Scopes;
9use crate::validator::Validator;
10
11pub fn validate_treaty_article(block: &Block, data: &Everything, sc: &mut ScopeContext) {
12    let mut vd = Validator::new(block, data);
13    vd.field_item("article", Item::TreatyArticle);
14    // TODO: directed articles _must_ specify this value, mutual articles _must not_ specify this value
15    vd.field_target_ok_this("source_country", sc, Scopes::Country);
16    // TODO: directed articles _must_ specify this value, mutual articles _must not_ specify this value
17    vd.field_target_ok_this("target_country", sc, Scopes::Country);
18    // TODO: check which inputs the article requires
19    vd.field_validated_block("inputs", |block, data| {
20        let mut vd = Validator::new(block, data);
21        for block in vd.blocks() {
22            let mut vd = Validator::new(block, data);
23            vd.field_script_value("quantity", sc);
24            vd.field_target("goods", sc, Scopes::Goods);
25            vd.field_target("state", sc, Scopes::State);
26            vd.field_target("strategic_region", sc, Scopes::StrategicRegion);
27            vd.field_target("company", sc, Scopes::Company);
28            vd.field_target("building_type", sc, Scopes::BuildingType);
29            vd.field_target("law_type", sc, Scopes::LawType);
30            vd.field_target("country", sc, Scopes::Country);
31            if block.num_items() > 1 {
32                let msg = "use only 1 input per block";
33                err(ErrorKey::Validation).msg(msg).loc(block).push();
34            }
35        }
36    });
37}
38
39pub fn validate_locators(vd: &mut Validator) -> Vec<&'static str> {
40    let mut locator_names = Vec::new();
41    vd.multi_field_validated_block("locator", |block, data| {
42        let mut vd = Validator::new(block, data);
43        vd.set_max_severity(Severity::Warning);
44        vd.req_field("name");
45        if let Some(name) = vd.field_value("name") {
46            if let Some(other) = locator_names.iter().find(|n| n == &name) {
47                let msg = format!("duplicate locator name `{name}`");
48                warn(ErrorKey::DuplicateField)
49                    .msg(msg)
50                    .loc(name)
51                    .loc_msg(other, "previous locator")
52                    .push();
53            } else {
54                locator_names.push(name.clone());
55            }
56        }
57        vd.field_list_precise_numeric_exactly("position", 3);
58        vd.field_list_precise_numeric_exactly("rotation", 3);
59        vd.field_numeric("scale");
60    });
61    locator_names.into_iter().map(|n| n.as_str()).collect()
62}