byte[] toBytes() {
    // create a byte array to hold the headerVersion + userMetadataVersion + userMetadataSize + blobRecordVersion +
    // blobType + blobRecordSize + storeKey.
    // Note: Blob Version 3 has introduced compression, but we don't want to add that to hard delete metadata.
    byte[] bytes = new byte[Version_Field_Size_In_Bytes + Version_Field_Size_In_Bytes + Integer.SIZE / 8
        + Version_Field_Size_In_Bytes + (blobRecordVersion >= Blob_Version_V2 ? (Short.SIZE / 8) : 0) + Long.SIZE / 8
        + storeKey.sizeInBytes()];

    ByteBuffer bufWrap = ByteBuffer.wrap(bytes);
    bufWrap.putShort(headerVersion);
    bufWrap.putShort(userMetadataVersion);
    bufWrap.putInt(userMetadataSize);
    bufWrap.putShort(blobRecordVersion);
    if (blobRecordVersion >= Blob_Version_V2) {
      bufWrap.putShort((short) blobType.ordinal());
    }
    bufWrap.putLong(blobStreamSize);
    bufWrap.put(storeKey.toBytes());
    return bytes;
  }
For the message at readSetIndex, does the following:
   1. Reads the whole blob and does a crc check. If the crc check fails, returns null - this means that the record
   is not retrievable anyway.
   2. Adds to a hard delete replacement write set.
   3. Returns the hard delete info.
ambry-messageformat/src/main/java/com/github/ambry/messageformat/BlobStoreHardDelete.java