param_opt/parameter/
table.rs1use 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}