// File: /workspace/github_cpp_makefile_star2_O3/oknenavin[P]cxon/examples/user-types-ex02.cxx
// Function: main
struct B_union {
        int d1;                     // from D1
        std::string d2;             // from D2
        B_union() : d1(), d2() {}   // define proper defaults as from all the members
                                    // the real type should be decidable
        // tis class is only used for reading
        CXON_JSON_CLS_READ_MEMBER(B_union, CXON_JSON_CLS_FIELD_ASIS(d1), CXON_JSON_CLS_FIELD_ASIS(d2))
    };

    // specialize the read/write structs for B*

    template <typename X>
        struct read<JSON<X>, B*> {
            template <typename II, typename Cx, typename Y = JSON<X>>
                static bool value(B*& t, II& i, II e, Cx& cx) {
                    if (!cio::consume<Y>(i, e, cx)) // consume any white-spaces
                        return false;
                    if (cio::peek(i, e) == *Y::id::nil) // check/read null
                        return read_value<Y>(t, i, e, cx);
                    B_union p; // the union type that represents a B*
                        if (read_value<Y>(p, i, e, cx)) { // try reading it
                            if (p.d1) // let d1 != 0 indicates D1
                                return (t = alc::make_in_context<D1>(cx, p.d1)); // create and assign D1
                            // create and assign D2
                            return (t = alc::make_in_context<D2>(cx, std::move(p.d2)));
                        }
                        return false;
                }
        };

    template <typename X>
        struct write<JSON<X>, B*> {
            template <typename O, typename Cx, typename Y = JSON<X>>
                static bool value(O& o, const B* t, Cx& cx) {
                    if (!t) // check/write null
                            return write_value<Y>(o, nullptr, cx);
                    // cast and write the runtime type
                    switch (t->type) {
                        case B::D1:
                            return write_value<Y>(o, static_cast<const D1*>(t), cx);
                        case B::D2:
                            return write_value<Y>(o, static_cast<const D2*>(t), cx);
                    }
                    return false;
                }
        };

}


int main() {
    U u;
        cxon::from_bytes(u,
            R"({"polymorphic": [{"d2": "42"}, {"d1": 42}]})"
        );
    std::string o;
        cxon::to_bytes(o, u);
    assert(o == R"({"polymorphic":[{"d2":"42"},{"d1":42}]})");
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x58, %rsp
xorps %xmm0, %xmm0
leaq 0x40(%rsp), %r14
movaps %xmm0, (%r14)
movq $0x0, 0x10(%r14)
leaq 0x1d9e(%rip), %rax      # 0x40a0
leaq 0x28(%rsp), %r15
movq %rax, (%r15)
leaq 0x8(%rsp), %r12
movl $0x0, (%r12)
callq 0x2070
movq %rax, %rbx
movq %rax, 0x8(%r12)
leaq 0x4815(%rip), %rsi      # 0x6b40
leaq 0x1d9a(%rip), %rcx      # 0x40cc
movq %r14, %rdi
movq %r15, %rdx
movq %r12, %r8
callq 0x24cd
cmpl $0x0, 0x8(%rsp)
setne %cl
xorb %cl, %al
je 0x23f9
leaq 0x18(%rsp), %r14
movq %r14, -0x10(%r14)
movq $0x0, -0x8(%r14)
movb $0x0, (%r14)
movl $0x0, 0x28(%rsp)
movq %rbx, 0x30(%rsp)
leaq 0x8(%rsp), %rdi
movl $0x7b, %esi
callq 0x20e0
leaq 0x48e8(%rip), %rdx      # 0x6c70
leaq 0x8(%rsp), %rdi
leaq 0x40(%rsp), %rsi
leaq 0x28(%rsp), %rcx
callq 0x382c
movl %eax, %ebx
testb %al, %al
je 0x23b1
leaq 0x8(%rsp), %rdi
movl $0x7d, %esi
callq 0x20e0
cmpl $0x0, 0x28(%rsp)
setne %al
xorb %al, %bl
je 0x2418
leaq 0x1d08(%rip), %rsi      # 0x40cc
leaq 0x8(%rsp), %rdi
callq 0x2050
testl %eax, %eax
jne 0x2437
movq 0x8(%rsp), %rdi
cmpq %r14, %rdi
je 0x23e1
callq 0x2100
leaq 0x40(%rsp), %rdi
callq 0x2480
xorl %eax, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
leaq 0x1d45(%rip), %rdi      # 0x4145
leaq 0x1d4b(%rip), %rsi      # 0x4152
leaq 0x1d59(%rip), %rcx      # 0x4167
movl $0xbd, %edx
callq 0x20a0
leaq 0x1d26(%rip), %rdi      # 0x4145
leaq 0x1d2c(%rip), %rsi      # 0x4152
leaq 0x200b(%rip), %rcx      # 0x4438
movl $0xe6, %edx
callq 0x20a0
leaq 0x1cb6(%rip), %rdi      # 0x40f4
leaq 0x1ce1(%rip), %rsi      # 0x4126
leaq 0x1cee(%rip), %rcx      # 0x413a
movl $0x67, %edx
callq 0x20a0
movq %rax, %rbx
jmp 0x246d
movq %rax, %rbx
movq 0x8(%rsp), %rdi
cmpq %r14, %rdi
je 0x246d
callq 0x2100
leaq 0x40(%rsp), %rdi
callq 0x2480
movq %rbx, %rdi
callq 0x2160
nop