nimbus_fml/backends/
frontend_manifest.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use 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}