Skip to main content

wxy_domain/
collection.rs

1//! Collections: fields and domains together, with attributes.
2
3use std::collections::BTreeMap;
4
5use crate::domain::Domain;
6use crate::field::Field;
7
8/// How two domains in a collection relate.
9#[derive(Debug, Clone, PartialEq)]
10pub enum RelationKind {
11    /// `to` is an overview of `from`, coarser by `factor` along each
12    /// mapped dim (not necessarily an integer, as in GDAL).
13    Overview {
14        factor: Vec<f64>,
15    },
16    /// `to` holds another stagger location of the same grid (SGRID, the
17    /// Arakawa C-grid's u and v points).
18    Stagger,
19    Other(String),
20}
21
22/// A relation from one domain to another, by index.
23#[derive(Debug, Clone, PartialEq)]
24pub struct Relation {
25    pub kind: RelationKind,
26    pub from: usize,
27    pub to: usize,
28}
29
30/// A set of fields and domains with attributes: a classic dataset, a
31/// multidimensional group, a mesh with its datasets, a feature layer.
32#[derive(Debug, Clone, Default)]
33pub struct Collection {
34    pub name: String,
35    pub domains: Vec<Domain>,
36    pub fields: Vec<Field>,
37    pub attrs: BTreeMap<String, String>,
38    pub children: Vec<Collection>,
39    pub related: Vec<Relation>,
40}
41
42impl Collection {
43    pub fn new(name: impl Into<String>) -> Self {
44        Self {
45            name: name.into(),
46            ..Default::default()
47        }
48    }
49
50    pub fn add_domain(&mut self, domain: Domain) -> usize {
51        self.domains.push(domain);
52        self.domains.len() - 1
53    }
54
55    pub fn add_field(&mut self, field: Field) -> usize {
56        assert!(
57            field.domain < self.domains.len(),
58            "field names a missing domain"
59        );
60        self.fields.push(field);
61        self.fields.len() - 1
62    }
63
64    pub fn field(&self, name: &str) -> Option<&Field> {
65        self.fields.iter().find(|f| f.name == name)
66    }
67
68    pub fn domain_of(&self, field: &Field) -> &Domain {
69        &self.domains[field.domain]
70    }
71}