vox_codegen/targets/swift/
decode.rs1use super::types::swift_field_name;
7use facet_core::{ScalarType, Shape};
8use vox_types::{
9 EnumInfo, ShapeKind, StructInfo, VariantKind, classify_shape, classify_variant, is_bytes,
10};
11
12pub fn generate_decode_stmt(shape: &'static Shape, var_name: &str, indent: &str) -> String {
15 generate_decode_stmt_impl(shape, var_name, indent, "buffer")
16}
17
18pub fn generate_decode_stmt_with_cursor(
21 shape: &'static Shape,
22 var_name: &str,
23 indent: &str,
24 _cursor_var: &str,
25) -> String {
26 generate_decode_stmt_impl(shape, var_name, indent, "buffer")
27}
28
29pub fn generate_decode_stmt_from(
32 shape: &'static Shape,
33 var_name: &str,
34 indent: &str,
35 _data_var: &str,
36) -> String {
37 generate_decode_stmt_impl(shape, var_name, indent, "buffer")
38}
39
40pub fn generate_decode_stmt_from_with_cursor(
43 shape: &'static Shape,
44 var_name: &str,
45 indent: &str,
46 _data_var: &str,
47 _cursor_var: &str,
48) -> String {
49 generate_decode_stmt_impl(shape, var_name, indent, "buffer")
50}
51
52pub fn generate_decode_stmt_with_buf(
54 shape: &'static Shape,
55 var_name: &str,
56 indent: &str,
57 buf_name: &str,
58) -> String {
59 generate_decode_stmt_impl(shape, var_name, indent, buf_name)
60}
61
62fn generate_decode_stmt_impl(
63 shape: &'static Shape,
64 var_name: &str,
65 indent: &str,
66 buf_name: &str,
67) -> String {
68 if is_bytes(shape) {
70 return format!(
71 "{indent}var _{var_name}_buf = try decodeBytes(from: &{buf_name})\n{indent}let {var_name} = Data(_{var_name}_buf.readBytes(length: _{var_name}_buf.readableBytes) ?? [])\n"
72 );
73 }
74
75 match classify_shape(shape) {
76 ShapeKind::Scalar(facet_core::ScalarType::Unit) => {
82 format!("{indent}let {var_name}: Void = ()\n")
83 }
84 ShapeKind::Tuple { elements: [] } => {
85 format!("{indent}let {var_name}: Void = ()\n")
86 }
87 ShapeKind::Tuple { elements } if elements.len() == 2 => {
88 let a = generate_decode_closure(elements[0].shape);
89 let b = generate_decode_closure(elements[1].shape);
90 format!(
91 "{indent}let {var_name} = try decodeTuple2(from: &{buf_name}, decoderA: {a}, decoderB: {b})\n"
92 )
93 }
94 ShapeKind::Scalar(scalar) => {
95 let decode_fn = swift_decode_fn(scalar);
96 format!("{indent}let {var_name} = try {decode_fn}(from: &{buf_name})\n")
97 }
98 ShapeKind::List { element }
99 | ShapeKind::Slice { element }
100 | ShapeKind::Array { element, .. } => {
101 let inner = generate_decode_closure(element);
102 format!("{indent}let {var_name} = try decodeVec(from: &{buf_name}, decoder: {inner})\n")
103 }
104 ShapeKind::Option { inner } => {
105 let inner = generate_decode_closure(inner);
106 format!(
107 "{indent}let {var_name} = try decodeOption(from: &{buf_name}, decoder: {inner})\n"
108 )
109 }
110 ShapeKind::TupleStruct { fields } if fields.len() == 2 => {
111 let a = generate_decode_closure(fields[0].shape());
112 let b = generate_decode_closure(fields[1].shape());
113 format!(
114 "{indent}let {var_name} = try decodeTuple2(from: &{buf_name}, decoderA: {a}, decoderB: {b})\n"
115 )
116 }
117 ShapeKind::Struct(StructInfo {
118 name: Some(name),
119 fields,
120 ..
121 }) => {
122 let mut out = String::new();
124 for f in fields.iter() {
125 let field_name = swift_field_name(f.name);
126 out.push_str(&generate_decode_stmt_impl(
127 f.shape(),
128 &format!("_{var_name}_{field_name}"),
129 indent,
130 buf_name,
131 ));
132 }
133 let field_inits: Vec<String> = fields
134 .iter()
135 .map(|f| {
136 let field_name = swift_field_name(f.name);
137 format!("{field_name}: _{var_name}_{field_name}")
138 })
139 .collect();
140 out.push_str(&format!(
141 "{indent}let {var_name} = {name}({})\n",
142 field_inits.join(", ")
143 ));
144 out
145 }
146 ShapeKind::Enum(EnumInfo {
147 name: Some(name),
148 variants,
149 ..
150 }) => {
151 let mut out = String::new();
152 out.push_str(&format!(
153 "{indent}let _{var_name}_disc = try decodeVarint(from: &{buf_name})\n"
154 ));
155 out.push_str(&format!("{indent}let {var_name}: {name}\n"));
156 out.push_str(&format!("{indent}switch _{var_name}_disc {{\n"));
157 for (i, v) in variants.iter().enumerate() {
158 out.push_str(&format!("{indent}case {i}:\n"));
159 let inner_indent = format!("{indent} ");
160 match classify_variant(v) {
161 VariantKind::Unit => {
162 out.push_str(&format!(
163 "{inner_indent}{var_name} = .{}\n",
164 swift_field_name(v.name)
165 ));
166 }
167 VariantKind::Newtype { inner } => {
168 out.push_str(&generate_decode_stmt_impl(
169 inner,
170 &format!("_{var_name}_val"),
171 &inner_indent,
172 buf_name,
173 ));
174 out.push_str(&format!(
175 "{inner_indent}{var_name} = .{}(_{var_name}_val)\n",
176 swift_field_name(v.name)
177 ));
178 }
179 VariantKind::Tuple { fields } => {
180 for (j, f) in fields.iter().enumerate() {
181 out.push_str(&generate_decode_stmt_impl(
182 f.shape(),
183 &format!("_{var_name}_f{j}"),
184 &inner_indent,
185 buf_name,
186 ));
187 }
188 let args: Vec<String> = (0..fields.len())
189 .map(|j| format!("_{var_name}_f{j}"))
190 .collect();
191 out.push_str(&format!(
192 "{inner_indent}{var_name} = .{}({})\n",
193 swift_field_name(v.name),
194 args.join(", ")
195 ));
196 }
197 VariantKind::Struct { fields } => {
198 for f in fields.iter() {
199 let field_name = swift_field_name(f.name);
200 out.push_str(&generate_decode_stmt_impl(
201 f.shape(),
202 &format!("_{var_name}_{field_name}"),
203 &inner_indent,
204 buf_name,
205 ));
206 }
207 let args: Vec<String> = fields
208 .iter()
209 .map(|f| {
210 let field_name = swift_field_name(f.name);
211 format!("{field_name}: _{var_name}_{field_name}")
212 })
213 .collect();
214 out.push_str(&format!(
215 "{inner_indent}{var_name} = .{}({})\n",
216 swift_field_name(v.name),
217 args.join(", ")
218 ));
219 }
220 }
221 }
222 out.push_str(&format!("{indent}default:\n"));
223 out.push_str(&format!(
224 "{indent} throw VoxError.decodeError(\"unknown enum variant\")\n"
225 ));
226 out.push_str(&format!("{indent}}}\n"));
227 out
228 }
229 ShapeKind::Pointer { pointee } => {
230 generate_decode_stmt_impl(pointee, var_name, indent, buf_name)
231 }
232 ShapeKind::Result { ok, err } => {
233 let ok_type = super::types::swift_type_base(ok);
234 let err_type = super::types::swift_type_base(err);
235 let mut out = String::new();
236 out.push_str(&format!(
237 "{indent}let _{var_name}_disc = try decodeVarint(from: &{buf_name})\n"
238 ));
239 out.push_str(&format!(
240 "{indent}let {var_name}: Result<{ok_type}, {err_type}>\n"
241 ));
242 out.push_str(&format!("{indent}switch _{var_name}_disc {{\n"));
243 out.push_str(&format!("{indent}case 0:\n"));
244 let inner_indent = format!("{indent} ");
245 out.push_str(&generate_decode_stmt_impl(
246 ok,
247 &format!("_{var_name}_ok"),
248 &inner_indent,
249 buf_name,
250 ));
251 out.push_str(&format!(
252 "{inner_indent}{var_name} = .success(_{var_name}_ok)\n"
253 ));
254 out.push_str(&format!("{indent}case 1:\n"));
255 out.push_str(&generate_decode_stmt_impl(
256 err,
257 &format!("_{var_name}_err"),
258 &inner_indent,
259 buf_name,
260 ));
261 out.push_str(&format!(
262 "{inner_indent}{var_name} = .failure(_{var_name}_err)\n"
263 ));
264 out.push_str(&format!("{indent}default:\n"));
265 out.push_str(&format!(
266 "{indent} throw VoxError.decodeError(\"invalid Result discriminant\")\n"
267 ));
268 out.push_str(&format!("{indent}}}\n"));
269 out
270 }
271 _ => {
272 format!("{indent}let {var_name}: Any = () // unsupported type\n")
273 }
274 }
275}
276
277pub fn generate_decode_closure(shape: &'static Shape) -> String {
280 if is_bytes(shape) {
281 return "{ buf in var _b = try decodeBytes(from: &buf); return Data(_b.readBytes(length: _b.readableBytes) ?? []) }".into();
283 }
284
285 match classify_shape(shape) {
286 ShapeKind::Scalar(scalar) => {
287 let decode_fn = swift_decode_fn(scalar);
288 format!("{{ buf in try {decode_fn}(from: &buf) }}")
289 }
290 ShapeKind::List { element } | ShapeKind::Slice { element } => {
291 let inner = generate_decode_closure(element);
292 format!("{{ buf in try decodeVec(from: &buf, decoder: {inner}) }}")
293 }
294 ShapeKind::Option { inner } => {
295 let inner = generate_decode_closure(inner);
296 format!("{{ buf in try decodeOption(from: &buf, decoder: {inner}) }}")
297 }
298 ShapeKind::Tuple { elements } if elements.len() == 2 => {
299 let a = generate_decode_closure(elements[0].shape);
300 let b = generate_decode_closure(elements[1].shape);
301 format!("{{ buf in try decodeTuple2(from: &buf, decoderA: {a}, decoderB: {b}) }}")
302 }
303 ShapeKind::TupleStruct { fields } if fields.len() == 2 => {
304 let a = generate_decode_closure(fields[0].shape());
305 let b = generate_decode_closure(fields[1].shape());
306 format!("{{ buf in try decodeTuple2(from: &buf, decoderA: {a}, decoderB: {b}) }}")
307 }
308 ShapeKind::Struct(StructInfo {
309 name: Some(name), ..
310 }) => {
311 let fn_name = named_type_decode_fn_name(name);
315 format!("{{ buf in try {fn_name}(from: &buf) }}")
316 }
317 ShapeKind::Enum(EnumInfo {
318 name: Some(name), ..
319 }) => {
320 let fn_name = named_type_decode_fn_name(name);
321 format!("{{ buf in try {fn_name}(from: &buf) }}")
322 }
323 ShapeKind::Enum(EnumInfo { name: None, .. }) => {
326 "{ _ in throw VoxError.decodeError(\"anonymous enum unsupported\") }".into()
327 }
328 ShapeKind::Pointer { pointee } => generate_decode_closure(pointee),
329 _ => "{ _ in throw VoxError.decodeError(\"unsupported type\") }".into(),
330 }
331}
332
333pub fn named_type_decode_fn_name(name: &str) -> String {
335 format!("decode{name}")
336}
337
338pub fn generate_named_type_decode_fn(name: &str, shape: &'static Shape) -> String {
340 let mut out = String::new();
341 let fn_name = named_type_decode_fn_name(name);
342 out.push_str(&format!(
343 "nonisolated internal func {fn_name}(from buffer: inout ByteBuffer) throws -> {name} {{\n"
344 ));
345
346 match classify_shape(shape) {
347 ShapeKind::Struct(StructInfo { fields, .. }) => {
348 for f in fields.iter() {
349 let field_name = swift_field_name(f.name);
350 let inner = generate_decode_closure(f.shape());
351 out.push_str(&format!(" let _{field_name} = try ({inner})(&buffer)\n"));
352 }
353 let inits: Vec<String> = fields
354 .iter()
355 .map(|f| {
356 let n = swift_field_name(f.name);
357 format!("{n}: _{n}")
358 })
359 .collect();
360 out.push_str(&format!(" return {name}({})\n", inits.join(", ")));
361 }
362 ShapeKind::Enum(EnumInfo { variants, .. }) => {
363 out.push_str(" let disc = try decodeVarint(from: &buffer)\n");
364 out.push_str(&format!(" let result: {name}\n"));
365 out.push_str(" switch disc {\n");
366 for (i, v) in variants.iter().enumerate() {
367 out.push_str(&format!(" case {i}:\n"));
368 match classify_variant(v) {
369 VariantKind::Unit => {
370 out.push_str(&format!(" result = .{}\n", swift_field_name(v.name)));
371 }
372 VariantKind::Newtype { inner } => {
373 let inner_closure = generate_decode_closure(inner);
374 out.push_str(&format!(
375 " let val = try ({inner_closure})(&buffer)\n result = .{}(val)\n",
376 swift_field_name(v.name)
377 ));
378 }
379 VariantKind::Tuple { fields } => {
380 for (j, f) in fields.iter().enumerate() {
381 let inner = generate_decode_closure(f.shape());
382 out.push_str(&format!(" let f{j} = try ({inner})(&buffer)\n"));
383 }
384 let args: Vec<String> =
385 (0..fields.len()).map(|j| format!("f{j}")).collect();
386 out.push_str(&format!(
387 " result = .{}({})\n",
388 swift_field_name(v.name),
389 args.join(", ")
390 ));
391 }
392 VariantKind::Struct { fields } => {
393 for f in fields.iter() {
394 let field_name = swift_field_name(f.name);
395 let inner = generate_decode_closure(f.shape());
396 out.push_str(&format!(
397 " let _{field_name} = try ({inner})(&buffer)\n"
398 ));
399 }
400 let args: Vec<String> = fields
401 .iter()
402 .map(|f| {
403 let n = swift_field_name(f.name);
404 format!("{n}: _{n}")
405 })
406 .collect();
407 out.push_str(&format!(
408 " result = .{}({})\n",
409 swift_field_name(v.name),
410 args.join(", ")
411 ));
412 }
413 }
414 }
415 out.push_str(
416 " default:\n throw VoxError.decodeError(\"unknown enum variant\")\n }\n return result\n",
417 );
418 }
419 _ => {}
420 }
421
422 out.push_str("}\n");
423 out
424}
425
426pub fn generate_named_type_decode_fns(named_types: &[(String, &'static Shape)]) -> String {
428 named_types
429 .iter()
430 .map(|(name, shape)| generate_named_type_decode_fn(name, shape))
431 .collect::<Vec<_>>()
432 .join("\n")
433}
434
435pub fn generate_inline_decode(shape: &'static Shape, _data_var: &str, _offset_var: &str) -> String {
438 let closure = generate_decode_closure(shape);
440 format!("({closure})(&buf)")
441}
442
443pub fn swift_decode_fn(scalar: ScalarType) -> &'static str {
445 match scalar {
446 ScalarType::Bool => "decodeBool",
447 ScalarType::U8 => "decodeU8",
448 ScalarType::I8 => "decodeI8",
449 ScalarType::U16 => "decodeU16",
450 ScalarType::I16 => "decodeI16",
451 ScalarType::U32 => "decodeU32",
452 ScalarType::I32 => "decodeI32",
453 ScalarType::U64 | ScalarType::USize => "decodeVarint",
454 ScalarType::I64 | ScalarType::ISize => "decodeI64",
455 ScalarType::F32 => "decodeF32",
456 ScalarType::F64 => "decodeF64",
457 ScalarType::Char | ScalarType::Str | ScalarType::CowStr | ScalarType::String => {
458 "decodeString"
459 }
460 ScalarType::Unit => "{ _ in () }",
461 _ => "decodeBytes",
462 }
463}