nimbus_fml/backends/swift/gen_structs/
mod.rs
1use askama::Template;
5use std::collections::HashSet;
6
7use crate::{
8 backends::{CodeDeclaration, CodeOracle, CodeType, TypeIdentifier},
9 intermediate_representation::{FeatureDef, FeatureManifest, TypeFinder},
10};
11mod bundled;
12mod common;
13mod enum_;
14mod feature;
15mod filters;
16mod imports;
17mod object;
18mod primitives;
19mod structural;
20
21#[derive(Template)]
22#[template(
23 syntax = "swift",
24 escape = "none",
25 path = "FeatureManifestTemplate.swift"
26)]
27pub struct FeatureManifestDeclaration<'a> {
28 fm: &'a FeatureManifest,
29 oracle: ConcreteCodeOracle,
30}
31
32impl<'a> FeatureManifestDeclaration<'a> {
33 pub fn new(fm: &'a FeatureManifest) -> Self {
34 Self {
35 fm,
36 oracle: Default::default(),
37 }
38 }
39
40 pub fn members(&self) -> Vec<Box<dyn CodeDeclaration + 'a>> {
41 let fm = self.fm;
42
43 fm.iter_feature_defs()
44 .map(|inner| {
45 Box::new(feature::FeatureCodeDeclaration::new(fm, inner))
46 as Box<dyn CodeDeclaration>
47 })
48 .chain(fm.iter_enum_defs().map(|inner| {
49 Box::new(enum_::EnumCodeDeclaration::new(fm, inner)) as Box<dyn CodeDeclaration>
50 }))
51 .chain(fm.iter_object_defs().map(|inner| {
52 Box::new(object::ObjectCodeDeclaration::new(fm, inner)) as Box<dyn CodeDeclaration>
53 }))
54 .chain(fm.iter_imported_files().iter().map(|inner| {
55 Box::new(imports::ImportedModuleInitialization::new(inner))
56 as Box<dyn CodeDeclaration>
57 }))
58 .collect()
59 }
60
61 pub fn iter_feature_defs(&self) -> Vec<&FeatureDef> {
62 self.fm.iter_feature_defs().collect::<_>()
63 }
64
65 pub fn initialization_code(&self) -> Vec<String> {
66 let oracle = &self.oracle;
67 self.members()
68 .into_iter()
69 .filter_map(|member| member.initialization_code(oracle))
70 .collect()
71 }
72
73 pub fn declaration_code(&self) -> Vec<String> {
74 let oracle = &self.oracle;
75 self.members()
76 .into_iter()
77 .filter_map(|member| member.definition_code(oracle))
78 .collect()
79 }
80
81 pub fn imports(&self) -> Vec<String> {
82 let oracle = &self.oracle;
83 let my_module = &self.fm.about.nimbus_module_name();
85 let as_module = std::env::var("MOZ_APPSERVICES_MODULE")
88 .map(|s| vec![s])
89 .unwrap_or_else(|_| vec![]);
90 let mut imports: Vec<String> = self
91 .members()
92 .into_iter()
93 .filter_map(|member| member.imports(oracle))
94 .flatten()
95 .chain(
96 self.fm
97 .all_types()
98 .into_iter()
99 .filter_map(|type_| self.oracle.find(&type_).imports(oracle))
100 .flatten(),
101 )
102 .chain(as_module)
103 .chain(vec!["Foundation".to_string()])
104 .filter(|i| i != my_module)
105 .collect::<HashSet<String>>()
106 .into_iter()
107 .collect();
108
109 imports.sort();
110 imports
111 }
112}
113
114#[derive(Default, Clone)]
115pub struct ConcreteCodeOracle;
116
117impl ConcreteCodeOracle {
118 fn create_code_type(&self, type_: TypeIdentifier) -> Box<dyn CodeType> {
119 match type_ {
120 TypeIdentifier::Boolean => Box::new(primitives::BooleanCodeType),
121 TypeIdentifier::String | TypeIdentifier::StringAlias(_) => {
122 Box::new(primitives::StringCodeType)
123 }
124 TypeIdentifier::Int => Box::new(primitives::IntCodeType),
125
126 TypeIdentifier::BundleText => Box::new(bundled::TextCodeType),
127 TypeIdentifier::BundleImage => Box::new(bundled::ImageCodeType),
128
129 TypeIdentifier::Enum(id) => Box::new(enum_::EnumCodeType::new(id)),
130 TypeIdentifier::Object(id) => Box::new(object::ObjectCodeType::new(id)),
131
132 TypeIdentifier::Option(ref inner) => Box::new(structural::OptionalCodeType::new(inner)),
133 TypeIdentifier::List(ref inner) => Box::new(structural::ListCodeType::new(inner)),
134 TypeIdentifier::StringMap(ref v_type) => {
135 let k_type = &TypeIdentifier::String;
136 Box::new(structural::MapCodeType::new(k_type, v_type))
137 }
138 TypeIdentifier::EnumMap(ref k_type, ref v_type) => {
139 Box::new(structural::MapCodeType::new(k_type, v_type))
140 }
141 }
142 }
143}
144
145impl CodeOracle for ConcreteCodeOracle {
146 fn find(&self, type_: &TypeIdentifier) -> Box<dyn CodeType> {
147 self.create_code_type(type_.clone())
148 }
149}