Firstly, a keyless type that is a use as a key field needs to be treated as-if all fields are key fields. It wasn't serializing all of these.
Secondly, the serializer in the Cyclone core sets the must-understand bit on fields actually used as key fields (not all implementations make this choice, the spec is ambiguous), but the Python one did not consistently do so: in a non-key field of an inner struct itself containing fields marked as keys, and in a key field of an inner type struct containing no key fields it would deviate. That leads to fuzzing failures.
It also changes the encoding used for strings in mutable data (not a correctness issue):
This change brings it in line with the encoding chosen by the C serializer, and happens to reduce the size of the serialized data. There is no change in meaning or correctness, it is simply that generating exactly the same as C makes some types pass the fuzzer test.
And finally cleans up some details in the type fuzzer.
This primarily addresses two issues:
Firstly, a keyless type that is a use as a key field needs to be treated as-if all fields are key fields. It wasn't serializing all of these.
Secondly, the serializer in the Cyclone core sets the must-understand bit on fields actually used as key fields (not all implementations make this choice, the spec is ambiguous), but the Python one did not consistently do so: in a non-key field of an inner struct itself containing fields marked as keys, and in a key field of an inner type struct containing no key fields it would deviate. That leads to fuzzing failures.
It also changes the encoding used for strings in mutable data (not a correctness issue):
And finally cleans up some details in the type fuzzer.