<commit_before>import pytest
from prophyc import model
from prophyc.generators.cpp_full import (
    generate_struct_encode,
    generate_struct_decode,
    generate_struct_print,
    generate_union_print,
    generate_union_encode,
    generate_union_decode
)

def process(nodes):
    model.cross_reference(nodes)
    model.evaluate_kinds(nodes)
    model.evaluate_sizes(nodes)
    return nodes

@pytest.fixture
def Builtin():
    return process([
        model.Struct('Builtin', [
            model.StructMember('x', 'u32'),
            model.StructMember('y', 'u32')
        ]),
        model.Struct('BuiltinFixed', [
            model.StructMember('x', 'u32', size = 2)
        ]),
        model.Struct('BuiltinDynamic', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u32', bound = 'num_of_x')
        ]),
        model.Struct('BuiltinLimited', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u32', size = 2, bound = 'num_of_x')
        ]),
        model.Struct('BuiltinGreedy', [
            model.StructMember('x', 'u32', unlimited = True)
        ])
    ])

@pytest.fixture
def Fixcomp():
    return process([
        model.Struct('Builtin', [
            model.StructMember('x', 'u32'),
            model.StructMember('y', 'u32')
        ]),
        model.Struct('Fixcomp', [
            model.StructMember('x', 'Builtin'),
            model.StructMember('y', 'Builtin')
        ]),
        model.Struct('FixcompFixed', [
            model.StructMember('x', 'Builtin', size = 2)
        ]),
        model.Struct('FixcompDynamic', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'Builtin', bound = 'num_of_x')
        ]),
        model.Struct('FixcompLimited', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'Builtin', size = 2, bound = 'num_of_x')
        ]),
        model.Struct('FixcompGreedy', [
            model.StructMember('x', 'Builtin', unlimited = True)
        ])
    ])

@pytest.fixture
def Dyncomp():
    return process([
        model.Struct('BuiltinDynamic', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u32', bound = 'num_of_x')
        ]),
        model.Struct('Dyncomp', [
            model.StructMember('x', 'BuiltinDynamic')
        ]),
        model.Struct('DyncompDynamic', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'BuiltinDynamic', bound = 'num_of_x')
        ]),
        model.Struct('DyncompGreedy', [
            model.StructMember('x', 'BuiltinDynamic', unlimited = True)
        ])
    ])

@pytest.fixture
def Unions():
    return process([
        model.Struct('Builtin', [
            model.StructMember('x', 'u32'),
            model.StructMember('y', 'u32')
        ]),
        model.Union('Union', [
            model.UnionMember('a', 'u8', '1'),
            model.UnionMember('b', 'u32', '2'),
            model.UnionMember('c', 'Builtin', '3')
        ]),
        model.Struct('BuiltinOptional', [
            model.StructMember('x', 'u32', optional = True)
        ]),
        model.Struct('FixcompOptional', [
            model.StructMember('x', 'Builtin', optional = True)
        ])
    ])

@pytest.fixture
def Enums():
    return process([
        model.Enum('Enum', [
            model.EnumMember('Enum_One', '1'),
            model.EnumMember('Enum_Two', '2')
        ]),
        model.Struct('DynEnum', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'Enum', bound = 'num_of_x')
        ])
    ])

@pytest.fixture
def Floats():
    return process([
        model.Struct('Floats', [
            model.StructMember('a', 'r32'),
            model.StructMember('b', 'r64')
        ])
    ])

@pytest.fixture
def Bytes():
    return process([
        model.Struct('BytesFixed', [
            model.StructMember('x', 'byte', size = 3)
        ]),
        model.Struct('BytesDynamic', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'byte', bound = 'num_of_x')
        ]),
        model.Struct('BytesLimited', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'byte', size = 4, bound = 'num_of_x')
        ]),
        model.Struct('BytesGreedy', [
            model.StructMember('x', 'byte', unlimited = True)
        ])
    ])

@pytest.fixture
def Endpad():
    return process([
        model.Struct('Endpad', [
            model.StructMember('x', 'u16'),
            model.StructMember('y', 'u8')
        ]),
        model.Struct('EndpadFixed', [
            model.StructMember('x', 'u32'),
            model.StructMember('y', 'u8', size = 3)
        ]),
        model.Struct('EndpadDynamic', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u8', bound = 'num_of_x')
        ]),
        model.Struct('EndpadLimited', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u8', size = 2, bound = 'num_of_x')
        ]),
        model.Struct('EndpadGreedy', [
            model.StructMember('x', 'u32'),
            model.StructMember('y', 'u8', unlimited = True)
        ])
    ])

@pytest.fixture
def Scalarpad():
    return process([
        model.Struct('Scalarpad', [
            model.StructMember('x', 'u8'),
            model.StructMember('y', 'u16')
        ]),
        model.Struct('ScalarpadComppre_Helper', [
            model.StructMember('x', 'u8')
        ]),
        model.Struct('ScalarpadComppre', [
            model.StructMember('x', 'ScalarpadComppre_Helper'),
            model.StructMember('y', 'u16')
        ]),
        model.Struct('ScalarpadComppost_Helper', [
            model.StructMember('x', 'u16')
        ]),
        model.Struct('ScalarpadComppost', [
            model.StructMember('x', 'u8'),
            model.StructMember('y', 'ScalarpadComppost_Helper')
        ]),
    ])

@pytest.fixture
def Unionpad():
    return process([
        model.Struct('UnionpadOptionalboolpad', [
            model.StructMember('x', 'u8'),
            model.StructMember('y', 'u8', optional = True)
        ]),
        model.Struct('UnionpadOptionalvaluepad', [
            model.StructMember('x', 'u64', optional = True)
        ]),
        model.Union('UnionpadDiscpad_Helper', [
            model.UnionMember('a', 'u8', '1')
        ]),
        model.Struct('UnionpadDiscpad', [
            model.StructMember('x', 'u8'),
            model.StructMember('y', 'UnionpadDiscpad_Helper')
        ]),
        model.Union('UnionpadArmpad_Helper', [
            model.UnionMember('a', 'u8', '1'),
            model.UnionMember('b', 'u64', '2')
        ]),
        model.Struct('UnionpadArmpad', [
            model.StructMember('x', 'u8'),
            model.StructMember('y', 'UnionpadArmpad_Helper')
        ])
    ])

@pytest.fixture
def Arraypad():
    return process([
        model.Struct('ArraypadCounter', [
            model.StructMember('num_of_x', 'u8'),
            model.StructMember('x', 'u16', bound = 'num_of_x')
        ]),
        model.Struct('ArraypadCounterSeparated', [
            model.StructMember('num_of_x', 'u8'),
            model.StructMember('y', 'u32'),
            model.StructMember('x', 'u32', bound = 'num_of_x')
        ]),
        model.Struct('ArraypadCounterAligns_Helper', [
            model.StructMember('num_of_x', 'u16'),
            model.StructMember('x', 'u8', bound = 'num_of_x')
        ]),
        model.Struct('ArraypadCounterAligns', [
            model.StructMember('x', 'u8'),
            model.StructMember('y', 'ArraypadCounterAligns_Helper')
        ]),
        model.Struct('ArraypadFixed', [
            model.StructMember('x', 'u32'),
            model.StructMember('y', 'u8', size = 3),
            model.StructMember('z', 'u32')
        ]),
        model.Struct('ArraypadDynamic', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u8', bound = 'num_of_x'),
            model.StructMember('y', 'u32')
        ]),
        model.Struct('ArraypadLimited', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u8', size = 2, bound = 'num_of_x'),
            model.StructMember('y', 'u32')
        ])
    ])

@pytest.fixture
def Dynfields():
    return process([
        model.Struct('Dynfields', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u8', bound = 'num_of_x'),
            model.StructMember('num_of_y', 'u16'),
            model.StructMember('y', 'u16', bound = 'num_of_y'),
            model.StructMember('z', 'u64')
        ]),
        model.Struct('DynfieldsMixed', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('num_of_y', 'u16'),
            model.StructMember('x', 'u8', bound = 'num_of_x'),
            model.StructMember('y', 'u16', bound = 'num_of_y')
        ]),
        model.Struct('DynfieldsOverlapped', [
            model.StructMember('num_of_a', 'u32'),
            model.StructMember('num_of_b', 'u32'),
            model.StructMember('b', 'u16', bound = 'num_of_b'),
            model.StructMember('num_of_c', 'u32'),
            model.StructMember('c', 'u16', bound = 'num_of_c'),
            model.StructMember('a', 'u16', bound = 'num_of_a')
        ]),
        model.Struct('DynfieldsPartialpad_Helper', [
            model.StructMember('num_of_x', 'u8'),
            model.StructMember('x', 'u8', bound = 'num_of_x'),
            model.StructMember('y', 'u8'),
            model.StructMember('z', 'u64')
        ]),
        model.Struct('DynfieldsPartialpad', [
            model.StructMember('x', 'u8'),
            model.StructMember('y', 'DynfieldsPartialpad_Helper')
        ]),
        model.Struct('DynfieldsScalarpartialpad_Helper', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u8', bound = 'num_of_x')
        ]),
        model.Struct('DynfieldsScalarpartialpad', [
            model.StructMember('x', 'DynfieldsScalarpartialpad_Helper'),
            model.StructMember('y', 'DynfieldsScalarpartialpad_Helper'),
            model.StructMember('z', 'DynfieldsScalarpartialpad_Helper')
        ])
    ])

def test_generate_builtin_encode(Builtin):
    assert generate_struct_encode(Builtin[0]) == """\
pos = do_encode<E>(pos, x.x);
pos = do_encode<E>(pos, x.y);
"""
    assert generate_struct_encode(Builtin[1]) == """\
pos = do_encode<E>(pos, x.x, 2);
"""
    assert generate_struct_encode(Builtin[2]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
"""
    assert generate_struct_encode(Builtin[3]) == """\
pos = do_encode<E>(pos, uint32_t(std::min(x.x.size(), size_t(2))));
do_encode<E>(pos, x.x.data(), uint32_t(std::min(x.x.size(), size_t(2))));
pos = pos + 8;
"""
    assert generate_struct_encode(Builtin[4]) == """\
pos = do_encode<E>(pos, x.x.data(), x.x.size());
"""

def test_generate_fixcomp_encode(Fixcomp):
    assert generate_struct_encode(Fixcomp[1]) == """\
pos = do_encode<E>(pos, x.x);
pos = do_encode<E>(pos, x.y);
"""
    assert generate_struct_encode(Fixcomp[2]) == """\
pos = do_encode<E>(pos, x.x, 2);
"""
    assert generate_struct_encode(Fixcomp[3]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
"""
    assert generate_struct_encode(Fixcomp[4]) == """\
pos = do_encode<E>(pos, uint32_t(std::min(x.x.size(), size_t(2))));
do_encode<E>(pos, x.x.data(), uint32_t(std::min(x.x.size(), size_t(2))));
pos = pos + 16;
"""
    assert generate_struct_encode(Fixcomp[5]) == """\
pos = do_encode<E>(pos, x.x.data(), x.x.size());
"""

def test_generate_dyncomp_encode(Dyncomp):
    assert generate_struct_encode(Dyncomp[1]) == """\
pos = do_encode<E>(pos, x.x);
"""
    assert generate_struct_encode(Dyncomp[2]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
"""
    assert generate_struct_encode(Dyncomp[3]) == """\
pos = do_encode<E>(pos, x.x.data(), x.x.size());
"""

def test_generate_unions_encode(Unions):
    assert generate_union_encode(Unions[1]) == """\
pos = do_encode<E>(pos, x.discriminator);
switch (x.discriminator)
{
    case Union::discriminator_a: do_encode<E>(pos, x.a); break;
    case Union::discriminator_b: do_encode<E>(pos, x.b); break;
    case Union::discriminator_c: do_encode<E>(pos, x.c); break;
}
pos = pos + 8;
"""
    assert generate_struct_encode(Unions[2]) == """\
pos = do_encode<E>(pos, x.has_x);
if (x.has_x) do_encode<E>(pos, x.x);
pos = pos + 4;
"""
    assert generate_struct_encode(Unions[3]) == """\
pos = do_encode<E>(pos, x.has_x);
if (x.has_x) do_encode<E>(pos, x.x);
pos = pos + 8;
"""

def test_generate_enums_encode(Enums):
    assert generate_struct_encode(Enums[1]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
"""

def test_generate_floats_encode(Floats):
    assert generate_struct_encode(Floats[0]) == """\
pos = do_encode<E>(pos, x.a);
pos = pos + 4;
pos = do_encode<E>(pos, x.b);
"""

def test_generate_bytes_encode(Bytes):
    assert generate_struct_encode(Bytes[0]) == """\
pos = do_encode<E>(pos, x.x, 3);
"""
    assert generate_struct_encode(Bytes[1]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
pos = align<4>(pos);
"""
    assert generate_struct_encode(Bytes[2]) == """\
pos = do_encode<E>(pos, uint32_t(std::min(x.x.size(), size_t(4))));
do_encode<E>(pos, x.x.data(), uint32_t(std::min(x.x.size(), size_t(4))));
pos = pos + 4;
"""
    assert generate_struct_encode(Bytes[3]) == """\
pos = do_encode<E>(pos, x.x.data(), x.x.size());
"""

def test_generate_endpad_encode(Endpad):
    assert generate_struct_encode(Endpad[0]) == """\
pos = do_encode<E>(pos, x.x);
pos = do_encode<E>(pos, x.y);
pos = pos + 1;
"""
    assert generate_struct_encode(Endpad[1]) == """\
pos = do_encode<E>(pos, x.x);
pos = do_encode<E>(pos, x.y, 3);
pos = pos + 1;
"""
    assert generate_struct_encode(Endpad[2]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
pos = align<4>(pos);
"""
    assert generate_struct_encode(Endpad[3]) == """\
pos = do_encode<E>(pos, uint32_t(std::min(x.x.size(), size_t(2))));
do_encode<E>(pos, x.x.data(), uint32_t(std::min(x.x.size(), size_t(2))));
pos = pos + 2;
pos = pos + 2;
"""
    assert generate_struct_encode(Endpad[4]) == """\
pos = do_encode<E>(pos, x.x);
pos = do_encode<E>(pos, x.y.data(), x.y.size());
pos = align<4>(pos);
"""

def test_generate_scalarpad_encode(Scalarpad):
    assert generate_struct_encode(Scalarpad[0]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 1;
pos = do_encode<E>(pos, x.y);
"""
    assert generate_struct_encode(Scalarpad[2]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 1;
pos = do_encode<E>(pos, x.y);
"""
    assert generate_struct_encode(Scalarpad[4]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 1;
pos = do_encode<E>(pos, x.y);
"""

def test_generate_unionpad_encode(Unionpad):
    assert generate_struct_encode(Unionpad[0]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 3;
pos = do_encode<E>(pos, x.has_y);
if (x.has_y) do_encode<E>(pos, x.y);
pos = pos + 1;
pos = pos + 3;
"""
    assert generate_struct_encode(Unionpad[1]) == """\
pos = do_encode<E>(pos, x.has_x);
pos = pos + 4;
if (x.has_x) do_encode<E>(pos, x.x);
pos = pos + 8;
"""
    assert generate_union_encode(Unionpad[2]) == """\
pos = do_encode<E>(pos, x.discriminator);
switch (x.discriminator)
{
    case UnionpadDiscpad_Helper::discriminator_a: do_encode<E>(pos, x.a); break;
}
pos = pos + 4;
"""
    assert generate_struct_encode(Unionpad[3]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 3;
pos = do_encode<E>(pos, x.y);
"""
    assert generate_union_encode(Unionpad[4]) == """\
pos = do_encode<E>(pos, x.discriminator);
pos = pos + 4;
switch (x.discriminator)
{
    case UnionpadArmpad_Helper::discriminator_a: do_encode<E>(pos, x.a); break;
    case UnionpadArmpad_Helper::discriminator_b: do_encode<E>(pos, x.b); break;
}
pos = pos + 8;
"""
    assert generate_struct_encode(Unionpad[5]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 7;
pos = do_encode<E>(pos, x.y);
"""

def test_generate_arraypad_encode(Arraypad):
    assert generate_struct_encode(Arraypad[0]) == """\
pos = do_encode<E>(pos, uint8_t(x.x.size()));
pos = pos + 1;
pos = do_encode<E>(pos, x.x.data(), uint8_t(x.x.size()));
"""
    assert generate_struct_encode(Arraypad[1]) == """\
pos = do_encode<E>(pos, uint8_t(x.x.size()));
pos = pos + 3;
pos = do_encode<E>(pos, x.y);
pos = do_encode<E>(pos, x.x.data(), uint8_t(x.x.size()));
"""
    assert generate_struct_encode(Arraypad[2]) == """\
pos = do_encode<E>(pos, uint16_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint16_t(x.x.size()));
pos = align<2>(pos);
"""
    assert generate_struct_encode(Arraypad[3]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 1;
pos = do_encode<E>(pos, x.y);
"""
    assert generate_struct_encode(Arraypad[4]) == """\
pos = do_encode<E>(pos, x.x);
pos = do_encode<E>(pos, x.y, 3);
pos = pos + 1;
pos = do_encode<E>(pos, x.z);
"""
    assert generate_struct_encode(Arraypad[5]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
pos = align<4>(pos);
pos = do_encode<E>(pos, x.y);
"""
    assert generate_struct_encode(Arraypad[6]) == """\
pos = do_encode<E>(pos, uint32_t(std::min(x.x.size(), size_t(2))));
do_encode<E>(pos, x.x.data(), uint32_t(std::min(x.x.size(), size_t(2))));
pos = pos + 2;
pos = pos + 2;
pos = do_encode<E>(pos, x.y);
"""

def test_generate_dynfields_encode(Dynfields):
    assert generate_struct_encode(Dynfields[0]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
pos = align<2>(pos);
pos = do_encode<E>(pos, uint16_t(x.y.size()));
pos = do_encode<E>(pos, x.y.data(), uint16_t(x.y.size()));
pos = align<8>(pos);
pos = do_encode<E>(pos, x.z);
"""
    assert generate_struct_encode(Dynfields[1]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, uint16_t(x.y.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
pos = align<2>(pos);
pos = do_encode<E>(pos, x.y.data(), uint16_t(x.y.size()));
pos = align<4>(pos);
"""
    assert generate_struct_encode(Dynfields[2]) == """\
pos = do_encode<E>(pos, uint32_t(x.a.size()));
pos = do_encode<E>(pos, uint32_t(x.b.size()));
pos = do_encode<E>(pos, x.b.data(), uint32_t(x.b.size()));
pos = align<4>(pos);
pos = do_encode<E>(pos, uint32_t(x.c.size()));
pos = do_encode<E>(pos, x.c.data(), uint32_t(x.c.size()));
pos = do_encode<E>(pos, x.a.data(), uint32_t(x.a.size()));
pos = align<4>(pos);
"""
    assert generate_struct_encode(Dynfields[3]) == """\
pos = do_encode<E>(pos, uint8_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint8_t(x.x.size()));
pos = align<8>(pos);
pos = do_encode<E>(pos, x.y);
pos = pos + 7;
pos = do_encode<E>(pos, x.z);
"""
    assert generate_struct_encode(Dynfields[4]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 7;
pos = do_encode<E>(pos, x.y);
"""
    assert generate_struct_encode(Dynfields[5]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
pos = align<4>(pos);
"""
    assert generate_struct_encode(Dynfields[6]) == """\
pos = do_encode<E>(pos, x.x);
pos = do_encode<E>(pos, x.y);
pos = do_encode<E>(pos, x.z);
"""

def test_generate_builtin_decode(Builtin):
    assert generate_struct_decode(Builtin[0]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_struct_decode(Builtin[1]) == """\
do_decode<E>(x.x, 2, pos, end)
"""
    assert generate_struct_decode(Builtin[2]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end)
"""
    assert generate_struct_decode(Builtin[3]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end, 2) &&
do_decode_in_place<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_advance(8, pos, end)
"""
    assert generate_struct_decode(Builtin[4]) == """\
do_decode_greedy<E>(x.x, pos, end)
"""

def test_generate_fixcomp_decode(Fixcomp):
    assert generate_struct_decode(Fixcomp[1]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_struct_decode(Fixcomp[2]) == """\
do_decode<E>(x.x, 2, pos, end)
"""
    assert generate_struct_decode(Fixcomp[3]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end)
"""
    assert generate_struct_decode(Fixcomp[4]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end, 2) &&
do_decode_in_place<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_advance(16, pos, end)
"""
    assert generate_struct_decode(Fixcomp[5]) == """\
do_decode_greedy<E>(x.x, pos, end)
"""

def test_generate_dyncomp_decode(Dyncomp):
    assert generate_struct_decode(Dyncomp[1]) == """\
do_decode<E>(x.x, pos, end)
"""
    assert generate_struct_decode(Dyncomp[2]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end)
"""
    assert generate_struct_decode(Dyncomp[3]) == """\
do_decode_greedy<E>(x.x, pos, end)
"""

def test_generate_unions_decode(Unions):
    assert generate_union_decode(Unions[1]) == """\
if (!do_decode<E>(x.discriminator, pos, end)) return false;
switch (x.discriminator)
{
    case Union::discriminator_a: if (!do_decode_in_place<E>(x.a, pos, end)) return false; break;
    case Union::discriminator_b: if (!do_decode_in_place<E>(x.b, pos, end)) return false; break;
    case Union::discriminator_c: if (!do_decode_in_place<E>(x.c, pos, end)) return false; break;
    default: return false;
}
return do_decode_advance(8, pos, end);
"""
    assert generate_struct_decode(Unions[2]) == """\
do_decode<E>(x.has_x, pos, end) &&
do_decode_in_place_optional<E>(x.x, x.has_x, pos, end) &&
do_decode_advance(4, pos, end)
"""
    assert generate_struct_decode(Unions[3]) == """\
do_decode<E>(x.has_x, pos, end) &&
do_decode_in_place_optional<E>(x.x, x.has_x, pos, end) &&
do_decode_advance(8, pos, end)
"""

def test_generate_enums_decode(Enums):
    assert generate_struct_decode(Enums[1]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end)
"""

def test_generate_floats_decode(Floats):
    assert generate_struct_decode(Floats[0]) == """\
do_decode<E>(x.a, pos, end) &&
do_decode_advance(4, pos, end) &&
do_decode<E>(x.b, pos, end)
"""

def test_generate_bytes_decode(Bytes):
    assert generate_struct_decode(Bytes[0]) == """\
do_decode<E>(x.x, 3, pos, end)
"""
    assert generate_struct_decode(Bytes[1]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<4>(pos, end)
"""
    assert generate_struct_decode(Bytes[2]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end, 4) &&
do_decode_in_place<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_advance(4, pos, end)
"""
    assert generate_struct_decode(Bytes[3]) == """\
do_decode_greedy<E>(x.x, pos, end)
"""

def test_generate_endpad_decode(Endpad):
    assert generate_struct_decode(Endpad[0]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode<E>(x.y, pos, end) &&
do_decode_advance(1, pos, end)
"""
    assert generate_struct_decode(Endpad[1]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode<E>(x.y, 3, pos, end) &&
do_decode_advance(1, pos, end)
"""
    assert generate_struct_decode(Endpad[2]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<4>(pos, end)
"""
    assert generate_struct_decode(Endpad[3]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end, 2) &&
do_decode_in_place<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_advance(2, pos, end) &&
do_decode_advance(2, pos, end)
"""
    assert generate_struct_decode(Endpad[4]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_greedy<E>(x.y, pos, end) &&
do_decode_align<4>(pos, end)
"""

def test_generate_scalarpad_decode(Scalarpad):
    assert generate_struct_decode(Scalarpad[0]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(1, pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_struct_decode(Scalarpad[2]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(1, pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_struct_decode(Scalarpad[4]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(1, pos, end) &&
do_decode<E>(x.y, pos, end)
"""

def test_generate_unionpad_decode(Unionpad):
    assert generate_struct_decode(Unionpad[0]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(3, pos, end) &&
do_decode<E>(x.has_y, pos, end) &&
do_decode_in_place_optional<E>(x.y, x.has_y, pos, end) &&
do_decode_advance(1, pos, end) &&
do_decode_advance(3, pos, end)
"""
    assert generate_struct_decode(Unionpad[1]) == """\
do_decode<E>(x.has_x, pos, end) &&
do_decode_advance(4, pos, end) &&
do_decode_in_place_optional<E>(x.x, x.has_x, pos, end) &&
do_decode_advance(8, pos, end)
"""
    assert generate_union_decode(Unionpad[2]) == """\
if (!do_decode<E>(x.discriminator, pos, end)) return false;
switch (x.discriminator)
{
    case UnionpadDiscpad_Helper::discriminator_a: if (!do_decode_in_place<E>(x.a, pos, end)) return false; break;
    default: return false;
}
return do_decode_advance(4, pos, end);
"""
    assert generate_struct_decode(Unionpad[3]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(3, pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_union_decode(Unionpad[4]) == """\
if (!do_decode<E>(x.discriminator, pos, end)) return false;
if (!do_decode_advance(4, pos, end)) return false;
switch (x.discriminator)
{
    case UnionpadArmpad_Helper::discriminator_a: if (!do_decode_in_place<E>(x.a, pos, end)) return false; break;
    case UnionpadArmpad_Helper::discriminator_b: if (!do_decode_in_place<E>(x.b, pos, end)) return false; break;
    default: return false;
}
return do_decode_advance(8, pos, end);
"""
    assert generate_struct_decode(Unionpad[5]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(7, pos, end) &&
do_decode<E>(x.y, pos, end)
"""

def test_generate_arraypad_decode(Arraypad):
    assert generate_struct_decode(Arraypad[0]) == """\
do_decode_resize<E, uint8_t>(x.x, pos, end) &&
do_decode_advance(1, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end)
"""
    assert generate_struct_decode(Arraypad[1]) == """\
do_decode_resize<E, uint8_t>(x.x, pos, end) &&
do_decode_advance(3, pos, end) &&
do_decode<E>(x.y, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end)
"""
    assert generate_struct_decode(Arraypad[2]) == """\
do_decode_resize<E, uint16_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<2>(pos, end)
"""
    assert generate_struct_decode(Arraypad[3]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(1, pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_struct_decode(Arraypad[4]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode<E>(x.y, 3, pos, end) &&
do_decode_advance(1, pos, end) &&
do_decode<E>(x.z, pos, end)
"""
    assert generate_struct_decode(Arraypad[5]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<4>(pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_struct_decode(Arraypad[6]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end, 2) &&
do_decode_in_place<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_advance(2, pos, end) &&
do_decode_advance(2, pos, end) &&
do_decode<E>(x.y, pos, end)
"""

def test_generate_dynfields_decode(Dynfields):
    assert generate_struct_decode(Dynfields[0]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<2>(pos, end) &&
do_decode_resize<E, uint16_t>(x.y, pos, end) &&
do_decode<E>(x.y.data(), x.y.size(), pos, end) &&
do_decode_align<8>(pos, end) &&
do_decode<E>(x.z, pos, end)
"""
    assert generate_struct_decode(Dynfields[1]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode_resize<E, uint16_t>(x.y, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<2>(pos, end) &&
do_decode<E>(x.y.data(), x.y.size(), pos, end) &&
do_decode_align<4>(pos, end)
"""
    assert generate_struct_decode(Dynfields[2]) == """\
do_decode_resize<E, uint32_t>(x.a, pos, end) &&
do_decode_resize<E, uint32_t>(x.b, pos, end) &&
do_decode<E>(x.b.data(), x.b.size(), pos, end) &&
do_decode_align<4>(pos, end) &&
do_decode_resize<E, uint32_t>(x.c, pos, end) &&
do_decode<E>(x.c.data(), x.c.size(), pos, end) &&
do_decode<E>(x.a.data(), x.a.size(), pos, end) &&
do_decode_align<4>(pos, end)
"""
    assert generate_struct_decode(Dynfields[3]) == """\
do_decode_resize<E, uint8_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<8>(pos, end) &&
do_decode<E>(x.y, pos, end) &&
do_decode_advance(7, pos, end) &&
do_decode<E>(x.z, pos, end)
"""
    assert generate_struct_decode(Dynfields[4]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(7, pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_struct_decode(Dynfields[5]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<4>(pos, end)
"""
    assert generate_struct_decode(Dynfields[6]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode<E>(x.y, pos, end) &&
do_decode<E>(x.z, pos, end)
"""

def test_generate_builtin_print(Builtin):
    assert generate_struct_print(Builtin[0]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y);
"""
    assert generate_struct_print(Builtin[1]) == """\
do_print(out, indent, "x", x.x, size_t(2));
"""
    assert generate_struct_print(Builtin[2]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""
    assert generate_struct_print(Builtin[3]) == """\
do_print(out, indent, "x", x.x.data(), std::min(x.x.size(), size_t(2)));
"""
    assert generate_struct_print(Builtin[4]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""

def test_generate_fixcomp_print(Fixcomp):
    assert generate_struct_print(Fixcomp[1]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y);
"""
    assert generate_struct_print(Fixcomp[2]) == """\
do_print(out, indent, "x", x.x, size_t(2));
"""
    assert generate_struct_print(Fixcomp[3]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""
    assert generate_struct_print(Fixcomp[4]) == """\
do_print(out, indent, "x", x.x.data(), std::min(x.x.size(), size_t(2)));
"""
    assert generate_struct_print(Fixcomp[5]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""

def test_generate_dyncomp_print(Dyncomp):
    assert generate_struct_print(Dyncomp[1]) == """\
do_print(out, indent, "x", x.x);
"""
    assert generate_struct_print(Dyncomp[2]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""
    assert generate_struct_print(Dyncomp[3]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""

def test_generate_unions_print(Unions):
    assert generate_union_print(Unions[1]) == """\
switch (x.discriminator)
{
    case Union::discriminator_a: do_print(out, indent, "a", x.a); break;
    case Union::discriminator_b: do_print(out, indent, "b", x.b); break;
    case Union::discriminator_c: do_print(out, indent, "c", x.c); break;
}
"""
    assert generate_struct_print(Unions[2]) == """\
if (x.has_x) do_print(out, indent, "x", x.x);
"""
    assert generate_struct_print(Unions[3]) == """\
if (x.has_x) do_print(out, indent, "x", x.x);
"""

def test_generate_enums_print(Enums):
    assert generate_struct_print(Enums[1]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""

def test_generate_floats_print(Floats):
    assert generate_struct_print(Floats[0]) == """\
do_print(out, indent, "a", x.a);
do_print(out, indent, "b", x.b);
"""

def test_generate_bytes_print(Bytes):
    assert generate_struct_print(Bytes[0]) == """\
do_print(out, indent, "x", std::make_pair(x.x, size_t(3)));
"""
    assert generate_struct_print(Bytes[1]) == """\
do_print(out, indent, "x", std::make_pair(x.x.data(), x.x.size()));
"""
    assert generate_struct_print(Bytes[2]) == """\
do_print(out, indent, "x", std::make_pair(x.x.data(), std::min(x.x.size(), size_t(4))));
"""
    assert generate_struct_print(Bytes[3]) == """\
do_print(out, indent, "x", std::make_pair(x.x.data(), x.x.size()));
"""<commit_msg>remaining print tests<commit_after>import pytest
from prophyc import model
from prophyc.generators.cpp_full import (
    generate_struct_encode,
    generate_struct_decode,
    generate_struct_print,
    generate_union_print,
    generate_union_encode,
    generate_union_decode
)

def process(nodes):
    model.cross_reference(nodes)
    model.evaluate_kinds(nodes)
    model.evaluate_sizes(nodes)
    return nodes

@pytest.fixture
def Builtin():
    return process([
        model.Struct('Builtin', [
            model.StructMember('x', 'u32'),
            model.StructMember('y', 'u32')
        ]),
        model.Struct('BuiltinFixed', [
            model.StructMember('x', 'u32', size = 2)
        ]),
        model.Struct('BuiltinDynamic', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u32', bound = 'num_of_x')
        ]),
        model.Struct('BuiltinLimited', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u32', size = 2, bound = 'num_of_x')
        ]),
        model.Struct('BuiltinGreedy', [
            model.StructMember('x', 'u32', unlimited = True)
        ])
    ])

@pytest.fixture
def Fixcomp():
    return process([
        model.Struct('Builtin', [
            model.StructMember('x', 'u32'),
            model.StructMember('y', 'u32')
        ]),
        model.Struct('Fixcomp', [
            model.StructMember('x', 'Builtin'),
            model.StructMember('y', 'Builtin')
        ]),
        model.Struct('FixcompFixed', [
            model.StructMember('x', 'Builtin', size = 2)
        ]),
        model.Struct('FixcompDynamic', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'Builtin', bound = 'num_of_x')
        ]),
        model.Struct('FixcompLimited', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'Builtin', size = 2, bound = 'num_of_x')
        ]),
        model.Struct('FixcompGreedy', [
            model.StructMember('x', 'Builtin', unlimited = True)
        ])
    ])

@pytest.fixture
def Dyncomp():
    return process([
        model.Struct('BuiltinDynamic', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u32', bound = 'num_of_x')
        ]),
        model.Struct('Dyncomp', [
            model.StructMember('x', 'BuiltinDynamic')
        ]),
        model.Struct('DyncompDynamic', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'BuiltinDynamic', bound = 'num_of_x')
        ]),
        model.Struct('DyncompGreedy', [
            model.StructMember('x', 'BuiltinDynamic', unlimited = True)
        ])
    ])

@pytest.fixture
def Unions():
    return process([
        model.Struct('Builtin', [
            model.StructMember('x', 'u32'),
            model.StructMember('y', 'u32')
        ]),
        model.Union('Union', [
            model.UnionMember('a', 'u8', '1'),
            model.UnionMember('b', 'u32', '2'),
            model.UnionMember('c', 'Builtin', '3')
        ]),
        model.Struct('BuiltinOptional', [
            model.StructMember('x', 'u32', optional = True)
        ]),
        model.Struct('FixcompOptional', [
            model.StructMember('x', 'Builtin', optional = True)
        ])
    ])

@pytest.fixture
def Enums():
    return process([
        model.Enum('Enum', [
            model.EnumMember('Enum_One', '1'),
            model.EnumMember('Enum_Two', '2')
        ]),
        model.Struct('DynEnum', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'Enum', bound = 'num_of_x')
        ])
    ])

@pytest.fixture
def Floats():
    return process([
        model.Struct('Floats', [
            model.StructMember('a', 'r32'),
            model.StructMember('b', 'r64')
        ])
    ])

@pytest.fixture
def Bytes():
    return process([
        model.Struct('BytesFixed', [
            model.StructMember('x', 'byte', size = 3)
        ]),
        model.Struct('BytesDynamic', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'byte', bound = 'num_of_x')
        ]),
        model.Struct('BytesLimited', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'byte', size = 4, bound = 'num_of_x')
        ]),
        model.Struct('BytesGreedy', [
            model.StructMember('x', 'byte', unlimited = True)
        ])
    ])

@pytest.fixture
def Endpad():
    return process([
        model.Struct('Endpad', [
            model.StructMember('x', 'u16'),
            model.StructMember('y', 'u8')
        ]),
        model.Struct('EndpadFixed', [
            model.StructMember('x', 'u32'),
            model.StructMember('y', 'u8', size = 3)
        ]),
        model.Struct('EndpadDynamic', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u8', bound = 'num_of_x')
        ]),
        model.Struct('EndpadLimited', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u8', size = 2, bound = 'num_of_x')
        ]),
        model.Struct('EndpadGreedy', [
            model.StructMember('x', 'u32'),
            model.StructMember('y', 'u8', unlimited = True)
        ])
    ])

@pytest.fixture
def Scalarpad():
    return process([
        model.Struct('Scalarpad', [
            model.StructMember('x', 'u8'),
            model.StructMember('y', 'u16')
        ]),
        model.Struct('ScalarpadComppre_Helper', [
            model.StructMember('x', 'u8')
        ]),
        model.Struct('ScalarpadComppre', [
            model.StructMember('x', 'ScalarpadComppre_Helper'),
            model.StructMember('y', 'u16')
        ]),
        model.Struct('ScalarpadComppost_Helper', [
            model.StructMember('x', 'u16')
        ]),
        model.Struct('ScalarpadComppost', [
            model.StructMember('x', 'u8'),
            model.StructMember('y', 'ScalarpadComppost_Helper')
        ]),
    ])

@pytest.fixture
def Unionpad():
    return process([
        model.Struct('UnionpadOptionalboolpad', [
            model.StructMember('x', 'u8'),
            model.StructMember('y', 'u8', optional = True)
        ]),
        model.Struct('UnionpadOptionalvaluepad', [
            model.StructMember('x', 'u64', optional = True)
        ]),
        model.Union('UnionpadDiscpad_Helper', [
            model.UnionMember('a', 'u8', '1')
        ]),
        model.Struct('UnionpadDiscpad', [
            model.StructMember('x', 'u8'),
            model.StructMember('y', 'UnionpadDiscpad_Helper')
        ]),
        model.Union('UnionpadArmpad_Helper', [
            model.UnionMember('a', 'u8', '1'),
            model.UnionMember('b', 'u64', '2')
        ]),
        model.Struct('UnionpadArmpad', [
            model.StructMember('x', 'u8'),
            model.StructMember('y', 'UnionpadArmpad_Helper')
        ])
    ])

@pytest.fixture
def Arraypad():
    return process([
        model.Struct('ArraypadCounter', [
            model.StructMember('num_of_x', 'u8'),
            model.StructMember('x', 'u16', bound = 'num_of_x')
        ]),
        model.Struct('ArraypadCounterSeparated', [
            model.StructMember('num_of_x', 'u8'),
            model.StructMember('y', 'u32'),
            model.StructMember('x', 'u32', bound = 'num_of_x')
        ]),
        model.Struct('ArraypadCounterAligns_Helper', [
            model.StructMember('num_of_x', 'u16'),
            model.StructMember('x', 'u8', bound = 'num_of_x')
        ]),
        model.Struct('ArraypadCounterAligns', [
            model.StructMember('x', 'u8'),
            model.StructMember('y', 'ArraypadCounterAligns_Helper')
        ]),
        model.Struct('ArraypadFixed', [
            model.StructMember('x', 'u32'),
            model.StructMember('y', 'u8', size = 3),
            model.StructMember('z', 'u32')
        ]),
        model.Struct('ArraypadDynamic', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u8', bound = 'num_of_x'),
            model.StructMember('y', 'u32')
        ]),
        model.Struct('ArraypadLimited', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u8', size = 2, bound = 'num_of_x'),
            model.StructMember('y', 'u32')
        ])
    ])

@pytest.fixture
def Dynfields():
    return process([
        model.Struct('Dynfields', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u8', bound = 'num_of_x'),
            model.StructMember('num_of_y', 'u16'),
            model.StructMember('y', 'u16', bound = 'num_of_y'),
            model.StructMember('z', 'u64')
        ]),
        model.Struct('DynfieldsMixed', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('num_of_y', 'u16'),
            model.StructMember('x', 'u8', bound = 'num_of_x'),
            model.StructMember('y', 'u16', bound = 'num_of_y')
        ]),
        model.Struct('DynfieldsOverlapped', [
            model.StructMember('num_of_a', 'u32'),
            model.StructMember('num_of_b', 'u32'),
            model.StructMember('b', 'u16', bound = 'num_of_b'),
            model.StructMember('num_of_c', 'u32'),
            model.StructMember('c', 'u16', bound = 'num_of_c'),
            model.StructMember('a', 'u16', bound = 'num_of_a')
        ]),
        model.Struct('DynfieldsPartialpad_Helper', [
            model.StructMember('num_of_x', 'u8'),
            model.StructMember('x', 'u8', bound = 'num_of_x'),
            model.StructMember('y', 'u8'),
            model.StructMember('z', 'u64')
        ]),
        model.Struct('DynfieldsPartialpad', [
            model.StructMember('x', 'u8'),
            model.StructMember('y', 'DynfieldsPartialpad_Helper')
        ]),
        model.Struct('DynfieldsScalarpartialpad_Helper', [
            model.StructMember('num_of_x', 'u32'),
            model.StructMember('x', 'u8', bound = 'num_of_x')
        ]),
        model.Struct('DynfieldsScalarpartialpad', [
            model.StructMember('x', 'DynfieldsScalarpartialpad_Helper'),
            model.StructMember('y', 'DynfieldsScalarpartialpad_Helper'),
            model.StructMember('z', 'DynfieldsScalarpartialpad_Helper')
        ])
    ])

def test_generate_builtin_encode(Builtin):
    assert generate_struct_encode(Builtin[0]) == """\
pos = do_encode<E>(pos, x.x);
pos = do_encode<E>(pos, x.y);
"""
    assert generate_struct_encode(Builtin[1]) == """\
pos = do_encode<E>(pos, x.x, 2);
"""
    assert generate_struct_encode(Builtin[2]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
"""
    assert generate_struct_encode(Builtin[3]) == """\
pos = do_encode<E>(pos, uint32_t(std::min(x.x.size(), size_t(2))));
do_encode<E>(pos, x.x.data(), uint32_t(std::min(x.x.size(), size_t(2))));
pos = pos + 8;
"""
    assert generate_struct_encode(Builtin[4]) == """\
pos = do_encode<E>(pos, x.x.data(), x.x.size());
"""

def test_generate_fixcomp_encode(Fixcomp):
    assert generate_struct_encode(Fixcomp[1]) == """\
pos = do_encode<E>(pos, x.x);
pos = do_encode<E>(pos, x.y);
"""
    assert generate_struct_encode(Fixcomp[2]) == """\
pos = do_encode<E>(pos, x.x, 2);
"""
    assert generate_struct_encode(Fixcomp[3]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
"""
    assert generate_struct_encode(Fixcomp[4]) == """\
pos = do_encode<E>(pos, uint32_t(std::min(x.x.size(), size_t(2))));
do_encode<E>(pos, x.x.data(), uint32_t(std::min(x.x.size(), size_t(2))));
pos = pos + 16;
"""
    assert generate_struct_encode(Fixcomp[5]) == """\
pos = do_encode<E>(pos, x.x.data(), x.x.size());
"""

def test_generate_dyncomp_encode(Dyncomp):
    assert generate_struct_encode(Dyncomp[1]) == """\
pos = do_encode<E>(pos, x.x);
"""
    assert generate_struct_encode(Dyncomp[2]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
"""
    assert generate_struct_encode(Dyncomp[3]) == """\
pos = do_encode<E>(pos, x.x.data(), x.x.size());
"""

def test_generate_unions_encode(Unions):
    assert generate_union_encode(Unions[1]) == """\
pos = do_encode<E>(pos, x.discriminator);
switch (x.discriminator)
{
    case Union::discriminator_a: do_encode<E>(pos, x.a); break;
    case Union::discriminator_b: do_encode<E>(pos, x.b); break;
    case Union::discriminator_c: do_encode<E>(pos, x.c); break;
}
pos = pos + 8;
"""
    assert generate_struct_encode(Unions[2]) == """\
pos = do_encode<E>(pos, x.has_x);
if (x.has_x) do_encode<E>(pos, x.x);
pos = pos + 4;
"""
    assert generate_struct_encode(Unions[3]) == """\
pos = do_encode<E>(pos, x.has_x);
if (x.has_x) do_encode<E>(pos, x.x);
pos = pos + 8;
"""

def test_generate_enums_encode(Enums):
    assert generate_struct_encode(Enums[1]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
"""

def test_generate_floats_encode(Floats):
    assert generate_struct_encode(Floats[0]) == """\
pos = do_encode<E>(pos, x.a);
pos = pos + 4;
pos = do_encode<E>(pos, x.b);
"""

def test_generate_bytes_encode(Bytes):
    assert generate_struct_encode(Bytes[0]) == """\
pos = do_encode<E>(pos, x.x, 3);
"""
    assert generate_struct_encode(Bytes[1]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
pos = align<4>(pos);
"""
    assert generate_struct_encode(Bytes[2]) == """\
pos = do_encode<E>(pos, uint32_t(std::min(x.x.size(), size_t(4))));
do_encode<E>(pos, x.x.data(), uint32_t(std::min(x.x.size(), size_t(4))));
pos = pos + 4;
"""
    assert generate_struct_encode(Bytes[3]) == """\
pos = do_encode<E>(pos, x.x.data(), x.x.size());
"""

def test_generate_endpad_encode(Endpad):
    assert generate_struct_encode(Endpad[0]) == """\
pos = do_encode<E>(pos, x.x);
pos = do_encode<E>(pos, x.y);
pos = pos + 1;
"""
    assert generate_struct_encode(Endpad[1]) == """\
pos = do_encode<E>(pos, x.x);
pos = do_encode<E>(pos, x.y, 3);
pos = pos + 1;
"""
    assert generate_struct_encode(Endpad[2]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
pos = align<4>(pos);
"""
    assert generate_struct_encode(Endpad[3]) == """\
pos = do_encode<E>(pos, uint32_t(std::min(x.x.size(), size_t(2))));
do_encode<E>(pos, x.x.data(), uint32_t(std::min(x.x.size(), size_t(2))));
pos = pos + 2;
pos = pos + 2;
"""
    assert generate_struct_encode(Endpad[4]) == """\
pos = do_encode<E>(pos, x.x);
pos = do_encode<E>(pos, x.y.data(), x.y.size());
pos = align<4>(pos);
"""

def test_generate_scalarpad_encode(Scalarpad):
    assert generate_struct_encode(Scalarpad[0]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 1;
pos = do_encode<E>(pos, x.y);
"""
    assert generate_struct_encode(Scalarpad[2]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 1;
pos = do_encode<E>(pos, x.y);
"""
    assert generate_struct_encode(Scalarpad[4]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 1;
pos = do_encode<E>(pos, x.y);
"""

def test_generate_unionpad_encode(Unionpad):
    assert generate_struct_encode(Unionpad[0]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 3;
pos = do_encode<E>(pos, x.has_y);
if (x.has_y) do_encode<E>(pos, x.y);
pos = pos + 1;
pos = pos + 3;
"""
    assert generate_struct_encode(Unionpad[1]) == """\
pos = do_encode<E>(pos, x.has_x);
pos = pos + 4;
if (x.has_x) do_encode<E>(pos, x.x);
pos = pos + 8;
"""
    assert generate_union_encode(Unionpad[2]) == """\
pos = do_encode<E>(pos, x.discriminator);
switch (x.discriminator)
{
    case UnionpadDiscpad_Helper::discriminator_a: do_encode<E>(pos, x.a); break;
}
pos = pos + 4;
"""
    assert generate_struct_encode(Unionpad[3]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 3;
pos = do_encode<E>(pos, x.y);
"""
    assert generate_union_encode(Unionpad[4]) == """\
pos = do_encode<E>(pos, x.discriminator);
pos = pos + 4;
switch (x.discriminator)
{
    case UnionpadArmpad_Helper::discriminator_a: do_encode<E>(pos, x.a); break;
    case UnionpadArmpad_Helper::discriminator_b: do_encode<E>(pos, x.b); break;
}
pos = pos + 8;
"""
    assert generate_struct_encode(Unionpad[5]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 7;
pos = do_encode<E>(pos, x.y);
"""

def test_generate_arraypad_encode(Arraypad):
    assert generate_struct_encode(Arraypad[0]) == """\
pos = do_encode<E>(pos, uint8_t(x.x.size()));
pos = pos + 1;
pos = do_encode<E>(pos, x.x.data(), uint8_t(x.x.size()));
"""
    assert generate_struct_encode(Arraypad[1]) == """\
pos = do_encode<E>(pos, uint8_t(x.x.size()));
pos = pos + 3;
pos = do_encode<E>(pos, x.y);
pos = do_encode<E>(pos, x.x.data(), uint8_t(x.x.size()));
"""
    assert generate_struct_encode(Arraypad[2]) == """\
pos = do_encode<E>(pos, uint16_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint16_t(x.x.size()));
pos = align<2>(pos);
"""
    assert generate_struct_encode(Arraypad[3]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 1;
pos = do_encode<E>(pos, x.y);
"""
    assert generate_struct_encode(Arraypad[4]) == """\
pos = do_encode<E>(pos, x.x);
pos = do_encode<E>(pos, x.y, 3);
pos = pos + 1;
pos = do_encode<E>(pos, x.z);
"""
    assert generate_struct_encode(Arraypad[5]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
pos = align<4>(pos);
pos = do_encode<E>(pos, x.y);
"""
    assert generate_struct_encode(Arraypad[6]) == """\
pos = do_encode<E>(pos, uint32_t(std::min(x.x.size(), size_t(2))));
do_encode<E>(pos, x.x.data(), uint32_t(std::min(x.x.size(), size_t(2))));
pos = pos + 2;
pos = pos + 2;
pos = do_encode<E>(pos, x.y);
"""

def test_generate_dynfields_encode(Dynfields):
    assert generate_struct_encode(Dynfields[0]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
pos = align<2>(pos);
pos = do_encode<E>(pos, uint16_t(x.y.size()));
pos = do_encode<E>(pos, x.y.data(), uint16_t(x.y.size()));
pos = align<8>(pos);
pos = do_encode<E>(pos, x.z);
"""
    assert generate_struct_encode(Dynfields[1]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, uint16_t(x.y.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
pos = align<2>(pos);
pos = do_encode<E>(pos, x.y.data(), uint16_t(x.y.size()));
pos = align<4>(pos);
"""
    assert generate_struct_encode(Dynfields[2]) == """\
pos = do_encode<E>(pos, uint32_t(x.a.size()));
pos = do_encode<E>(pos, uint32_t(x.b.size()));
pos = do_encode<E>(pos, x.b.data(), uint32_t(x.b.size()));
pos = align<4>(pos);
pos = do_encode<E>(pos, uint32_t(x.c.size()));
pos = do_encode<E>(pos, x.c.data(), uint32_t(x.c.size()));
pos = do_encode<E>(pos, x.a.data(), uint32_t(x.a.size()));
pos = align<4>(pos);
"""
    assert generate_struct_encode(Dynfields[3]) == """\
pos = do_encode<E>(pos, uint8_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint8_t(x.x.size()));
pos = align<8>(pos);
pos = do_encode<E>(pos, x.y);
pos = pos + 7;
pos = do_encode<E>(pos, x.z);
"""
    assert generate_struct_encode(Dynfields[4]) == """\
pos = do_encode<E>(pos, x.x);
pos = pos + 7;
pos = do_encode<E>(pos, x.y);
"""
    assert generate_struct_encode(Dynfields[5]) == """\
pos = do_encode<E>(pos, uint32_t(x.x.size()));
pos = do_encode<E>(pos, x.x.data(), uint32_t(x.x.size()));
pos = align<4>(pos);
"""
    assert generate_struct_encode(Dynfields[6]) == """\
pos = do_encode<E>(pos, x.x);
pos = do_encode<E>(pos, x.y);
pos = do_encode<E>(pos, x.z);
"""

def test_generate_builtin_decode(Builtin):
    assert generate_struct_decode(Builtin[0]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_struct_decode(Builtin[1]) == """\
do_decode<E>(x.x, 2, pos, end)
"""
    assert generate_struct_decode(Builtin[2]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end)
"""
    assert generate_struct_decode(Builtin[3]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end, 2) &&
do_decode_in_place<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_advance(8, pos, end)
"""
    assert generate_struct_decode(Builtin[4]) == """\
do_decode_greedy<E>(x.x, pos, end)
"""

def test_generate_fixcomp_decode(Fixcomp):
    assert generate_struct_decode(Fixcomp[1]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_struct_decode(Fixcomp[2]) == """\
do_decode<E>(x.x, 2, pos, end)
"""
    assert generate_struct_decode(Fixcomp[3]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end)
"""
    assert generate_struct_decode(Fixcomp[4]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end, 2) &&
do_decode_in_place<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_advance(16, pos, end)
"""
    assert generate_struct_decode(Fixcomp[5]) == """\
do_decode_greedy<E>(x.x, pos, end)
"""

def test_generate_dyncomp_decode(Dyncomp):
    assert generate_struct_decode(Dyncomp[1]) == """\
do_decode<E>(x.x, pos, end)
"""
    assert generate_struct_decode(Dyncomp[2]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end)
"""
    assert generate_struct_decode(Dyncomp[3]) == """\
do_decode_greedy<E>(x.x, pos, end)
"""

def test_generate_unions_decode(Unions):
    assert generate_union_decode(Unions[1]) == """\
if (!do_decode<E>(x.discriminator, pos, end)) return false;
switch (x.discriminator)
{
    case Union::discriminator_a: if (!do_decode_in_place<E>(x.a, pos, end)) return false; break;
    case Union::discriminator_b: if (!do_decode_in_place<E>(x.b, pos, end)) return false; break;
    case Union::discriminator_c: if (!do_decode_in_place<E>(x.c, pos, end)) return false; break;
    default: return false;
}
return do_decode_advance(8, pos, end);
"""
    assert generate_struct_decode(Unions[2]) == """\
do_decode<E>(x.has_x, pos, end) &&
do_decode_in_place_optional<E>(x.x, x.has_x, pos, end) &&
do_decode_advance(4, pos, end)
"""
    assert generate_struct_decode(Unions[3]) == """\
do_decode<E>(x.has_x, pos, end) &&
do_decode_in_place_optional<E>(x.x, x.has_x, pos, end) &&
do_decode_advance(8, pos, end)
"""

def test_generate_enums_decode(Enums):
    assert generate_struct_decode(Enums[1]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end)
"""

def test_generate_floats_decode(Floats):
    assert generate_struct_decode(Floats[0]) == """\
do_decode<E>(x.a, pos, end) &&
do_decode_advance(4, pos, end) &&
do_decode<E>(x.b, pos, end)
"""

def test_generate_bytes_decode(Bytes):
    assert generate_struct_decode(Bytes[0]) == """\
do_decode<E>(x.x, 3, pos, end)
"""
    assert generate_struct_decode(Bytes[1]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<4>(pos, end)
"""
    assert generate_struct_decode(Bytes[2]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end, 4) &&
do_decode_in_place<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_advance(4, pos, end)
"""
    assert generate_struct_decode(Bytes[3]) == """\
do_decode_greedy<E>(x.x, pos, end)
"""

def test_generate_endpad_decode(Endpad):
    assert generate_struct_decode(Endpad[0]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode<E>(x.y, pos, end) &&
do_decode_advance(1, pos, end)
"""
    assert generate_struct_decode(Endpad[1]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode<E>(x.y, 3, pos, end) &&
do_decode_advance(1, pos, end)
"""
    assert generate_struct_decode(Endpad[2]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<4>(pos, end)
"""
    assert generate_struct_decode(Endpad[3]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end, 2) &&
do_decode_in_place<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_advance(2, pos, end) &&
do_decode_advance(2, pos, end)
"""
    assert generate_struct_decode(Endpad[4]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_greedy<E>(x.y, pos, end) &&
do_decode_align<4>(pos, end)
"""

def test_generate_scalarpad_decode(Scalarpad):
    assert generate_struct_decode(Scalarpad[0]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(1, pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_struct_decode(Scalarpad[2]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(1, pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_struct_decode(Scalarpad[4]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(1, pos, end) &&
do_decode<E>(x.y, pos, end)
"""

def test_generate_unionpad_decode(Unionpad):
    assert generate_struct_decode(Unionpad[0]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(3, pos, end) &&
do_decode<E>(x.has_y, pos, end) &&
do_decode_in_place_optional<E>(x.y, x.has_y, pos, end) &&
do_decode_advance(1, pos, end) &&
do_decode_advance(3, pos, end)
"""
    assert generate_struct_decode(Unionpad[1]) == """\
do_decode<E>(x.has_x, pos, end) &&
do_decode_advance(4, pos, end) &&
do_decode_in_place_optional<E>(x.x, x.has_x, pos, end) &&
do_decode_advance(8, pos, end)
"""
    assert generate_union_decode(Unionpad[2]) == """\
if (!do_decode<E>(x.discriminator, pos, end)) return false;
switch (x.discriminator)
{
    case UnionpadDiscpad_Helper::discriminator_a: if (!do_decode_in_place<E>(x.a, pos, end)) return false; break;
    default: return false;
}
return do_decode_advance(4, pos, end);
"""
    assert generate_struct_decode(Unionpad[3]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(3, pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_union_decode(Unionpad[4]) == """\
if (!do_decode<E>(x.discriminator, pos, end)) return false;
if (!do_decode_advance(4, pos, end)) return false;
switch (x.discriminator)
{
    case UnionpadArmpad_Helper::discriminator_a: if (!do_decode_in_place<E>(x.a, pos, end)) return false; break;
    case UnionpadArmpad_Helper::discriminator_b: if (!do_decode_in_place<E>(x.b, pos, end)) return false; break;
    default: return false;
}
return do_decode_advance(8, pos, end);
"""
    assert generate_struct_decode(Unionpad[5]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(7, pos, end) &&
do_decode<E>(x.y, pos, end)
"""

def test_generate_arraypad_decode(Arraypad):
    assert generate_struct_decode(Arraypad[0]) == """\
do_decode_resize<E, uint8_t>(x.x, pos, end) &&
do_decode_advance(1, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end)
"""
    assert generate_struct_decode(Arraypad[1]) == """\
do_decode_resize<E, uint8_t>(x.x, pos, end) &&
do_decode_advance(3, pos, end) &&
do_decode<E>(x.y, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end)
"""
    assert generate_struct_decode(Arraypad[2]) == """\
do_decode_resize<E, uint16_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<2>(pos, end)
"""
    assert generate_struct_decode(Arraypad[3]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(1, pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_struct_decode(Arraypad[4]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode<E>(x.y, 3, pos, end) &&
do_decode_advance(1, pos, end) &&
do_decode<E>(x.z, pos, end)
"""
    assert generate_struct_decode(Arraypad[5]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<4>(pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_struct_decode(Arraypad[6]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end, 2) &&
do_decode_in_place<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_advance(2, pos, end) &&
do_decode_advance(2, pos, end) &&
do_decode<E>(x.y, pos, end)
"""

def test_generate_dynfields_decode(Dynfields):
    assert generate_struct_decode(Dynfields[0]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<2>(pos, end) &&
do_decode_resize<E, uint16_t>(x.y, pos, end) &&
do_decode<E>(x.y.data(), x.y.size(), pos, end) &&
do_decode_align<8>(pos, end) &&
do_decode<E>(x.z, pos, end)
"""
    assert generate_struct_decode(Dynfields[1]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode_resize<E, uint16_t>(x.y, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<2>(pos, end) &&
do_decode<E>(x.y.data(), x.y.size(), pos, end) &&
do_decode_align<4>(pos, end)
"""
    assert generate_struct_decode(Dynfields[2]) == """\
do_decode_resize<E, uint32_t>(x.a, pos, end) &&
do_decode_resize<E, uint32_t>(x.b, pos, end) &&
do_decode<E>(x.b.data(), x.b.size(), pos, end) &&
do_decode_align<4>(pos, end) &&
do_decode_resize<E, uint32_t>(x.c, pos, end) &&
do_decode<E>(x.c.data(), x.c.size(), pos, end) &&
do_decode<E>(x.a.data(), x.a.size(), pos, end) &&
do_decode_align<4>(pos, end)
"""
    assert generate_struct_decode(Dynfields[3]) == """\
do_decode_resize<E, uint8_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<8>(pos, end) &&
do_decode<E>(x.y, pos, end) &&
do_decode_advance(7, pos, end) &&
do_decode<E>(x.z, pos, end)
"""
    assert generate_struct_decode(Dynfields[4]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode_advance(7, pos, end) &&
do_decode<E>(x.y, pos, end)
"""
    assert generate_struct_decode(Dynfields[5]) == """\
do_decode_resize<E, uint32_t>(x.x, pos, end) &&
do_decode<E>(x.x.data(), x.x.size(), pos, end) &&
do_decode_align<4>(pos, end)
"""
    assert generate_struct_decode(Dynfields[6]) == """\
do_decode<E>(x.x, pos, end) &&
do_decode<E>(x.y, pos, end) &&
do_decode<E>(x.z, pos, end)
"""

def test_generate_builtin_print(Builtin):
    assert generate_struct_print(Builtin[0]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y);
"""
    assert generate_struct_print(Builtin[1]) == """\
do_print(out, indent, "x", x.x, size_t(2));
"""
    assert generate_struct_print(Builtin[2]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""
    assert generate_struct_print(Builtin[3]) == """\
do_print(out, indent, "x", x.x.data(), std::min(x.x.size(), size_t(2)));
"""
    assert generate_struct_print(Builtin[4]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""

def test_generate_fixcomp_print(Fixcomp):
    assert generate_struct_print(Fixcomp[1]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y);
"""
    assert generate_struct_print(Fixcomp[2]) == """\
do_print(out, indent, "x", x.x, size_t(2));
"""
    assert generate_struct_print(Fixcomp[3]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""
    assert generate_struct_print(Fixcomp[4]) == """\
do_print(out, indent, "x", x.x.data(), std::min(x.x.size(), size_t(2)));
"""
    assert generate_struct_print(Fixcomp[5]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""

def test_generate_dyncomp_print(Dyncomp):
    assert generate_struct_print(Dyncomp[1]) == """\
do_print(out, indent, "x", x.x);
"""
    assert generate_struct_print(Dyncomp[2]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""
    assert generate_struct_print(Dyncomp[3]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""

def test_generate_unions_print(Unions):
    assert generate_union_print(Unions[1]) == """\
switch (x.discriminator)
{
    case Union::discriminator_a: do_print(out, indent, "a", x.a); break;
    case Union::discriminator_b: do_print(out, indent, "b", x.b); break;
    case Union::discriminator_c: do_print(out, indent, "c", x.c); break;
}
"""
    assert generate_struct_print(Unions[2]) == """\
if (x.has_x) do_print(out, indent, "x", x.x);
"""
    assert generate_struct_print(Unions[3]) == """\
if (x.has_x) do_print(out, indent, "x", x.x);
"""

def test_generate_enums_print(Enums):
    assert generate_struct_print(Enums[1]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""

def test_generate_floats_print(Floats):
    assert generate_struct_print(Floats[0]) == """\
do_print(out, indent, "a", x.a);
do_print(out, indent, "b", x.b);
"""

def test_generate_bytes_print(Bytes):
    assert generate_struct_print(Bytes[0]) == """\
do_print(out, indent, "x", std::make_pair(x.x, size_t(3)));
"""
    assert generate_struct_print(Bytes[1]) == """\
do_print(out, indent, "x", std::make_pair(x.x.data(), x.x.size()));
"""
    assert generate_struct_print(Bytes[2]) == """\
do_print(out, indent, "x", std::make_pair(x.x.data(), std::min(x.x.size(), size_t(4))));
"""
    assert generate_struct_print(Bytes[3]) == """\
do_print(out, indent, "x", std::make_pair(x.x.data(), x.x.size()));
"""

def test_generate_endpad_print(Endpad):
    assert generate_struct_print(Endpad[0]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y);
"""
    assert generate_struct_print(Endpad[1]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y, size_t(3));
"""
    assert generate_struct_print(Endpad[2]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""
    assert generate_struct_print(Endpad[3]) == """\
do_print(out, indent, "x", x.x.data(), std::min(x.x.size(), size_t(2)));
"""
    assert generate_struct_print(Endpad[4]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y.data(), x.y.size());
"""

def test_generate_scalarpad_print(Scalarpad):
    assert generate_struct_print(Scalarpad[0]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y);
"""
    assert generate_struct_print(Scalarpad[2]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y);
"""
    assert generate_struct_print(Scalarpad[4]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y);
"""

def test_generate_unionpad_print(Unionpad):
    assert generate_struct_print(Unionpad[0]) == """\
do_print(out, indent, "x", x.x);
if (x.has_y) do_print(out, indent, "y", x.y);
"""
    assert generate_struct_print(Unionpad[1]) == """\
if (x.has_x) do_print(out, indent, "x", x.x);
"""
    assert generate_union_print(Unionpad[2]) == """\
switch (x.discriminator)
{
    case UnionpadDiscpad_Helper::discriminator_a: do_print(out, indent, "a", x.a); break;
}
"""
    assert generate_struct_print(Unionpad[3]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y);
"""
    assert generate_union_print(Unionpad[4]) == """\
switch (x.discriminator)
{
    case UnionpadArmpad_Helper::discriminator_a: do_print(out, indent, "a", x.a); break;
    case UnionpadArmpad_Helper::discriminator_b: do_print(out, indent, "b", x.b); break;
}
"""
    assert generate_struct_print(Unionpad[5]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y);
"""

def test_generate_arraypad_print(Arraypad):
    assert generate_struct_print(Arraypad[0]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""
    assert generate_struct_print(Arraypad[1]) == """\
do_print(out, indent, "y", x.y);
do_print(out, indent, "x", x.x.data(), x.x.size());
"""
    assert generate_struct_print(Arraypad[2]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""
    assert generate_struct_print(Arraypad[3]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y);
"""
    assert generate_struct_print(Arraypad[4]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y, size_t(3));
do_print(out, indent, "z", x.z);
"""
    assert generate_struct_print(Arraypad[5]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
do_print(out, indent, "y", x.y);
"""
    assert generate_struct_print(Arraypad[6]) == """\
do_print(out, indent, "x", x.x.data(), std::min(x.x.size(), size_t(2)));
do_print(out, indent, "y", x.y);
"""

def test_generate_dynfields_print(Dynfields):
    assert generate_struct_print(Dynfields[0]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
do_print(out, indent, "y", x.y.data(), x.y.size());
do_print(out, indent, "z", x.z);
"""
    assert generate_struct_print(Dynfields[1]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
do_print(out, indent, "y", x.y.data(), x.y.size());
"""
    assert generate_struct_print(Dynfields[2]) == """\
do_print(out, indent, "b", x.b.data(), x.b.size());
do_print(out, indent, "c", x.c.data(), x.c.size());
do_print(out, indent, "a", x.a.data(), x.a.size());
"""
    assert generate_struct_print(Dynfields[3]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
do_print(out, indent, "y", x.y);
do_print(out, indent, "z", x.z);
"""
    assert generate_struct_print(Dynfields[4]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y);
"""
    assert generate_struct_print(Dynfields[5]) == """\
do_print(out, indent, "x", x.x.data(), x.x.size());
"""
    assert generate_struct_print(Dynfields[6]) == """\
do_print(out, indent, "x", x.x);
do_print(out, indent, "y", x.y);
do_print(out, indent, "z", x.z);
"""
{'fraction_non_alphanumeric': 0.2132678343812211, 'fraction_numerical': 0.01606920355756699, 'mean_word_length': 3.9977811180302054, 'pattern_counts': {'":': 0, '<': 503, '<?xml version=': 0, '>': 503, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2260649', 'n_tokens_mistral': 27368, 'n_tokens_neox': 26874, 'n_words': 4350}