featurecomb_schema/
lib.rs1use indexmap::IndexMap;
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12#[serde(rename_all = "kebab-case")]
13pub struct Metadata {
14 pub feature_groups: Option<FeatureGroups>,
16}
17
18#[derive(Debug, Clone, Default, Serialize, Deserialize)]
22#[serde(rename_all = "kebab-case")]
23pub struct FeatureGroups {
24 pub features: Option<FeaturesTable>,
26 #[serde(flatten)]
28 pub groups: IndexMap<FeatureGroupName, FeatureGroup>,
29}
30
31impl FeatureGroups {
32 pub fn features_in_group<'a>(
34 &'a self,
35 feature_group: &FeatureGroupName,
36 ) -> impl Iterator<Item = &'a FeatureName> {
37 self.groups
38 .get(feature_group)
39 .into_iter()
40 .flat_map(|g| g.features().into_iter().flat_map(|f| f.iter()))
41 }
42}
43
44#[derive(Debug, Clone, Default, Serialize, Deserialize)]
48#[serde(rename_all = "kebab-case")]
49pub struct FeaturesTable {
50 #[serde(flatten)]
51 features: IndexMap<FeatureName, FeatureRelations>,
52}
53
54impl FeaturesTable {
55 pub fn feature_names(&self) -> impl Iterator<Item = &FeatureName> {
57 self.features.keys()
58 }
59
60 pub fn iter(&self) -> impl Iterator<Item = (&FeatureName, &FeatureRelations)> {
62 self.features.iter()
63 }
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
68#[serde(deny_unknown_fields)]
69#[serde(rename_all = "kebab-case")]
70pub enum FeatureGroup {
71 ExactlyOne {
74 features: Vec<FeatureName>,
76 },
77 Xor {
79 features: Vec<FeatureName>,
81 },
82 #[serde(untagged)]
84 Or {
85 features: Vec<FeatureName>,
87 },
88}
89
90impl FeatureGroup {
91 #[must_use]
96 pub fn features(&self) -> Option<&Vec<FeatureName>> {
97 match self {
98 Self::ExactlyOne { features, .. }
99 | Self::Or { features, .. }
100 | Self::Xor { features, .. } => Some(features),
101 }
102 }
103}
104
105#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
107pub struct FeatureGroupName(String);
108
109impl FeatureGroupName {
110 #[must_use]
112 pub fn name(&self) -> &str {
113 &self.0
114 }
115}
116
117impl std::fmt::Display for FeatureGroupName {
118 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 write!(f, "{}", self.0)
120 }
121}
122
123#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
125pub struct FeatureName(String);
126
127impl FeatureName {
128 #[must_use]
130 pub fn name(&self) -> &str {
131 &self.0
132 }
133}
134
135impl std::fmt::Display for FeatureName {
136 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137 write!(f, "{}", self.0)
138 }
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
143#[serde(deny_unknown_fields)]
144#[serde(rename_all = "kebab-case")]
145pub enum FeatureRelations {
146 Requires {
148 features: Option<Vec<FeatureName>>,
152 groups: Option<Vec<FeatureGroupName>>,
154 },
155}