litcheck_lit/config/
features.rs1use std::{borrow::Borrow, collections::BTreeSet};
2
3use litcheck::StaticCow;
4use serde::Deserialize;
5
6use super::BooleanExpr;
7
8#[derive(Default, Clone, Deserialize)]
9#[serde(transparent)]
10pub struct FeatureSet {
11 pub features: BTreeSet<StaticCow<str>>,
12}
13impl IntoIterator for FeatureSet {
14 type Item = StaticCow<str>;
15 type IntoIter = std::collections::btree_set::IntoIter<Self::Item>;
16
17 fn into_iter(self) -> Self::IntoIter {
18 self.features.into_iter()
19 }
20}
21impl FeatureSet {
22 #[allow(unused)]
23 pub fn new<I, S>(features: I) -> Self
24 where
25 StaticCow<str>: From<S>,
26 I: IntoIterator<Item = S>,
27 {
28 let features = features.into_iter().map(StaticCow::from).collect();
29 Self { features }
30 }
31
32 #[inline]
33 pub fn is_empty(&self) -> bool {
34 self.features.is_empty()
35 }
36
37 pub fn contains<Q>(&self, feature: &Q) -> bool
38 where
39 Q: Ord + ?Sized,
40 StaticCow<str>: Borrow<Q>,
41 {
42 self.features.contains(feature)
43 }
44
45 pub fn iter(&self) -> std::collections::btree_set::Iter<'_, StaticCow<str>> {
46 self.features.iter()
47 }
48
49 pub fn insert<S>(&mut self, feature: S)
50 where
51 StaticCow<str>: From<S>,
52 {
53 self.features.insert(StaticCow::from(feature));
54 }
55
56 pub fn extend<I, S>(&mut self, features: I)
57 where
58 StaticCow<str>: From<S>,
59 I: IntoIterator<Item = S>,
60 {
61 self.features
62 .extend(features.into_iter().map(StaticCow::from));
63 }
64
65 pub fn missing_features<F: AsRef<BooleanExpr>>(&self, required: &[F]) -> Option<String> {
66 use std::fmt::Write;
67
68 let mut buf = String::new();
69 for expr in required {
70 let expr = expr.as_ref();
71 if !expr.evaluate(&self.features) {
72 if buf.is_empty() {
73 buf.push_str("Test requires the following unavailable features: ");
74 } else {
75 buf.push_str(", ");
76 }
77 write!(&mut buf, "{}", expr).unwrap();
78 }
79 }
80 if buf.is_empty() {
81 None
82 } else {
83 Some(buf)
84 }
85 }
86
87 pub fn unsupported_features<F: AsRef<BooleanExpr>>(&self, unsupported: &[F]) -> Option<String> {
88 use std::fmt::Write;
89
90 let mut buf = String::new();
91 for expr in unsupported {
92 let expr = expr.as_ref();
93 if expr.evaluate(&self.features) {
94 if buf.is_empty() {
95 buf.push_str("Test does not support the following features: ");
96 } else {
97 buf.push_str(", ");
98 }
99 write!(&mut buf, "{}", expr).unwrap();
100 }
101 }
102 if buf.is_empty() {
103 None
104 } else {
105 Some(buf)
106 }
107 }
108}