nimbus_fml/backends/
frontend_manifest.rs
1use std::collections::BTreeMap;
6
7use crate::frontend::{
8 EnumBody, EnumVariantBody, ExampleBlock, FeatureBody, FeatureFieldBody, FieldBody,
9 InlineExampleBlock, ManifestFrontEnd, ObjectBody, Types,
10};
11use crate::intermediate_representation::{
12 EnumDef, FeatureDef, FeatureExample, FeatureManifest, ObjectDef, PropDef, TypeRef, VariantDef,
13};
14
15impl From<FeatureManifest> for ManifestFrontEnd {
16 fn from(value: FeatureManifest) -> Self {
17 let features = merge(&value, |fm| fm.iter_feature_defs().collect(), |f| &f.name);
18 let objects = merge(&value, |fm| fm.iter_object_defs().collect(), |o| &o.name);
19 let enums = merge(&value, |fm| fm.iter_enum_defs().collect(), |e| &e.name);
20
21 let about = value.about.description_only();
22 let channels = value.channel.into_iter().collect();
23
24 ManifestFrontEnd {
25 about: Some(about),
26 version: "1.0.0".to_string(),
27 channels,
28 includes: Default::default(),
29 imports: Default::default(),
30 features,
31 legacy_types: None,
32 types: Types { enums, objects },
33 }
34 }
35}
36
37fn merge<ListGetter, NameGetter, S, T>(
38 root: &FeatureManifest,
39 list_getter: ListGetter,
40 name_getter: NameGetter,
41) -> BTreeMap<String, T>
42where
43 S: Clone,
44 T: From<S>,
45 ListGetter: Fn(&FeatureManifest) -> Vec<&S>,
46 NameGetter: Fn(&S) -> &str,
47{
48 let mut dest: BTreeMap<String, T> = BTreeMap::new();
49
50 for s in list_getter(root) {
51 dest.insert(name_getter(s).to_string(), s.to_owned().into());
52 }
53
54 for fm in root.all_imports.values() {
55 for s in list_getter(fm) {
56 dest.insert(name_getter(s).to_string(), s.to_owned().into());
57 }
58 }
59
60 dest
61}
62
63impl From<FeatureDef> for FeatureBody {
64 fn from(value: FeatureDef) -> Self {
65 let mut variables = BTreeMap::new();
66 for f in value.props {
67 variables.insert(f.name(), f.into());
68 }
69
70 let examples: Vec<_> = value.examples.into_iter().map(ExampleBlock::from).collect();
71
72 Self {
73 metadata: value.metadata,
74 variables,
75 default: None,
76 allow_coenrollment: value.allow_coenrollment,
77 examples,
78 }
79 }
80}
81
82impl From<FeatureExample> for ExampleBlock {
83 fn from(example: FeatureExample) -> Self {
84 ExampleBlock::Inline(example.into())
85 }
86}
87
88impl From<FeatureExample> for InlineExampleBlock {
89 fn from(example: FeatureExample) -> Self {
90 Self {
91 metadata: example.metadata,
92 value: example.value,
93 }
94 }
95}
96
97impl From<ObjectDef> for ObjectBody {
98 fn from(value: ObjectDef) -> Self {
99 let mut fields = BTreeMap::new();
100 for f in value.props {
101 fields.insert(f.name.clone(), f.into());
102 }
103
104 Self {
105 description: value.doc,
106 fields,
107 }
108 }
109}
110
111impl From<EnumDef> for EnumBody {
112 fn from(value: EnumDef) -> Self {
113 let mut variants = BTreeMap::new();
114 for v in value.variants {
115 variants.insert(v.name.clone(), v.into());
116 }
117 Self {
118 description: value.doc,
119 variants,
120 }
121 }
122}
123
124impl From<VariantDef> for EnumVariantBody {
125 fn from(value: VariantDef) -> Self {
126 Self {
127 description: value.doc,
128 }
129 }
130}
131
132impl From<PropDef> for FieldBody {
133 fn from(value: PropDef) -> Self {
134 Self {
135 description: value.doc,
136 variable_type: value.typ.to_string(),
137 default: Some(value.default),
138 }
139 }
140}
141
142impl From<PropDef> for FeatureFieldBody {
143 fn from(value: PropDef) -> Self {
144 Self {
145 pref_key: value.pref_key.clone(),
146 gecko_pref: value.gecko_pref.clone(),
147 string_alias: value.string_alias.as_ref().map(TypeRef::to_string),
148 field: value.into(),
149 }
150 }
151}