public static AddMsgLocation decode(final ByteBuffer buf) {
   if (!buf.hasRemaining()) {
     return null;
   }
   final long offset = buf.getLong();
   final int length = buf.getInt();
   final int checksum = buf.getInt();
   final int descLen = buf.getInt();
   final byte[] descBytes = new byte[descLen];
   buf.get(descBytes);
   final String desc = ByteUtils.getString(descBytes);
   return new AddMsgLocation(offset, length, checksum, desc);
 }
 /**
  * 消息位置序列化为:
  *
  * <ul>
  *   <li>8个字节的offset
  *   <li>4个字节的长度
  *   <li>4个字节checksum:这是指整个消息存储数据的checksum,跟message的checksum不同
  *   <li>4个字节长度,存储的分区名的长度
  *   <li>存储的分区名
  * </ul>
  *
  * @return
  */
 public ByteBuffer encode() {
   if (this.buf == null) {
     final byte[] storeDescBytes = ByteUtils.getBytes(this.storeDesc);
     final ByteBuffer buf = ByteBuffer.allocate(4 + 4 + 8 + 4 + this.storeDesc.length());
     buf.putLong(this.getOffset());
     buf.putInt(this.getLength());
     buf.putInt(this.checksum);
     buf.putInt(storeDescBytes.length);
     buf.put(storeDescBytes);
     buf.flip();
     this.buf = buf;
   }
   return this.buf;
 }
  /**
   * 将消息属性和消息payload打包,结构如下:</br></br> 0或者1个定长attribute + payload
   *
   * @param message
   * @return
   */
  public static final byte[] encodePayload(final Message message) {
    final byte[] payload = message.getData();
    final String attribute = message.getAttribute();
    byte[] attrData = null;
    if (attribute != null) {
      attrData = ByteUtils.getBytes(attribute);
    } else {
      return payload;
    }
    final int attrLen = attrData == null ? 0 : attrData.length;
    final ByteBuffer buffer = ByteBuffer.allocate(4 + attrLen + payload.length);
    if (attribute != null) {
      buffer.putInt(attrLen);
      if (attrData != null) {
        buffer.put(attrData);
      }
    }

    buffer.put(payload);
    return buffer.array();
  }
 /**
  * 从binary数据中解出消息
  *
  * @param topic
  * @param data
  * @param offset
  * @return
  * @throws InvalidMessageException
  */
 public static final DecodedMessage decodeMessage(
     final String topic, final byte[] data, final int offset) throws InvalidMessageException {
   final ByteBuffer buf = ByteBuffer.wrap(data, offset, HEADER_LEN);
   final int msgLen = buf.getInt();
   final int checksum = buf.getInt();
   vailidateMessage(offset + HEADER_LEN, msgLen, checksum, data);
   final long id = buf.getLong();
   // 取flag
   final int flag = buf.getInt();
   String attribute = null;
   int payLoadOffset = offset + HEADER_LEN;
   int payLoadLen = msgLen;
   if (payLoadLen > MAX_READ_BUFFER_SIZE) {
     throw new InvalidMessageException("Too much long payload length:" + payLoadLen);
   }
   // 如果有属性,需要解析属性
   if (MessageFlagUtils.hasAttribute(flag)) {
     // 取4个字节的属性长度
     final int attrLen = getInt(offset + HEADER_LEN, data);
     // 取消息属性
     final byte[] attrData = new byte[attrLen];
     System.arraycopy(data, offset + HEADER_LEN + 4, attrData, 0, attrLen);
     attribute = ByteUtils.getString(attrData);
     // 递增payloadOffset,加上4个字节的消息长度和消息长度本身
     payLoadOffset = offset + HEADER_LEN + 4 + attrLen;
     // payload长度递减,减去4个字节的消息长度和消息长度本身
     payLoadLen = msgLen - 4 - attrLen;
   }
   // 获取payload
   final byte[] payload = new byte[payLoadLen];
   System.arraycopy(data, payLoadOffset, payload, 0, payLoadLen);
   final Message msg = new Message(topic, payload);
   MessageAccessor.setFlag(msg, flag);
   msg.setAttribute(attribute);
   MessageAccessor.setId(msg, id);
   return new DecodedMessage(
       payLoadOffset + payLoadLen,
       msg,
       ByteBuffer.wrap(data, offset, payLoadOffset + payLoadLen - offset));
 }