nimbus_fml/backends/swift/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!("{prop}.rawValue"))
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!(".{}", common::enum_variant_name(variant))
88 }
89}
90#[derive(Template)]
91#[template(syntax = "swift", escape = "none", path = "EnumTemplate.swift")]
92pub(crate) struct EnumCodeDeclaration {
93 inner: EnumDef,
94}
95
96impl EnumCodeDeclaration {
97 pub fn new(_fm: &FeatureManifest, inner: &EnumDef) -> Self {
98 Self {
99 inner: inner.clone(),
100 }
101 }
102 fn inner(&self) -> EnumDef {
103 self.inner.clone()
104 }
105}
106
107impl CodeDeclaration for EnumCodeDeclaration {
108 fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
109 Some(self.render().unwrap())
110 }
111}
112
113#[cfg(test)]
114mod unit_tests {
115
116 use serde_json::json;
117
118 use super::*;
119 use crate::backends::TypeIdentifier;
120 struct TestCodeOracle;
121 impl CodeOracle for TestCodeOracle {
122 fn find(&self, _type_: &TypeIdentifier) -> Box<dyn CodeType> {
123 unreachable!()
124 }
125 }
126
127 struct TestRenderer;
128 impl LiteralRenderer for TestRenderer {
129 fn literal(
130 &self,
131 _oracle: &dyn CodeOracle,
132 _typ: &TypeIdentifier,
133 _value: &Literal,
134 _ctx: &dyn Display,
135 ) -> String {
136 unreachable!()
137 }
138 }
139
140 fn oracle() -> Box<dyn CodeOracle> {
141 Box::new(TestCodeOracle) as Box<dyn CodeOracle>
142 }
143
144 fn code_type(name: &str) -> Box<dyn CodeType> {
145 Box::new(EnumCodeType::new(name.to_string())) as Box<dyn CodeType>
146 }
147
148 #[test]
149 fn test_type_label() {
150 let ct = code_type("AEnum");
151 let oracle = &*oracle();
152 assert_eq!("AEnum".to_string(), ct.type_label(oracle))
153 }
154
155 #[test]
156 fn test_literal() {
157 let ct = code_type("AEnum");
158 let oracle = &*oracle();
159 let finder = &TestRenderer;
160 let ctx = String::from("ctx");
161 assert_eq!(
162 ".foo".to_string(),
163 ct.literal(oracle, &ctx, finder, &json!("foo"))
164 );
165 assert_eq!(
166 ".barBaz".to_string(),
167 ct.literal(oracle, &ctx, finder, &json!("barBaz"))
168 );
169 assert_eq!(
170 ".aBC".to_string(),
171 ct.literal(oracle, &ctx, finder, &json!("a-b-c"))
172 );
173 }
174
175 #[test]
176 fn test_get_value() {
177 let ct = code_type("AEnum");
178 let oracle = &*oracle();
179
180 assert_eq!(
181 r#"v.getString("the-property")"#.to_string(),
182 ct.value_getter(oracle, &"v", &"the-property")
183 );
184 }
185
186 #[test]
187 fn test_getter_with_fallback() {
188 let ct = code_type("AEnum");
189 let oracle = &*oracle();
190
191 assert_eq!(
192 r#"v.getString("the-property")?.map(AEnum.enumValue) ?? def"#.to_string(),
193 ct.property_getter(oracle, &"v", &"the-property", &"def")
194 );
195 }
196}