/**
  * Read a {@code string} field value from the stream. If the stream contains malformed UTF-8,
  * throw exception {@link InvalidProtocolBufferException}.
  */
 public String readStringRequireUtf8() throws IOException {
   final int size = readRawVarint32();
   final byte[] bytes;
   int pos = bufferPos;
   if (size <= (bufferSize - pos) && size > 0) {
     // Fast path:  We already have the bytes in a contiguous buffer, so
     //   just copy directly from it.
     bytes = buffer;
     bufferPos = pos + size;
   } else if (size == 0) {
     return "";
   } else {
     // Slow path:  Build a byte array first then copy it.
     bytes = readRawBytesSlowPath(size);
     pos = 0;
   }
   // TODO(martinrb): We could save a pass by validating while decoding.
   if (!Utf8.isValidUtf8(bytes, pos, pos + size)) {
     throw InvalidProtocolBufferException.invalidUtf8();
   }
   return new String(bytes, pos, size, Internal.UTF_8);
 }