1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use crate::generator::dart::gen_wire2api_simple_type_cast;
use crate::generator::dart::ty::*;
use crate::ir::IrType::{DartOpaque, Delegate, EnumRef, Primitive, RustOpaque, StructRef};
use crate::ir::*;
use crate::target::Acc;
use crate::type_dart_generator_struct;

#[cfg(feature = "chrono")]
use super::gen_wire2api_chrono;

type_dart_generator_struct!(TypeBoxedGenerator, IrTypeBoxed);

fn is_empty_struct(ty: &TypeBoxedGenerator) -> bool {
    if let StructRef(ref s) = ty.ir.inner.as_ref() {
        let s = s.get(ty.context.ir_file);
        s.fields.is_empty()
    } else {
        false
    }
}

impl TypeDartGeneratorTrait for TypeBoxedGenerator<'_> {
    fn api2wire_body(&self) -> Acc<Option<String>> {
        let as_primitive = self.ir.inner.is_primitive().then(|| {
            format!(
                "return inner.new_{}_{}(api2wire_{}(raw));",
                self.ir.safe_ident(),
                self.context.config.block_index,
                self.ir.inner.safe_ident()
            )
        });
        let ident = self.ir.safe_ident();
        let context = self.context.config.block_index;
        let inner = self.ir.inner.safe_ident();
        let empty_struct = is_empty_struct(self);
        Acc {
            io: Some(as_primitive.unwrap_or_else(|| {
                if self.ir.inner.is_array() {
                    format!("return api2wire_{inner}(raw);")
                } else if empty_struct {
                    format!(
                        "final ptr = inner.new_{ident}_{context}();
                        return ptr;",
                    )
                } else {
                    format!(
                        "final ptr = inner.new_{ident}_{context}();
                        _api_fill_to_wire_{inner}(raw, ptr.ref);
                        return ptr;"
                    )
                }
            })),
            wasm: Some(format!(
                "return api2wire_{}(raw);",
                self.ir.inner.safe_ident()
            )),
            ..Default::default()
        }
    }

    fn api_fill_to_wire_body(&self) -> Option<String> {
        if self.ir.inner.is_array() {
            return Some(format!(
                "wireObj = api2wire_{}(apiObj);",
                self.ir.inner.safe_ident()
            ));
        }
        (!self.ir.inner.is_primitive() && !is_empty_struct(self)).then(|| {
            format!(
                "_api_fill_to_wire_{}(apiObj, wireObj.ref);",
                self.ir.inner.safe_ident()
            )
        })
    }

    fn wire2api_body(&self) -> String {
        match &*self.ir.inner {
            StructRef(_)
            | DartOpaque(_)
            | RustOpaque(_)
            | EnumRef(_)
            | Primitive(IrTypePrimitive::I64 | IrTypePrimitive::U64 | IrTypePrimitive::Usize)
            | Delegate(IrTypeDelegate::Array(_) | IrTypeDelegate::PrimitiveEnum { .. }) => {
                format!("return _wire2api_{}(raw);", self.ir.inner.safe_ident())
            }
            #[cfg(feature = "chrono")]
            Delegate(IrTypeDelegate::Time(time)) => gen_wire2api_chrono(time),
            _ => gen_wire2api_simple_type_cast(&self.ir.dart_api_type()),
        }
    }
}