I was able to get it loading and saving correctly by creating an alternate UDT that used integer type instead of enum. I copied the UDT with enums into the one without enums before save, then back into the UDT with enums after loading.

So in the end, load and save work without enums but not with. And you can copy an array of UDTs from it's enum version back to it's non-enum version and vice versa with a simple assignment: udt() = xudt() or xudt() = udt().

Only problem I see now is that it saves subtypes that are empty. I wonder how it will react with the sub-arrays of different sizes.

Still, it's probably more memory efficient than xml.

Next problem would be to make a packer/unpacker. It doesn't look like there are any non-complex general solutions for that.