Google Protobuf ByteString vs. Byte[]

Rahim Pirbhai picture Rahim Pirbhai · Mar 12, 2015 · Viewed 39k times · Source

I am working with google protobuf in Java. I see that it is possible to serialize a protobuf message to String, byte[], ByteString, etc: (Source: https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/MessageLite)

I don't know what a ByteString is. I got the following definition from the the protobuf API documentation (source: https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/ByteString): "Immutable sequence of bytes. Substring is supported by sharing the reference to the immutable underlying bytes, as with String."

It is not clear to me how a ByteString is different from a String or byte[]. Can somebody please explain? Thanks.

Answer

Matt Ball picture Matt Ball · Mar 12, 2015

You can think of ByteString as an immutable byte array. That's pretty much it. It's a byte[] which you can use in a protobuf. Protobuf does not let you use Java arrays because they're mutable.

ByteString exists because String is not suitable for representing arbitrary sequences of bytes. String is specifically for character data.

The protobuf MessageLite Interface provides toByteArray() and toByteString() methods. If ByteString is an immutable byte[], would the byte representation of a message represented by both ByteString and byte[] be the same?

Sort of. If you call toByteArray() you'll get the same value as if you were to call toByteString().toByteArray(). Compare the implementation of the two methods, in AbstractMessageLite:

public ByteString toByteString() {
  try {
    final ByteString.CodedBuilder out =
      ByteString.newCodedBuilder(getSerializedSize());
    writeTo(out.getCodedOutput());
    return out.build();
  } catch (IOException e) {
    throw new RuntimeException(
      "Serializing to a ByteString threw an IOException (should " +
      "never happen).", e);
  }
}

public byte[] toByteArray() {
  try {
    final byte[] result = new byte[getSerializedSize()];
    final CodedOutputStream output = CodedOutputStream.newInstance(result);
    writeTo(output);
    output.checkNoSpaceLeft();
    return result;
  } catch (IOException e) {
    throw new RuntimeException(
      "Serializing to a byte array threw an IOException " +
      "(should never happen).", e);
  }
}