code: @SuppressWarnings("unchecked")
    public <F extends TFieldIdEnum> Message doConvert(TBase<?, F> thriftObj) {
      if (thriftObj == null) { return null; }
  
      Class<TBase<?, F>> clazz = (Class<TBase<?, F>>) thriftObj.getClass();
      checkState(clazz);
  
      Message.Builder builder = getBuilder(clazz);
  
      TStructDescriptor fieldDesc = TStructDescriptor.getInstance(clazz);
      int fieldId = 0;
      for (Field tField : fieldDesc.getFields()) {
        // don't want to carry over default values from unset fields
        if (!thriftObj.isSet((F) tField.getFieldIdEnum())
            || (!supportNestedObjects && hasNestedObject(tField))) {
          fieldId++;
          continue;
        }
  
        // recurse into the object if it's a struct, otherwise just add the field
        if (supportNestedObjects && tField.getType() == TType.STRUCT) {
          TBase<?, ?> fieldValue = (TBase<?, ?>) fieldDesc.getFieldValue(fieldId++, thriftObj);
          Message message = doConvert(fieldValue);
          if (message != null) {
            FieldDescriptor protoFieldDesc = builder.getDescriptorForType().findFieldByName(
                tField.getName());
            builder.setField(protoFieldDesc, message);
          }
        } else {
          fieldId = convertField(thriftObj, builder, fieldDesc, fieldId, tField);
        }
      }
      return builder.build();
    }
docs: conver TBase object to Message object
  @param thriftObj