blob: 4a8a3cc1d1d767c0dc04426d83197eb6c792671e [file] [log] [blame]
Brian Silvermancc09f182022-03-09 15:40:20 -08001use serde::{Deserialize, Serialize};
2use std::collections::{btree_set, BTreeMap, BTreeSet};
3use std::iter::once;
4
5pub trait SelectMap<T, U> {
6 // A selectable should also implement a `map` function allowing one type of selectable
7 // to be mutated into another. However, the approach I'm looking for requires GAT
8 // (Generic Associated Types) which are not yet stable.
9 // https://github.com/rust-lang/rust/issues/44265
10 type Mapped;
11 fn map<F: Copy + Fn(T) -> U>(self, func: F) -> Self::Mapped;
12}
13
14pub trait Select<T> {
15 /// Gather a list of all conditions currently set on the selectable. A conditional
16 /// would be the key of the select statement.
17 fn configurations(&self) -> BTreeSet<Option<&String>>;
18}
19
20#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, Clone)]
21pub struct SelectList<T: Ord> {
22 common: BTreeSet<T>,
23 selects: BTreeMap<String, BTreeSet<T>>,
24}
25
26impl<T: Ord> Default for SelectList<T> {
27 fn default() -> Self {
28 Self {
29 common: BTreeSet::new(),
30 selects: BTreeMap::new(),
31 }
32 }
33}
34
35impl<T: Ord> SelectList<T> {
36 // TODO: This should probably be added to the [Select] trait
37 pub fn insert(&mut self, value: T, configuration: Option<String>) {
38 match configuration {
39 None => {
40 self.common.insert(value);
41 }
42 Some(cfg) => {
43 match self.selects.get_mut(&cfg) {
44 None => {
45 let mut set = BTreeSet::new();
46 set.insert(value);
47 self.selects.insert(cfg, set);
48 }
49 Some(set) => {
50 set.insert(value);
51 }
52 };
53 }
54 };
55 }
56
57 // TODO: This should probably be added to the [Select] trait
58 pub fn get_iter<'a>(&'a self, config: Option<&String>) -> Option<btree_set::Iter<T>> {
59 match config {
60 Some(conf) => self.selects.get(conf).map(|set| set.iter()),
61 None => Some(self.common.iter()),
62 }
63 }
64
65 /// Determine whether or not the select should be serialized
66 pub fn should_skip_serializing(&self) -> bool {
67 self.common.is_empty() && self.selects.is_empty()
68 }
69}
70
71impl<T: Ord> Select<T> for SelectList<T> {
72 fn configurations(&self) -> BTreeSet<Option<&String>> {
73 let configs = self.selects.keys().map(Some);
74 match self.common.is_empty() {
75 true => configs.collect(),
76 false => configs.chain(once(None)).collect(),
77 }
78 }
79}
80
81impl<T: Ord, U: Ord> SelectMap<T, U> for SelectList<T> {
82 type Mapped = SelectList<U>;
83
84 fn map<F: Copy + Fn(T) -> U>(self, func: F) -> Self::Mapped {
85 SelectList {
86 common: self.common.into_iter().map(func).collect(),
87 selects: self
88 .selects
89 .into_iter()
90 .map(|(key, map)| (key, map.into_iter().map(func).collect()))
91 .collect(),
92 }
93 }
94}
95
96#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, Clone)]
97pub struct SelectDict<T: Ord> {
98 common: BTreeMap<String, T>,
99 selects: BTreeMap<String, BTreeMap<String, T>>,
100}
101
102impl<T: Ord> Default for SelectDict<T> {
103 fn default() -> Self {
104 Self {
105 common: BTreeMap::new(),
106 selects: BTreeMap::new(),
107 }
108 }
109}
110
111impl<T: Ord> SelectDict<T> {
112 // TODO: This should probably be added to the [Select] trait
113 pub fn insert(&mut self, value: BTreeMap<String, T>, configuration: Option<String>) {
114 match configuration {
115 None => {
116 self.common.extend(value);
117 }
118 Some(cfg) => {
119 match self.selects.get_mut(&cfg) {
120 None => {
121 let mut set = BTreeMap::new();
122 set.extend(value);
123 self.selects.insert(cfg, set);
124 }
125 Some(set) => {
126 set.extend(value);
127 }
128 };
129 }
130 };
131 }
132
133 /// Determine whether or not the select should be serialized
134 pub fn should_skip_serializing(&self) -> bool {
135 self.common.is_empty() && self.selects.is_empty()
136 }
137}
138
139impl<T: Ord> Select<T> for SelectDict<T> {
140 fn configurations(&self) -> BTreeSet<Option<&String>> {
141 let configs = self.selects.keys().map(Some);
142 match self.common.is_empty() {
143 true => configs.collect(),
144 false => configs.chain(once(None)).collect(),
145 }
146 }
147}
148
149impl<T: Ord, U: Ord> SelectMap<T, U> for SelectDict<T> {
150 type Mapped = SelectDict<U>;
151
152 fn map<F: Copy + Fn(T) -> U>(self, func: F) -> Self::Mapped {
153 SelectDict {
154 common: self
155 .common
156 .into_iter()
157 .map(|(key, val)| (key, func(val)))
158 .collect(),
159 selects: self
160 .selects
161 .into_iter()
162 .map(|(key, map)| (key, map.into_iter().map(|(k, v)| (k, func(v))).collect()))
163 .collect(),
164 }
165 }
166}