vox_codegen/targets/swift/
encode.rs1use super::types::swift_field_name;
8use facet_core::{ScalarType, Shape};
9use vox_types::{
10 EnumInfo, ShapeKind, StructInfo, VariantKind, classify_shape, classify_variant, is_bytes,
11};
12
13pub fn generate_encode_stmt(shape: &'static Shape, value: &str) -> String {
16 if is_bytes(shape) {
17 return format!("encodeByteSeq({value}, into: &buffer)");
18 }
19
20 match classify_shape(shape) {
21 ShapeKind::Scalar(scalar) => {
22 let fn_name = swift_encode_fn(scalar);
23 format!("{fn_name}({value}, into: &buffer)")
24 }
25 ShapeKind::List { element }
26 | ShapeKind::Slice { element }
27 | ShapeKind::Array { element, .. } => {
28 let inner = generate_encode_closure(element);
29 format!("encodeVec({value}, into: &buffer, encoder: {inner})")
30 }
31 ShapeKind::Option { inner } => {
32 let inner = generate_encode_closure(inner);
33 format!("encodeOption({value}, into: &buffer, encoder: {inner})")
34 }
35 ShapeKind::Tx { .. } | ShapeKind::Rx { .. } => {
36 format!("encodeVarint({value}.channelId, into: &buffer)")
37 }
38 ShapeKind::Tuple { elements } if elements.len() == 2 => {
39 let a = generate_encode_stmt(elements[0].shape, &format!("{value}.0"));
40 let b = generate_encode_stmt(elements[1].shape, &format!("{value}.1"));
41 format!("{a}\n{b}")
42 }
43 ShapeKind::TupleStruct { fields } if fields.len() == 2 => {
44 let a = generate_encode_stmt(fields[0].shape(), &format!("{value}.0"));
45 let b = generate_encode_stmt(fields[1].shape(), &format!("{value}.1"));
46 format!("{a}\n{b}")
47 }
48 ShapeKind::Struct(StructInfo {
49 name: Some(name), ..
50 }) => {
51 let fn_name = named_type_encode_fn_name(name);
52 format!("{fn_name}({value}, into: &buffer)")
53 }
54 ShapeKind::Struct(StructInfo {
55 name: None, fields, ..
56 }) => {
57 let stmts: Vec<String> = fields
59 .iter()
60 .map(|f| {
61 let field_name = swift_field_name(f.name);
62 generate_encode_stmt(f.shape(), &format!("{value}.{field_name}"))
63 })
64 .collect();
65 stmts.join("\n")
66 }
67 ShapeKind::Enum(EnumInfo {
68 name: Some(name), ..
69 }) => {
70 let fn_name = named_type_encode_fn_name(name);
71 format!("{fn_name}({value}, into: &buffer)")
72 }
73 ShapeKind::Enum(EnumInfo { name: None, .. }) => {
74 let closure = generate_encode_closure(shape);
76 format!("{closure}({value}, &buffer)")
77 }
78 ShapeKind::Pointer { pointee } => generate_encode_stmt(pointee, value),
79 ShapeKind::Result { ok, err } => {
80 let ok_stmt = generate_encode_stmt(ok, "v");
81 let err_stmt = generate_encode_stmt(err, "e");
82 format!(
83 "switch {value} {{\ncase .success(let v):\n encodeVarint(UInt64(0), into: &buffer)\n {ok_stmt}\ncase .failure(let e):\n encodeVarint(UInt64(1), into: &buffer)\n {err_stmt}\n}}"
84 )
85 }
86 _ => format!("/* unsupported encode for {value} */"),
87 }
88}
89
90pub fn generate_encode_closure(shape: &'static Shape) -> String {
93 if is_bytes(shape) {
94 return "{ val, buf in encodeByteSeq(val, into: &buf) }".into();
95 }
96
97 match classify_shape(shape) {
98 ShapeKind::Scalar(scalar) => {
99 let fn_name = swift_encode_fn(scalar);
100 format!("{{ val, buf in {fn_name}(val, into: &buf) }}")
101 }
102 ShapeKind::List { element } | ShapeKind::Slice { element } => {
103 let inner = generate_encode_closure(element);
104 format!("{{ val, buf in encodeVec(val, into: &buf, encoder: {inner}) }}")
105 }
106 ShapeKind::Option { inner } => {
107 let inner = generate_encode_closure(inner);
108 format!("{{ val, buf in encodeOption(val, into: &buf, encoder: {inner}) }}")
109 }
110 ShapeKind::Tx { .. } | ShapeKind::Rx { .. } => {
111 "{ val, buf in encodeVarint(val.channelId, into: &buf) }".into()
112 }
113 ShapeKind::Tuple { elements } if elements.len() == 2 => {
114 let a = encode_call_expr(elements[0].shape, "val.0", "buf");
115 let b = encode_call_expr(elements[1].shape, "val.1", "buf");
116 format!("{{ val, buf in {a}; {b} }}")
117 }
118 ShapeKind::TupleStruct { fields } if fields.len() == 2 => {
119 let a = encode_call_expr(fields[0].shape(), "val.0", "buf");
120 let b = encode_call_expr(fields[1].shape(), "val.1", "buf");
121 format!("{{ val, buf in {a}; {b} }}")
122 }
123 ShapeKind::Struct(StructInfo {
124 name: Some(name), ..
125 }) => {
126 let fn_name = named_type_encode_fn_name(name);
127 format!("{{ val, buf in {fn_name}(val, into: &buf) }}")
128 }
129 ShapeKind::Struct(StructInfo {
130 name: None, fields, ..
131 }) => {
132 let stmts: Vec<String> = fields
134 .iter()
135 .map(|f| {
136 let field_name = swift_field_name(f.name);
137 let inner = generate_encode_closure(f.shape());
138 format!("{inner}(val.{field_name}, &buf)")
139 })
140 .collect();
141 if stmts.is_empty() {
142 "{ _, _ in }".into()
143 } else {
144 format!("{{ val, buf in {} }}", stmts.join("; "))
145 }
146 }
147 ShapeKind::Enum(EnumInfo {
148 name: Some(name), ..
149 }) => {
150 let fn_name = named_type_encode_fn_name(name);
151 format!("{{ val, buf in {fn_name}(val, into: &buf) }}")
152 }
153 ShapeKind::Enum(EnumInfo {
154 name: None,
155 variants,
156 }) => {
157 let mut code = "{ val, buf in\nswitch val {\n".to_string();
159 for (i, v) in variants.iter().enumerate() {
160 let variant_name = swift_field_name(v.name);
161 match classify_variant(v) {
162 VariantKind::Unit => {
163 code.push_str(&format!(
164 "case .{variant_name}: encodeVarint(UInt64({i}), into: &buf)\n"
165 ));
166 }
167 VariantKind::Newtype { inner } => {
168 let inner_closure = generate_encode_closure(inner);
169 code.push_str(&format!(
170 "case .{variant_name}(let v): encodeVarint(UInt64({i}), into: &buf); {inner_closure}(v, &buf)\n"
171 ));
172 }
173 VariantKind::Tuple { fields } => {
174 let bindings: Vec<String> =
175 (0..fields.len()).map(|j| format!("f{j}")).collect();
176 let stmts: Vec<String> = fields
177 .iter()
178 .enumerate()
179 .map(|(j, f)| {
180 let c = generate_encode_closure(f.shape());
181 format!("{c}(f{j}, &buf)")
182 })
183 .collect();
184 code.push_str(&format!(
185 "case .{variant_name}({}): encodeVarint(UInt64({i}), into: &buf); {}\n",
186 bindings
187 .iter()
188 .map(|b| format!("let {b}"))
189 .collect::<Vec<_>>()
190 .join(", "),
191 stmts.join("; ")
192 ));
193 }
194 VariantKind::Struct { fields } => {
195 let bindings: Vec<String> =
196 fields.iter().map(|f| swift_field_name(f.name)).collect();
197 let stmts: Vec<String> = fields
198 .iter()
199 .map(|f| {
200 let field_name = swift_field_name(f.name);
201 let c = generate_encode_closure(f.shape());
202 format!("{c}({field_name}, &buf)")
203 })
204 .collect();
205 code.push_str(&format!(
206 "case .{variant_name}({}): encodeVarint(UInt64({i}), into: &buf); {}\n",
207 bindings
208 .iter()
209 .map(|b| format!("let {b}"))
210 .collect::<Vec<_>>()
211 .join(", "),
212 stmts.join("; ")
213 ));
214 }
215 }
216 }
217 code.push_str("} }");
218 code
219 }
220 ShapeKind::Pointer { pointee } => generate_encode_closure(pointee),
221 ShapeKind::Result { ok, err } => {
222 let ok_closure = generate_encode_closure(ok);
223 let err_closure = generate_encode_closure(err);
224 format!(
225 "{{ val, buf in switch val {{ case .success(let v): encodeVarint(UInt64(0), into: &buf); {ok_closure}(v, &buf); case .failure(let e): encodeVarint(UInt64(1), into: &buf); {err_closure}(e, &buf) }} }}"
226 )
227 }
228 _ => "{ _, _ in /* unsupported */ }".into(),
229 }
230}
231
232pub fn generate_named_type_encode_fn(name: &str, shape: &'static Shape) -> String {
235 let fn_name = named_type_encode_fn_name(name);
236 let mut out = String::new();
237 out.push_str(&format!(
238 "nonisolated internal func {fn_name}(_ value: {name}, into buffer: inout ByteBuffer) {{\n"
239 ));
240
241 match classify_shape(shape) {
242 ShapeKind::Struct(StructInfo { fields, .. }) => {
243 for f in fields {
244 let field_name = swift_field_name(f.name);
245 let stmt = generate_encode_stmt(f.shape(), &format!("value.{field_name}"));
246 for line in stmt.lines() {
247 out.push_str(&format!(" {line}\n"));
248 }
249 }
250 }
251 ShapeKind::Enum(EnumInfo { variants, .. }) => {
252 out.push_str(" switch value {\n");
253 for (i, v) in variants.iter().enumerate() {
254 let variant_name = swift_field_name(v.name);
255 match classify_variant(v) {
256 VariantKind::Unit => {
257 out.push_str(&format!(
258 " case .{variant_name}:\n encodeVarint(UInt64({i}), into: &buffer)\n"
259 ));
260 }
261 VariantKind::Newtype { inner } => {
262 let stmt = generate_encode_stmt(inner, "val");
263 out.push_str(&format!(
264 " case .{variant_name}(let val):\n encodeVarint(UInt64({i}), into: &buffer)\n"
265 ));
266 for line in stmt.lines() {
267 out.push_str(&format!(" {line}\n"));
268 }
269 }
270 VariantKind::Tuple { fields } => {
271 let bindings: Vec<String> =
272 (0..fields.len()).map(|j| format!("f{j}")).collect();
273 let binding_str = bindings
274 .iter()
275 .map(|b| format!("let {b}"))
276 .collect::<Vec<_>>()
277 .join(", ");
278 out.push_str(&format!(
279 " case .{variant_name}({binding_str}):\n encodeVarint(UInt64({i}), into: &buffer)\n"
280 ));
281 for (j, f) in fields.iter().enumerate() {
282 let stmt = generate_encode_stmt(f.shape(), &format!("f{j}"));
283 for line in stmt.lines() {
284 out.push_str(&format!(" {line}\n"));
285 }
286 }
287 }
288 VariantKind::Struct { fields } => {
289 let bindings: Vec<String> =
290 fields.iter().map(|f| swift_field_name(f.name)).collect();
291 let binding_str = bindings
292 .iter()
293 .map(|b| format!("let {b}"))
294 .collect::<Vec<_>>()
295 .join(", ");
296 out.push_str(&format!(
297 " case .{variant_name}({binding_str}):\n encodeVarint(UInt64({i}), into: &buffer)\n"
298 ));
299 for f in fields {
300 let field_name = swift_field_name(f.name);
301 let stmt = generate_encode_stmt(f.shape(), &field_name);
302 for line in stmt.lines() {
303 out.push_str(&format!(" {line}\n"));
304 }
305 }
306 }
307 }
308 }
309 out.push_str(" }\n");
310 }
311 _ => {}
312 }
313
314 out.push_str("}\n");
315 out
316}
317
318pub fn generate_named_type_encode_fns(named_types: &[(String, &'static Shape)]) -> String {
320 named_types
321 .iter()
322 .map(|(name, shape)| generate_named_type_encode_fn(name, shape))
323 .collect::<Vec<_>>()
324 .join("\n")
325}
326
327pub fn named_type_encode_fn_name(name: &str) -> String {
329 format!("encode{name}")
330}
331
332fn encode_call_expr(shape: &'static Shape, value: &str, buf: &str) -> String {
335 if is_bytes(shape) {
336 return format!("encodeByteSeq({value}, into: &{buf})");
337 }
338 match classify_shape(shape) {
339 ShapeKind::Scalar(scalar) => {
340 let fn_name = swift_encode_fn(scalar);
341 format!("{fn_name}({value}, into: &{buf})")
342 }
343 ShapeKind::Struct(StructInfo {
344 name: Some(name), ..
345 })
346 | ShapeKind::Enum(EnumInfo {
347 name: Some(name), ..
348 }) => {
349 let fn_name = named_type_encode_fn_name(name);
350 format!("{fn_name}({value}, into: &{buf})")
351 }
352 ShapeKind::List { element } | ShapeKind::Slice { element } => {
353 let inner = generate_encode_closure(element);
354 format!("encodeVec({value}, into: &{buf}, encoder: {inner})")
355 }
356 ShapeKind::Option { inner } => {
357 let inner = generate_encode_closure(inner);
358 format!("encodeOption({value}, into: &{buf}, encoder: {inner})")
359 }
360 ShapeKind::Pointer { pointee } => encode_call_expr(pointee, value, buf),
361 ShapeKind::Tx { .. } | ShapeKind::Rx { .. } => {
362 format!("encodeVarint({value}.channelId, into: &{buf})")
363 }
364 _ => {
365 let closure = generate_encode_closure(shape);
367 format!("({closure})({value}, &{buf})")
368 }
369 }
370}
371
372pub fn swift_encode_fn(scalar: ScalarType) -> &'static str {
374 match scalar {
375 ScalarType::Bool => "encodeBool",
376 ScalarType::U8 => "encodeU8",
377 ScalarType::I8 => "encodeI8",
378 ScalarType::U16 => "encodeU16",
379 ScalarType::I16 => "encodeI16",
380 ScalarType::U32 => "encodeU32",
381 ScalarType::I32 => "encodeI32",
382 ScalarType::U64 | ScalarType::USize => "encodeVarint",
383 ScalarType::I64 | ScalarType::ISize => "encodeI64",
384 ScalarType::F32 => "encodeF32",
385 ScalarType::F64 => "encodeF64",
386 ScalarType::Char | ScalarType::Str | ScalarType::CowStr | ScalarType::String => {
387 "encodeString"
388 }
389 ScalarType::Unit => "{ _, _ in }",
390 _ => "encodeByteSeq",
391 }
392}