nimbus_fml/backends/kotlin/gen_structs/
primitives.rs
1use std::fmt::Display;
6
7use super::common::{code_type, quoted};
8use crate::backends::{CodeOracle, CodeType, LiteralRenderer, VariablesType};
9use crate::intermediate_representation::Literal;
10
11pub(crate) struct BooleanCodeType;
12
13impl CodeType for BooleanCodeType {
14 fn type_label(&self, _oracle: &dyn CodeOracle) -> String {
17 "Boolean".into()
18 }
19
20 fn property_getter(
21 &self,
22 oracle: &dyn CodeOracle,
23 vars: &dyn Display,
24 prop: &dyn Display,
25 default: &dyn Display,
26 ) -> String {
27 code_type::property_getter(self, oracle, vars, prop, default)
28 }
29
30 fn value_getter(
31 &self,
32 oracle: &dyn CodeOracle,
33 vars: &dyn Display,
34 prop: &dyn Display,
35 ) -> String {
36 code_type::value_getter(self, oracle, vars, prop)
37 }
38
39 fn value_mapper(&self, oracle: &dyn CodeOracle) -> Option<String> {
40 code_type::value_mapper(self, oracle)
41 }
42
43 fn variables_type(&self, _oracle: &dyn CodeOracle) -> VariablesType {
46 VariablesType::Bool
47 }
48
49 fn literal(
52 &self,
53 _oracle: &dyn CodeOracle,
54 _ctx: &dyn Display,
55 _renderer: &dyn LiteralRenderer,
56 literal: &Literal,
57 ) -> String {
58 match literal {
59 serde_json::Value::Bool(v) => {
60 if *v {
61 "true".to_string()
62 } else {
63 "false".to_string()
64 }
65 }
66 _ => unreachable!("Expecting a boolean"),
67 }
68 }
69
70 fn preference_getter(
71 &self,
72 _oracle: &dyn CodeOracle,
73 prefs: &dyn Display,
74 pref_key: &dyn Display,
75 ) -> Option<String> {
76 Some(format!("{prefs}.getBoolean({}, false)", quoted(pref_key)))
77 }
78}
79
80pub(crate) struct IntCodeType;
81
82impl CodeType for IntCodeType {
83 fn type_label(&self, _oracle: &dyn CodeOracle) -> String {
86 "Int".into()
87 }
88
89 fn property_getter(
90 &self,
91 oracle: &dyn CodeOracle,
92 vars: &dyn Display,
93 prop: &dyn Display,
94 default: &dyn Display,
95 ) -> String {
96 code_type::property_getter(self, oracle, vars, prop, default)
97 }
98
99 fn value_getter(
100 &self,
101 oracle: &dyn CodeOracle,
102 vars: &dyn Display,
103 prop: &dyn Display,
104 ) -> String {
105 code_type::value_getter(self, oracle, vars, prop)
106 }
107
108 fn value_mapper(&self, oracle: &dyn CodeOracle) -> Option<String> {
109 code_type::value_mapper(self, oracle)
110 }
111
112 fn variables_type(&self, _oracle: &dyn CodeOracle) -> VariablesType {
115 VariablesType::Int
116 }
117
118 fn literal(
121 &self,
122 _oracle: &dyn CodeOracle,
123 _ctx: &dyn Display,
124 _renderer: &dyn LiteralRenderer,
125 literal: &Literal,
126 ) -> String {
127 match literal {
128 serde_json::Value::Number(v) => {
129 format!("{:.0}", v)
130 }
131 _ => unreachable!("Expecting a number"),
132 }
133 }
134
135 fn preference_getter(
136 &self,
137 _oracle: &dyn CodeOracle,
138 prefs: &dyn Display,
139 pref_key: &dyn Display,
140 ) -> Option<String> {
141 Some(format!("{prefs}.getInt({}, 0)", quoted(pref_key)))
142 }
143}
144
145pub(crate) struct StringCodeType;
146
147impl CodeType for StringCodeType {
148 fn type_label(&self, _oracle: &dyn CodeOracle) -> String {
151 "String".into()
152 }
153
154 fn property_getter(
155 &self,
156 oracle: &dyn CodeOracle,
157 vars: &dyn Display,
158 prop: &dyn Display,
159 default: &dyn Display,
160 ) -> String {
161 code_type::property_getter(self, oracle, vars, prop, default)
162 }
163
164 fn value_getter(
165 &self,
166 oracle: &dyn CodeOracle,
167 vars: &dyn Display,
168 prop: &dyn Display,
169 ) -> String {
170 code_type::value_getter(self, oracle, vars, prop)
171 }
172
173 fn value_mapper(&self, oracle: &dyn CodeOracle) -> Option<String> {
174 code_type::value_mapper(self, oracle)
175 }
176
177 fn variables_type(&self, _oracle: &dyn CodeOracle) -> VariablesType {
180 VariablesType::String
181 }
182
183 fn literal(
186 &self,
187 _oracle: &dyn CodeOracle,
188 _ctx: &dyn Display,
189 _renderer: &dyn LiteralRenderer,
190 literal: &Literal,
191 ) -> String {
192 match literal {
193 serde_json::Value::String(v) => {
194 quoted(v)
198 }
199 _ => unreachable!("Expecting a string"),
200 }
201 }
202
203 fn preference_getter(
204 &self,
205 _oracle: &dyn CodeOracle,
206 prefs: &dyn Display,
207 pref_key: &dyn Display,
208 ) -> Option<String> {
209 Some(format!("{prefs}.getString({}, \"\")", quoted(pref_key)))
210 }
211}
212
213#[cfg(test)]
214mod unit_tests {
215
216 use serde_json::json;
217
218 use crate::backends::TypeIdentifier;
219
220 use super::*;
221
222 struct TestCodeOracle;
223 impl CodeOracle for TestCodeOracle {
224 fn find(&self, _type_: &TypeIdentifier) -> Box<dyn CodeType> {
225 unreachable!()
226 }
227 }
228
229 struct TestRenderer;
230 impl LiteralRenderer for TestRenderer {
231 fn literal(
232 &self,
233 _oracle: &dyn CodeOracle,
234 _typ: &TypeIdentifier,
235 _value: &Literal,
236 _ctx: &dyn Display,
237 ) -> String {
238 unreachable!()
239 }
240 }
241
242 fn oracle() -> Box<dyn CodeOracle> {
243 Box::new(TestCodeOracle) as Box<dyn CodeOracle>
244 }
245
246 fn bool_type() -> Box<dyn CodeType> {
247 Box::new(BooleanCodeType) as Box<dyn CodeType>
248 }
249
250 fn string_type() -> Box<dyn CodeType> {
251 Box::new(StringCodeType) as Box<dyn CodeType>
252 }
253
254 fn int_type() -> Box<dyn CodeType> {
255 Box::new(IntCodeType) as Box<dyn CodeType>
256 }
257
258 #[test]
259 fn test_type_label() {
260 let oracle = &*oracle();
261
262 let ct = bool_type();
263 assert_eq!("Boolean".to_string(), ct.type_label(oracle));
264
265 let ct = string_type();
266 assert_eq!("String".to_string(), ct.type_label(oracle));
267
268 let ct = int_type();
269 assert_eq!("Int".to_string(), ct.type_label(oracle));
270 }
271
272 #[test]
273 fn test_literal() {
274 let oracle = &*oracle();
275 let finder = &TestRenderer;
276
277 let ct = bool_type();
278 let ctx = "context".to_string();
279 assert_eq!(
280 "true".to_string(),
281 ct.literal(oracle, &ctx, finder, &json!(true))
282 );
283 assert_eq!(
284 "false".to_string(),
285 ct.literal(oracle, &ctx, finder, &json!(false))
286 );
287
288 let ct = string_type();
289 assert_eq!(
290 r#""no""#.to_string(),
291 ct.literal(oracle, &ctx, finder, &json!("no"))
292 );
293 assert_eq!(
294 r#""yes""#.to_string(),
295 ct.literal(oracle, &ctx, finder, &json!("yes"))
296 );
297
298 let ct = int_type();
299 assert_eq!("1".to_string(), ct.literal(oracle, &ctx, finder, &json!(1)));
300 assert_eq!("2".to_string(), ct.literal(oracle, &ctx, finder, &json!(2)));
301 }
302
303 #[test]
304 fn test_get_value() {
305 let oracle = &*oracle();
306
307 let ct = bool_type();
308 assert_eq!(
309 r#"v.getBool("the-property")"#.to_string(),
310 ct.value_getter(oracle, &"v", &"the-property")
311 );
312
313 let ct = string_type();
314 assert_eq!(
315 r#"v.getString("the-property")"#.to_string(),
316 ct.value_getter(oracle, &"v", &"the-property")
317 );
318
319 let ct = int_type();
320 assert_eq!(
321 r#"v.getInt("the-property")"#.to_string(),
322 ct.value_getter(oracle, &"v", &"the-property")
323 );
324 }
325}