param_opt/parameter/
table.rs

1use std::{collections::HashMap, num::NonZeroUsize, sync::Arc};
2
3use thiserror::Error;
4
5use super::{
6    dataset::{ParameterDataset, ParameterValue},
7    ParameterSpace,
8};
9
10#[derive(Debug, Clone, PartialEq)]
11pub struct ParameterTable {
12    named: HashMap<String, ParameterDataset>,
13    vectored: Arc<[String]>,
14}
15impl ParameterTable {
16    pub fn new(
17        named: HashMap<String, ParameterDataset>,
18        vectored: Arc<[String]>,
19    ) -> Result<Self, ParameterTableError> {
20        if named.len() != vectored.len() {
21            return Err(ParameterTableError::InconsistentLength);
22        }
23        for key in vectored.as_ref() {
24            if named.get(key).is_none() {
25                return Err(ParameterTableError::KeyNotExists {
26                    key: key.to_owned(),
27                });
28            }
29        }
30        Ok(Self { named, vectored })
31    }
32
33    pub fn new_unordered(parameters: HashMap<String, ParameterDataset>) -> Self {
34        let vectored = parameters.keys().cloned().collect();
35        Self {
36            named: parameters,
37            vectored,
38        }
39    }
40
41    pub fn spaces(&self) -> impl Iterator<Item = NonZeroUsize> + '_ {
42        self.vectored
43            .iter()
44            .map(|name| &self.named[name])
45            .map(ParameterSpace::space_size)
46    }
47
48    pub fn values(
49        &self,
50        indices: impl Iterator<Item = usize>,
51    ) -> impl Iterator<Item = (&String, ParameterValue)> {
52        indices
53            .enumerate()
54            .map(|(i, index)| (&self.vectored[i], index))
55            .map(|(name, index)| (name, self.named[name].value(index)))
56    }
57}
58
59#[derive(Debug, Clone, PartialEq, Error)]
60pub enum ParameterTableError {
61    #[error("`named` and `vectored` should be of the same size")]
62    InconsistentLength,
63    #[error("`{key}` does not exist in `named`")]
64    KeyNotExists { key: String },
65}