1 use std::collections::{BTreeMap, BTreeSet}; 2 use std::fmt::Debug; 3 4 use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize}; 5 6 /// A wrapper around values where some values may be conditionally included (e.g. only on a certain platform), and others are unconditional. 7 #[derive(Debug, Clone, PartialEq, Eq, Serialize)] 8 pub struct Select<T> 9 where 10 T: Selectable, 11 { 12 common: T::CommonType, 13 selects: BTreeMap<String, T::SelectsType>, 14 } 15 16 pub trait Selectable 17 where 18 Self: SelectableValue, 19 { 20 type ItemType: SelectableValue; 21 type CommonType: SelectableValue + Default; 22 type SelectsType: SelectableValue; 23 is_empty(this: &Select<Self>) -> bool24 fn is_empty(this: &Select<Self>) -> bool; insert(this: &mut Select<Self>, value: Self::ItemType, configuration: Option<String>)25 fn insert(this: &mut Select<Self>, value: Self::ItemType, configuration: Option<String>); 26 items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)>27 fn items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)>; values(this: &Select<Self>) -> Vec<Self::ItemType>28 fn values(this: &Select<Self>) -> Vec<Self::ItemType>; 29 merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self>30 fn merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self>; 31 } 32 33 // Replace with `trait_alias` once stabilized. 34 // https://github.com/rust-lang/rust/issues/41517 35 pub trait SelectableValue 36 where 37 Self: Debug + Clone + PartialEq + Eq + Serialize + DeserializeOwned, 38 { 39 } 40 41 impl<T> SelectableValue for T where T: Debug + Clone + PartialEq + Eq + Serialize + DeserializeOwned {} 42 43 // Replace with `trait_alias` once stabilized. 44 // https://github.com/rust-lang/rust/issues/41517 45 pub trait SelectableOrderedValue 46 where 47 Self: SelectableValue + PartialOrd + Ord, 48 { 49 } 50 51 impl<T> SelectableOrderedValue for T where T: SelectableValue + PartialOrd + Ord {} 52 53 pub(crate) trait SelectableScalar 54 where 55 Self: SelectableValue, 56 { 57 } 58 59 impl SelectableScalar for String {} 60 impl SelectableScalar for bool {} 61 impl SelectableScalar for i64 {} 62 63 // General 64 impl<T> Select<T> 65 where 66 T: Selectable, 67 { new() -> Self68 pub(crate) fn new() -> Self { 69 Self { 70 common: T::CommonType::default(), 71 selects: BTreeMap::new(), 72 } 73 } 74 from_value(value: T::CommonType) -> Self75 pub(crate) fn from_value(value: T::CommonType) -> Self { 76 Self { 77 common: value, 78 selects: BTreeMap::new(), 79 } 80 } 81 82 /// Whether there zero values in this collection, common or configuration-specific. is_empty(&self) -> bool83 pub fn is_empty(&self) -> bool { 84 T::is_empty(self) 85 } 86 87 /// A list of the configurations which have some configuration-specific value associated. configurations(&self) -> BTreeSet<String>88 pub fn configurations(&self) -> BTreeSet<String> { 89 self.selects.keys().cloned().collect() 90 } 91 92 /// All values and their associated configurations, if any. items(&self) -> Vec<(Option<String>, T::ItemType)>93 pub fn items(&self) -> Vec<(Option<String>, T::ItemType)> { 94 T::items(self) 95 } 96 97 /// All values, whether common or configured. values(&self) -> Vec<T::ItemType>98 pub fn values(&self) -> Vec<T::ItemType> { 99 T::values(self) 100 } 101 insert(&mut self, value: T::ItemType, configuration: Option<String>)102 pub(crate) fn insert(&mut self, value: T::ItemType, configuration: Option<String>) { 103 T::insert(self, value, configuration); 104 } 105 into_parts(self) -> (T::CommonType, BTreeMap<String, T::SelectsType>)106 pub(crate) fn into_parts(self) -> (T::CommonType, BTreeMap<String, T::SelectsType>) { 107 (self.common, self.selects) 108 } 109 merge(lhs: Self, rhs: Self) -> Self110 pub(crate) fn merge(lhs: Self, rhs: Self) -> Self { 111 T::merge(lhs, rhs) 112 } 113 } 114 115 impl<T> Default for Select<T> 116 where 117 T: Selectable, 118 { default() -> Self119 fn default() -> Self { 120 Self::new() 121 } 122 } 123 124 impl<'de, T> Deserialize<'de> for Select<T> 125 where 126 T: Selectable, 127 { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,128 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 129 where 130 D: Deserializer<'de>, 131 { 132 #[derive(Debug, Deserialize)] 133 #[serde(untagged)] 134 enum Either<T> 135 where 136 T: Selectable, 137 { 138 Select { 139 common: T::CommonType, 140 selects: BTreeMap<String, T::SelectsType>, 141 }, 142 Value(T::CommonType), 143 } 144 145 let either = Either::<T>::deserialize(deserializer)?; 146 match either { 147 Either::Select { common, selects } => Ok(Self { common, selects }), 148 Either::Value(common) => Ok(Self { 149 common, 150 selects: BTreeMap::new(), 151 }), 152 } 153 } 154 } 155 156 // Scalar 157 impl<T> Selectable for T 158 where 159 T: SelectableScalar, 160 { 161 type ItemType = T; 162 type CommonType = Option<Self::ItemType>; 163 type SelectsType = Self::ItemType; 164 is_empty(this: &Select<Self>) -> bool165 fn is_empty(this: &Select<Self>) -> bool { 166 this.common.is_none() && this.selects.is_empty() 167 } 168 items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)>169 fn items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)> { 170 let mut result = Vec::new(); 171 if let Some(value) = this.common.as_ref() { 172 result.push((None, value.clone())); 173 } 174 result.extend( 175 this.selects 176 .iter() 177 .map(|(configuration, value)| (Some(configuration.clone()), value.clone())), 178 ); 179 result 180 } 181 values(this: &Select<Self>) -> Vec<Self::ItemType>182 fn values(this: &Select<Self>) -> Vec<Self::ItemType> { 183 let mut result = Vec::new(); 184 if let Some(value) = this.common.as_ref() { 185 result.push(value.clone()); 186 } 187 result.extend(this.selects.values().cloned()); 188 result 189 } 190 insert(this: &mut Select<Self>, value: Self::ItemType, configuration: Option<String>)191 fn insert(this: &mut Select<Self>, value: Self::ItemType, configuration: Option<String>) { 192 match configuration { 193 None => { 194 this.selects 195 .retain(|_, existing_value| existing_value != &value); 196 this.common = Some(value); 197 } 198 Some(configuration) => { 199 if Some(&value) != this.common.as_ref() { 200 this.selects.insert(configuration, value); 201 } 202 } 203 } 204 } 205 merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self>206 fn merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self> { 207 let mut result: Select<Self> = Select::new(); 208 209 if let Some(value) = lhs.common { 210 result.insert(value, None); 211 } 212 if let Some(value) = rhs.common { 213 result.insert(value, None); 214 } 215 216 for (configuration, value) in lhs.selects.into_iter() { 217 result.insert(value, Some(configuration)); 218 } 219 for (configuration, value) in rhs.selects.into_iter() { 220 result.insert(value, Some(configuration)); 221 } 222 223 result 224 } 225 } 226 227 // Vec<T> 228 impl<T> Selectable for Vec<T> 229 where 230 T: SelectableValue, 231 { 232 type ItemType = T; 233 type CommonType = Vec<T>; 234 type SelectsType = Vec<T>; 235 is_empty(this: &Select<Self>) -> bool236 fn is_empty(this: &Select<Self>) -> bool { 237 this.common.is_empty() && this.selects.is_empty() 238 } 239 items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)>240 fn items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)> { 241 let mut result = Vec::new(); 242 result.extend(this.common.iter().map(|value| (None, value.clone()))); 243 result.extend(this.selects.iter().flat_map(|(configuration, values)| { 244 values 245 .iter() 246 .map(|value| (Some(configuration.clone()), value.clone())) 247 })); 248 result 249 } 250 values(this: &Select<Self>) -> Vec<Self::ItemType>251 fn values(this: &Select<Self>) -> Vec<Self::ItemType> { 252 let mut result = Vec::new(); 253 result.extend(this.common.iter().cloned()); 254 result.extend( 255 this.selects 256 .values() 257 .flat_map(|values| values.iter().cloned()), 258 ); 259 result 260 } 261 insert(this: &mut Select<Self>, value: Self::ItemType, configuration: Option<String>)262 fn insert(this: &mut Select<Self>, value: Self::ItemType, configuration: Option<String>) { 263 match configuration { 264 None => this.common.push(value), 265 Some(configuration) => this.selects.entry(configuration).or_default().push(value), 266 } 267 } 268 merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self>269 fn merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self> { 270 let mut result: Select<Self> = Select::new(); 271 272 for value in lhs.common.into_iter() { 273 result.insert(value, None); 274 } 275 for value in rhs.common.into_iter() { 276 result.insert(value, None); 277 } 278 279 for (configuration, values) in lhs.selects.into_iter() { 280 for value in values.into_iter() { 281 result.insert(value, Some(configuration.clone())); 282 } 283 } 284 for (configuration, values) in rhs.selects.into_iter() { 285 for value in values.into_iter() { 286 result.insert(value, Some(configuration.clone())); 287 } 288 } 289 290 result 291 } 292 } 293 294 // BTreeSet<T> 295 impl<T> Selectable for BTreeSet<T> 296 where 297 T: SelectableOrderedValue, 298 { 299 type ItemType = T; 300 type CommonType = BTreeSet<T>; 301 type SelectsType = BTreeSet<T>; 302 is_empty(this: &Select<Self>) -> bool303 fn is_empty(this: &Select<Self>) -> bool { 304 this.common.is_empty() && this.selects.is_empty() 305 } 306 items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)>307 fn items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)> { 308 let mut result = Vec::new(); 309 result.extend(this.common.iter().map(|value| (None, value.clone()))); 310 result.extend(this.selects.iter().flat_map(|(configuration, values)| { 311 values 312 .iter() 313 .map(|value| (Some(configuration.clone()), value.clone())) 314 })); 315 result 316 } 317 values(this: &Select<Self>) -> Vec<Self::ItemType>318 fn values(this: &Select<Self>) -> Vec<Self::ItemType> { 319 let mut result = Vec::new(); 320 result.extend(this.common.iter().cloned()); 321 result.extend( 322 this.selects 323 .values() 324 .flat_map(|values| values.iter().cloned()), 325 ); 326 result 327 } 328 insert(this: &mut Select<Self>, value: Self::ItemType, configuration: Option<String>)329 fn insert(this: &mut Select<Self>, value: Self::ItemType, configuration: Option<String>) { 330 match configuration { 331 None => { 332 this.selects.retain(|_, set| { 333 set.remove(&value); 334 !set.is_empty() 335 }); 336 this.common.insert(value); 337 } 338 Some(configuration) => { 339 if !this.common.contains(&value) { 340 this.selects.entry(configuration).or_default().insert(value); 341 } 342 } 343 } 344 } 345 merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self>346 fn merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self> { 347 let mut result: Select<Self> = Select::new(); 348 349 for value in lhs.common.into_iter() { 350 result.insert(value, None); 351 } 352 for value in rhs.common.into_iter() { 353 result.insert(value, None); 354 } 355 356 for (configuration, values) in lhs.selects.into_iter() { 357 for value in values { 358 result.insert(value, Some(configuration.clone())); 359 } 360 } 361 for (configuration, values) in rhs.selects.into_iter() { 362 for value in values { 363 result.insert(value, Some(configuration.clone())); 364 } 365 } 366 367 result 368 } 369 } 370 371 impl<T> Select<BTreeSet<T>> 372 where 373 T: SelectableOrderedValue, 374 { map<U, F>(self, func: F) -> Select<BTreeSet<U>> where U: SelectableOrderedValue, F: Copy + FnMut(T) -> U,375 pub(crate) fn map<U, F>(self, func: F) -> Select<BTreeSet<U>> 376 where 377 U: SelectableOrderedValue, 378 F: Copy + FnMut(T) -> U, 379 { 380 Select { 381 common: self.common.into_iter().map(func).collect(), 382 selects: self 383 .selects 384 .into_iter() 385 .map(|(configuration, values)| { 386 (configuration, values.into_iter().map(func).collect()) 387 }) 388 .collect(), 389 } 390 } 391 } 392 393 // BTreeMap<U, T> 394 impl<U, T> Selectable for BTreeMap<U, T> 395 where 396 U: SelectableOrderedValue, 397 T: SelectableValue, 398 { 399 type ItemType = (U, T); 400 type CommonType = BTreeMap<U, T>; 401 type SelectsType = BTreeMap<U, T>; 402 is_empty(this: &Select<Self>) -> bool403 fn is_empty(this: &Select<Self>) -> bool { 404 this.common.is_empty() && this.selects.is_empty() 405 } 406 items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)>407 fn items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)> { 408 let mut result = Vec::new(); 409 result.extend( 410 this.common 411 .iter() 412 .map(|(key, value)| (None, (key.clone(), value.clone()))), 413 ); 414 result.extend(this.selects.iter().flat_map(|(configuration, values)| { 415 values 416 .iter() 417 .map(|(key, value)| (Some(configuration.clone()), (key.clone(), value.clone()))) 418 })); 419 result 420 } 421 values(this: &Select<Self>) -> Vec<Self::ItemType>422 fn values(this: &Select<Self>) -> Vec<Self::ItemType> { 423 let mut result = Vec::new(); 424 result.extend( 425 this.common 426 .iter() 427 .map(|(key, value)| (key.clone(), value.clone())), 428 ); 429 result.extend(this.selects.values().flat_map(|values| { 430 values 431 .iter() 432 .map(|(key, value)| (key.clone(), value.clone())) 433 })); 434 result 435 } 436 insert( this: &mut Select<Self>, (key, value): Self::ItemType, configuration: Option<String>, )437 fn insert( 438 this: &mut Select<Self>, 439 (key, value): Self::ItemType, 440 configuration: Option<String>, 441 ) { 442 match configuration { 443 None => { 444 this.selects.retain(|_, map| { 445 map.remove(&key); 446 !map.is_empty() 447 }); 448 this.common.insert(key, value); 449 } 450 Some(configuration) => { 451 if !this.common.contains_key(&key) { 452 this.selects 453 .entry(configuration) 454 .or_default() 455 .insert(key, value); 456 } 457 } 458 } 459 } 460 merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self>461 fn merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self> { 462 let mut result: Select<Self> = Select::new(); 463 464 for (key, value) in lhs.common.into_iter() { 465 result.insert((key, value), None); 466 } 467 for (key, value) in rhs.common.into_iter() { 468 result.insert((key, value), None); 469 } 470 471 for (configuration, entries) in lhs.selects.into_iter() { 472 for (key, value) in entries { 473 result.insert((key, value), Some(configuration.clone())); 474 } 475 } 476 for (configuration, entries) in rhs.selects.into_iter() { 477 for (key, value) in entries { 478 result.insert((key, value), Some(configuration.clone())); 479 } 480 } 481 482 result 483 } 484 } 485