nimbus_fml/backends/kotlin/gen_structs/
enum_.rs
1use std::fmt::Display;
6
7use askama::Template;
8
9use super::common;
10use super::common::code_type;
11use super::filters;
12use crate::backends::{CodeDeclaration, CodeOracle, CodeType, LiteralRenderer, VariablesType};
13use crate::intermediate_representation::{EnumDef, FeatureManifest, Literal};
14
15pub(crate) struct EnumCodeType {
16 id: String,
17}
18
19impl EnumCodeType {
20 pub(crate) fn new(id: String) -> Self {
21 Self { id }
22 }
23}
24
25impl CodeType for EnumCodeType {
26 fn type_label(&self, _oracle: &dyn CodeOracle) -> String {
29 common::class_name(&self.id)
30 }
31
32 fn property_getter(
33 &self,
34 oracle: &dyn CodeOracle,
35 vars: &dyn Display,
36 prop: &dyn Display,
37 default: &dyn Display,
38 ) -> String {
39 code_type::property_getter(self, oracle, vars, prop, default)
40 }
41
42 fn value_getter(
43 &self,
44 oracle: &dyn CodeOracle,
45 vars: &dyn Display,
46 prop: &dyn Display,
47 ) -> String {
48 code_type::value_getter(self, oracle, vars, prop)
49 }
50
51 fn value_mapper(&self, oracle: &dyn CodeOracle) -> Option<String> {
52 code_type::value_mapper(self, oracle)
53 }
54
55 fn variables_type(&self, _oracle: &dyn CodeOracle) -> VariablesType {
58 VariablesType::String
59 }
60
61 fn create_transform(&self, oracle: &dyn CodeOracle) -> Option<String> {
63 Some(format!(
64 "{enum_type}::enumValue",
65 enum_type = self.type_label(oracle)
66 ))
67 }
68
69 fn as_json_transform(&self, _oracle: &dyn CodeOracle, prop: &dyn Display) -> Option<String> {
70 Some(format!("{}.toJSONString()", prop))
71 }
72
73 fn literal(
76 &self,
77 oracle: &dyn CodeOracle,
78 _ctx: &dyn Display,
79 _renderer: &dyn LiteralRenderer,
80 literal: &Literal,
81 ) -> String {
82 let variant = match literal {
83 serde_json::Value::String(v) => v,
84 _ => unreachable!(),
85 };
86
87 format!(
88 "{}.{}",
89 self.type_label(oracle),
90 common::enum_variant_name(variant)
91 )
92 }
93}
94#[derive(Template)]
95#[template(syntax = "kt", escape = "none", path = "EnumTemplate.kt")]
96pub(crate) struct EnumCodeDeclaration {
97 inner: EnumDef,
98}
99
100impl EnumCodeDeclaration {
101 pub fn new(_fm: &FeatureManifest, inner: &EnumDef) -> Self {
102 Self {
103 inner: inner.clone(),
104 }
105 }
106 fn inner(&self) -> EnumDef {
107 self.inner.clone()
108 }
109}
110
111impl CodeDeclaration for EnumCodeDeclaration {
112 fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
113 Some(self.render().unwrap())
114 }
115}
116
117#[cfg(test)]
118mod unit_tests {
119
120 use serde_json::json;
121
122 use super::*;
123 use crate::backends::TypeIdentifier;
124
125 struct TestCodeOracle;
126 impl CodeOracle for TestCodeOracle {
127 fn find(&self, _type_: &TypeIdentifier) -> Box<dyn CodeType> {
128 unreachable!()
129 }
130 }
131
132 struct TestRenderer;
133 impl LiteralRenderer for TestRenderer {
134 fn literal(
135 &self,
136 _oracle: &dyn CodeOracle,
137 _typ: &TypeIdentifier,
138 _value: &Literal,
139 _ctx: &dyn Display,
140 ) -> String {
141 unreachable!()
142 }
143 }
144
145 fn oracle() -> Box<dyn CodeOracle> {
146 Box::new(TestCodeOracle) as Box<dyn CodeOracle>
147 }
148
149 fn code_type(name: &str) -> Box<dyn CodeType> {
150 Box::new(EnumCodeType::new(name.to_string())) as Box<dyn CodeType>
151 }
152
153 #[test]
154 fn test_type_label() {
155 let ct = code_type("AEnum");
156 let oracle = &*oracle();
157 assert_eq!("AEnum".to_string(), ct.type_label(oracle))
158 }
159
160 #[test]
161 fn test_literal() {
162 let ct = code_type("AEnum");
163 let oracle = &*oracle();
164 let finder = &TestRenderer;
165 let ctx = String::from("ctx");
166 assert_eq!(
167 "AEnum.FOO".to_string(),
168 ct.literal(oracle, &ctx, finder, &json!("foo"))
169 );
170 assert_eq!(
171 "AEnum.BAR_BAZ".to_string(),
172 ct.literal(oracle, &ctx, finder, &json!("barBaz"))
173 );
174 assert_eq!(
175 "AEnum.A_B_C".to_string(),
176 ct.literal(oracle, &ctx, finder, &json!("a-b-c"))
177 );
178 }
179
180 #[test]
181 fn test_get_value() {
182 let ct = code_type("AEnum");
183 let oracle = &*oracle();
184
185 assert_eq!(
186 r#"v.getString("the-property")"#.to_string(),
187 ct.value_getter(oracle, &"v", &"the-property")
188 );
189 }
190
191 #[test]
192 fn test_getter_with_fallback() {
193 let ct = code_type("AEnum");
194 let oracle = &*oracle();
195
196 assert_eq!(
197 r#"v.getString("the-property")?.let(AEnum::enumValue) ?: def"#.to_string(),
198 ct.property_getter(oracle, &"v", &"the-property", &"def")
199 );
200 }
201}