static void checkKeyValueBytes(byte[] buf, int offset, int length, boolean withTags) {
    if (buf == null) {
      String msg = "Invalid to have null byte array in KeyValue.";
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }

    int pos = offset, endOffset = offset + length;
    // check the key
    if (pos + Bytes.SIZEOF_INT > endOffset) {
      String msg =
        "Overflow when reading key length at position=" + pos + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
    int keyLen = Bytes.toInt(buf, pos, Bytes.SIZEOF_INT);
    pos += Bytes.SIZEOF_INT;
    if (keyLen <= 0 || pos + keyLen > endOffset) {
      String msg =
        "Invalid key length in KeyValue. keyLength=" + keyLen + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
    // check the value
    if (pos + Bytes.SIZEOF_INT > endOffset) {
      String msg =
        "Overflow when reading value length at position=" + pos + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
    int valLen = Bytes.toInt(buf, pos, Bytes.SIZEOF_INT);
    pos += Bytes.SIZEOF_INT;
    if (valLen < 0 || pos + valLen > endOffset) {
      String msg =
        "Invalid value length in KeyValue, valueLength=" + valLen + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
    // check the row
    if (pos + Bytes.SIZEOF_SHORT > endOffset) {
      String msg =
        "Overflow when reading row length at position=" + pos + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
    short rowLen = Bytes.toShort(buf, pos, Bytes.SIZEOF_SHORT);
    pos += Bytes.SIZEOF_SHORT;
    if (rowLen < 0 || pos + rowLen > endOffset) {
      String msg =
        "Invalid row length in KeyValue, rowLength=" + rowLen + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
    pos += rowLen;
    // check the family
    if (pos + Bytes.SIZEOF_BYTE > endOffset) {
      String msg =
        "Overflow when reading family length at position=" + pos + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
    int familyLen = buf[pos];
    pos += Bytes.SIZEOF_BYTE;
    if (familyLen < 0 || pos + familyLen > endOffset) {
      String msg = "Invalid family length in KeyValue, familyLength=" + familyLen
        + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
    pos += familyLen;
    // check the qualifier
    int qualifierLen = keyLen - Bytes.SIZEOF_SHORT - rowLen - Bytes.SIZEOF_BYTE - familyLen
      - Bytes.SIZEOF_LONG - Bytes.SIZEOF_BYTE;
    if (qualifierLen < 0 || pos + qualifierLen > endOffset) {
      String msg = "Invalid qualifier length in KeyValue, qualifierLen=" + qualifierLen
        + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
    pos += qualifierLen;
    // check the timestamp
    if (pos + Bytes.SIZEOF_LONG > endOffset) {
      String msg =
        "Overflow when reading timestamp at position=" + pos + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
    long timestamp = Bytes.toLong(buf, pos, Bytes.SIZEOF_LONG);
    if (timestamp < 0) {
      String msg =
        "Timestamp cannot be negative, ts=" + timestamp + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
    pos += Bytes.SIZEOF_LONG;
    // check the type
    if (pos + Bytes.SIZEOF_BYTE > endOffset) {
      String msg =
        "Overflow when reading type at position=" + pos + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
    byte type = buf[pos];
    if (!KeyValue.Type.isValidType(type)) {
      String msg = "Invalid type in KeyValue, type=" + type + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
    pos += Bytes.SIZEOF_BYTE;
    // check the value
    if (pos + valLen > endOffset) {
      String msg =
        "Overflow when reading value part at position=" + pos + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
    pos += valLen;
    // check the tags
    if (withTags) {
      if (pos == endOffset) {
        // withTags is true but no tag in the cell.
        return;
      }
      pos = checkKeyValueTagBytes(buf, offset, length, pos, endOffset);
    }
    if (pos != endOffset) {
      String msg = "Some redundant bytes in KeyValue's buffer, startOffset=" + pos + ", endOffset="
        + endOffset + bytesToHex(buf, offset, length);
      LOG.warn(msg);
      throw new IllegalArgumentException(msg);
    }
  }
Write out a KeyValue in the manner in which we used to when KeyValue was a Writable.
@return Length written on stream
@see #create(DataInput) for the inverse function
hbase-common/src/main/java/org/apache/hadoop/hbase/KeyValueUtil.java