1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::{
err::Error,
file::{from_json, Build, Load},
ord::Link,
};
use serde::{Deserialize, Serialize};
use std::{
collections::{
btree_map::{IntoIter, Values},
BTreeMap,
},
path::Path,
};
#[derive(Debug, Deserialize, Serialize)]
pub struct Set<T>(BTreeMap<String, T>);
impl<T> Set<T> {
#[inline]
#[must_use]
pub fn new(map: BTreeMap<String, T>) -> Self {
debug_assert!(!map.is_empty());
Self(map)
}
#[inline]
pub fn from_vec(list: Vec<(String, T)>) -> Result<Self, Error> {
let mut map = BTreeMap::new();
for (key, item) in list {
if map.contains_key(&key) {
return Err(Error::Text(format!("Duplicate entries for group: {}", key)));
}
map.insert(key, item);
}
Ok(Self::new(map))
}
#[inline]
#[must_use]
pub fn values(&self) -> Values<String, T> {
self.0.values()
}
#[inline]
#[must_use]
pub fn get(&self, name: &str) -> Option<&T> {
self.0.get(name)
}
}
impl<T> IntoIterator for Set<T> {
type Item = (String, T);
type IntoIter = IntoIter<String, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<T> Load for Set<T>
where
for<'de> T: Deserialize<'de>,
{
#[inline]
fn load_data(path: &Path) -> Result<Self, Error> {
from_json(path)
}
}
#[allow(clippy::use_self)]
impl<T: Build> Build for Set<T> {
type Inst = Set<T::Inst>;
#[inline]
fn build(self, in_dir: &Path) -> Result<Self::Inst, Error> {
let mut map = BTreeMap::new();
for (key, item) in self.0 {
map.insert(key, item.build(in_dir)?);
}
Ok(Self::Inst::new(map))
}
}
#[allow(clippy::use_self)]
impl<'a, T, S: Link<'a, T>> Link<'a, T> for Set<S> {
type Inst = Set<S::Inst>;
#[inline]
fn requires(&self) -> Vec<String> {
self.0
.values()
.map(|v| v.requires())
.collect::<Vec<_>>()
.into_iter()
.flatten()
.collect()
}
#[inline]
fn link(self, set: &'a Set<T>) -> Result<Self::Inst, Error> {
let mut list = Vec::with_capacity(self.0.len());
for (name, val) in self.0 {
list.push((name, val.link(set)?));
}
Self::Inst::from_vec(list)
}
}