/**
* Define the write method.
*/
private void defineWriteMethod()
{
MethodDefinition write = new MethodDefinition(
a(PUBLIC),
"write",
null,
arg("struct", structType),
arg("protocol", TProtocol.class)
);
classDefinition.addMethod(write);
// TProtocolReader reader = new TProtocolReader(protocol);
write.addLocalVariable(type(TProtocolWriter.class), "writer");
write.newObject(TProtocolWriter.class);
write.dup();
write.loadVariable("protocol");
write.invokeConstructor(type(TProtocolWriter.class), type(TProtocol.class));
write.storeVariable("writer");
LocalVariableDefinition protocol = write.getLocalVariable("writer");
// protocol.writeStructBegin("bonk");
write.loadVariable(protocol)
.loadConstant(metadata.getStructName())
.invokeVirtual(TProtocolWriter.class, "writeStructBegin", void.class, String.class);
// write fields
for (ThriftFieldMetadata field : metadata.getFields()) {
// push protocol
write.loadVariable(protocol);
// push (String) field.name
write.loadConstant(field.getName());
// push (short) field.id
write.loadConstant(field.getId());
// push ThriftTypeCodec for this field
FieldDefinition codecField = codecFields.get(field.getId());
if (codecField != null) {
write.loadThis().getField(codecType, codecField);
}
// push field value
loadFieldValue(write, field);
// if field value is null, don't coerce or write the field
if (!isFieldTypeJavaPrimitive(field)) {
// ifNullGoto consumes the top of the stack, so we need to duplicate the value
write.dup();
write.ifNullGoto("field_is_null_" + field.getName());
}
// coerce value
if (field.getCoercion() != null) {
write.invokeStatic(field.getCoercion().getToThrift());
// if coerced value is null, don't write the field
if (!isProtocolTypeJavaPrimitive(field)) {
write.dup();
write.ifNullGoto("field_is_null_" + field.getName());
}
}
// write value
Method writeMethod = WRITE_METHODS.get(field.getType().getProtocolType());
if (writeMethod == null) {
throw new IllegalArgumentException(
"Unsupported field type " + field.getType().getProtocolType()
);
}
write.invokeVirtual(writeMethod);
//
// If not written because of a null, clean-up the stack
if (!isProtocolTypeJavaPrimitive(field) || !isFieldTypeJavaPrimitive(field)) {
// value was written so skip cleanup
write.gotoLabel("field_end_" + field.getName());
// cleanup stack for null field value
write.visitLabel("field_is_null_" + field.getName());
// pop value
write.pop();
// pop codec
if (codecField != null) {
write.pop();
}
// pop id
write.pop();
// pop name
write.pop();
// pop protocol
write.pop();
write.visitLabel("field_end_" + field.getName());
}
}
write.loadVariable(protocol)
.invokeVirtual(TProtocolWriter.class, "writeStructEnd", void.class);
write.ret();
}