Question

Thrift File:
struct Sub {
1: required i32 number
}

struct Message {
1: required Sub sub
}

Message m;
m.write(protocol.get());
Message parsedM;
parsedM.read(protocol2.get());
std::cout << parsedM.sub.number;

SourceCode

Should not Thrift raise an error or is there any other possibiliy to properly check if all required field have been set? Otherwise I see no real point in that keyword.

Was it helpful?

Solution

Short answer

Yes, you should get a TProtocolException::INVALID_DATA if the data are not present while deserializing. That's not the case in your example, so you don't get the exception.

Long answer

This is one of the generated C++ read() methods based on your IDL. Watch out for isset_number and how it is used:

uint32_t Sub::read(::apache::thrift::protocol::TProtocol* iprot) {

  uint32_t xfer = 0;
  std::string fname;
  ::apache::thrift::protocol::TType ftype;
  int16_t fid;

  xfer += iprot->readStructBegin(fname);

  using ::apache::thrift::protocol::TProtocolException;

  bool isset_number = false;

  while (true)
  {
    xfer += iprot->readFieldBegin(fname, ftype, fid);
    if (ftype == ::apache::thrift::protocol::T_STOP) {
      break;
    }
    switch (fid)
    {
      case 1:
        if (ftype == ::apache::thrift::protocol::T_I32) {
          xfer += iprot->readI32(this->number);
          isset_number = true;
        } else {
          xfer += iprot->skip(ftype);
        }
        break;
      default:
        xfer += iprot->skip(ftype);
        break;
    }
    xfer += iprot->readFieldEnd();
  }

  xfer += iprot->readStructEnd();

  if (!isset_number)
    throw TProtocolException(TProtocolException::INVALID_DATA);
  return xfer;
}

So why does it work in your example?

As we have seen, required fields are expected to be present in the deserialized data, while optional (and default) fields may be missing. But fields marked required (and default fields) are also always written to the transport, optional only when a value has been assigned. Hence you read the data that you serialized before:

uint32_t Sub::write(::apache::thrift::protocol::TProtocol* oprot) const {
  uint32_t xfer = 0;
  xfer += oprot->writeStructBegin("Sub");

  xfer += oprot->writeFieldBegin("number", ::apache::thrift::protocol::T_I32, 1);
  xfer += oprot->writeI32(this->number);
  xfer += oprot->writeFieldEnd();

  xfer += oprot->writeFieldStop();
  xfer += oprot->writeStructEnd();
  return xfer;
}

Note that Thrift does not care about whether the field contains valid data. It's all about the serializing aspect.

Recommended reading

Diwaker Gupta's "Missing Guide" explains the pros ands cons of required quite good.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top