/**
  * Writes 24-bit integer <code>value</code> if not null, otherwise writes zeros to the <code>
  * output</code> ByteBuf. ByteBuf's writerIndex is increased by 3.
  *
  * @param value Medium value to be written to the output.
  * @param output ByteBuf, where value or zeros are written.
  */
 public static void writeMedium(final Integer value, final ByteBuf output) {
   if (value != null) {
     output.writeMedium(value);
   } else {
     output.writeZero(MEDIUM_BYTES_LENGTH);
   }
 }
 /** encode Message to byte & write to network framework */
 public void encode(ResponseSocketBlock resMsg, ByteBuf buf) throws IOException {
   //
   // * --------------------------------------------------------bytes =13
   // * byte[1]  version                              RSF版本(0x81)
   buf.writeByte(resMsg.getVersion());
   // * byte[8]  requestID                            请求ID
   buf.writeLong(resMsg.getRequestID());
   // * byte[1]  keepData                             保留区
   buf.writeByte(0);
   // * byte[3]  contentLength                        内容大小(max = 16MB)
   ByteBuf responseBody = this.encodeResponse(resMsg);
   int bodyLength = responseBody.readableBytes();
   bodyLength = (bodyLength << 8) >>> 8; // 左移8未,在无符号右移8位。形成最大16777215字节的限制。
   buf.writeMedium(bodyLength);
   //
   buf.writeBytes(responseBody);
   //
 }
  /**
   * Encode a simple UA TCP message.
   *
   * @param messageType {@link MessageType#Hello}, {@link MessageType#Acknowledge}, or {@link
   *     MessageType#Error}.
   * @param messageEncoder a function that encodes the message payload.
   * @param buffer the {@link ByteBuf} to encode into.
   */
  private static ByteBuf encode(
      MessageType messageType, Consumer<ByteBuf> messageEncoder, ByteBuf buffer)
      throws UaException {
    buffer.writeMedium(MessageType.toMediumInt(messageType));
    buffer.writeByte('F');

    int lengthIndex = buffer.writerIndex();
    buffer.writeInt(0);

    int indexBefore = buffer.writerIndex();
    messageEncoder.accept(buffer);
    int indexAfter = buffer.writerIndex();
    int bytesWritten = indexAfter - indexBefore;

    buffer.writerIndex(lengthIndex);
    buffer.writeInt(8 + bytesWritten);
    buffer.writerIndex(indexAfter);

    return buffer;
  }
  @Override
  public void write(ByteBuf buf) {
    ByteBuf payload = Unpooled.buffer(2048);
    int count = packets.length;
    int records = 0;

    if (count > 0) {
      int pointer = 0;
      int start = packets[0];
      int last = packets[0];

      while (pointer + 1 < count) {
        int current = packets[pointer++];
        int diff = current - last;
        if (diff == 1) {
          last = current;
        } else if (diff > 1) {
          if (start == last) {
            payload.writeByte((byte) 0x01);
            payload.writeMedium(start);
            start = last = current;
          } else {
            payload.writeByte((byte) 0x00);
            payload.writeMedium(start);
            payload.writeMedium(last);
            start = last = current;
          }
          records = records + 1;
        }
      }

      if (start == last) {
        payload.writeByte((byte) 0x01);
        payload.writeMedium(start);
      } else {
        payload.writeByte((byte) 0x00);
        payload.writeMedium(start);
        payload.writeMedium(last);
      }
      records = records + 1;
    }
    buf.writeShort(records);
    buf.writeBytes(payload);
  }
  @Override
  protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
    if (msg instanceof SpdyDataFrame) {

      SpdyDataFrame spdyDataFrame = (SpdyDataFrame) msg;
      ByteBuf data = spdyDataFrame.data();
      byte flags = spdyDataFrame.isLast() ? SPDY_DATA_FLAG_FIN : 0;
      out.ensureWritable(SPDY_HEADER_SIZE + data.readableBytes());
      out.writeInt(spdyDataFrame.getStreamId() & 0x7FFFFFFF);
      out.writeByte(flags);
      out.writeMedium(data.readableBytes());
      out.writeBytes(data, data.readerIndex(), data.readableBytes());

    } else if (msg instanceof SpdySynStreamFrame) {

      SpdySynStreamFrame spdySynStreamFrame = (SpdySynStreamFrame) msg;
      ByteBuf data = compressHeaderBlock(encodeHeaderBlock(version, spdySynStreamFrame));
      byte flags = spdySynStreamFrame.isLast() ? SPDY_FLAG_FIN : 0;
      if (spdySynStreamFrame.isUnidirectional()) {
        flags |= SPDY_FLAG_UNIDIRECTIONAL;
      }
      int headerBlockLength = data.readableBytes();
      int length;
      if (version < 3) {
        length = headerBlockLength == 0 ? 12 : 10 + headerBlockLength;
      } else {
        length = 10 + headerBlockLength;
      }
      out.ensureWritable(SPDY_HEADER_SIZE + length);
      out.writeShort(version | 0x8000);
      out.writeShort(SPDY_SYN_STREAM_FRAME);
      out.writeByte(flags);
      out.writeMedium(length);
      out.writeInt(spdySynStreamFrame.getStreamId());
      out.writeInt(spdySynStreamFrame.getAssociatedToStreamId());
      if (version < 3) {
        // Restrict priorities for SPDY/2 to between 0 and 3
        byte priority = spdySynStreamFrame.getPriority();
        if (priority > 3) {
          priority = 3;
        }
        out.writeShort((priority & 0xFF) << 14);
      } else {
        out.writeShort((spdySynStreamFrame.getPriority() & 0xFF) << 13);
      }
      if (version < 3 && data.readableBytes() == 0) {
        out.writeShort(0);
      }
      out.writeBytes(data, data.readerIndex(), headerBlockLength);

    } else if (msg instanceof SpdySynReplyFrame) {

      SpdySynReplyFrame spdySynReplyFrame = (SpdySynReplyFrame) msg;
      ByteBuf data = compressHeaderBlock(encodeHeaderBlock(version, spdySynReplyFrame));
      byte flags = spdySynReplyFrame.isLast() ? SPDY_FLAG_FIN : 0;
      int headerBlockLength = data.readableBytes();
      int length;
      if (version < 3) {
        length = headerBlockLength == 0 ? 8 : 6 + headerBlockLength;
      } else {
        length = 4 + headerBlockLength;
      }
      out.ensureWritable(SPDY_HEADER_SIZE + length);
      out.writeShort(version | 0x8000);
      out.writeShort(SPDY_SYN_REPLY_FRAME);
      out.writeByte(flags);
      out.writeMedium(length);
      out.writeInt(spdySynReplyFrame.getStreamId());
      if (version < 3) {
        if (headerBlockLength == 0) {
          out.writeInt(0);
        } else {
          out.writeShort(0);
        }
      }
      out.writeBytes(data, data.readerIndex(), headerBlockLength);

    } else if (msg instanceof SpdyRstStreamFrame) {

      SpdyRstStreamFrame spdyRstStreamFrame = (SpdyRstStreamFrame) msg;
      out.ensureWritable(SPDY_HEADER_SIZE + 8);
      out.writeShort(version | 0x8000);
      out.writeShort(SPDY_RST_STREAM_FRAME);
      out.writeInt(8);
      out.writeInt(spdyRstStreamFrame.getStreamId());
      out.writeInt(spdyRstStreamFrame.getStatus().getCode());

    } else if (msg instanceof SpdySettingsFrame) {

      SpdySettingsFrame spdySettingsFrame = (SpdySettingsFrame) msg;
      byte flags = spdySettingsFrame.clearPreviouslyPersistedSettings() ? SPDY_SETTINGS_CLEAR : 0;
      Set<Integer> IDs = spdySettingsFrame.getIds();
      int numEntries = IDs.size();
      int length = 4 + numEntries * 8;
      out.ensureWritable(SPDY_HEADER_SIZE + length);
      out.writeShort(version | 0x8000);
      out.writeShort(SPDY_SETTINGS_FRAME);
      out.writeByte(flags);
      out.writeMedium(length);
      out.writeInt(numEntries);
      for (Integer ID : IDs) {
        int id = ID.intValue();
        byte ID_flags = 0;
        if (spdySettingsFrame.isPersistValue(id)) {
          ID_flags |= SPDY_SETTINGS_PERSIST_VALUE;
        }
        if (spdySettingsFrame.isPersisted(id)) {
          ID_flags |= SPDY_SETTINGS_PERSISTED;
        }
        if (version < 3) {
          // Chromium Issue 79156
          // SPDY setting ids are not written in network byte order
          // Write id assuming the architecture is little endian
          out.writeByte(id & 0xFF);
          out.writeByte(id >> 8 & 0xFF);
          out.writeByte(id >> 16 & 0xFF);
          out.writeByte(ID_flags);
        } else {
          out.writeByte(ID_flags);
          out.writeMedium(id);
        }
        out.writeInt(spdySettingsFrame.getValue(id));
      }

    } else if (msg instanceof SpdyNoOpFrame) {

      out.ensureWritable(SPDY_HEADER_SIZE);
      out.writeShort(version | 0x8000);
      out.writeShort(SPDY_NOOP_FRAME);
      out.writeInt(0);

    } else if (msg instanceof SpdyPingFrame) {

      SpdyPingFrame spdyPingFrame = (SpdyPingFrame) msg;
      out.ensureWritable(SPDY_HEADER_SIZE + 4);
      out.writeShort(version | 0x8000);
      out.writeShort(SPDY_PING_FRAME);
      out.writeInt(4);
      out.writeInt(spdyPingFrame.getId());

    } else if (msg instanceof SpdyGoAwayFrame) {

      SpdyGoAwayFrame spdyGoAwayFrame = (SpdyGoAwayFrame) msg;
      int length = version < 3 ? 4 : 8;
      out.ensureWritable(SPDY_HEADER_SIZE + length);
      out.writeShort(version | 0x8000);
      out.writeShort(SPDY_GOAWAY_FRAME);
      out.writeInt(length);
      out.writeInt(spdyGoAwayFrame.getLastGoodStreamId());
      if (version >= 3) {
        out.writeInt(spdyGoAwayFrame.getStatus().getCode());
      }

    } else if (msg instanceof SpdyHeadersFrame) {

      SpdyHeadersFrame spdyHeadersFrame = (SpdyHeadersFrame) msg;
      ByteBuf data = compressHeaderBlock(encodeHeaderBlock(version, spdyHeadersFrame));
      byte flags = spdyHeadersFrame.isLast() ? SPDY_FLAG_FIN : 0;
      int headerBlockLength = data.readableBytes();
      int length;
      if (version < 3) {
        length = headerBlockLength == 0 ? 4 : 6 + headerBlockLength;
      } else {
        length = 4 + headerBlockLength;
      }
      out.ensureWritable(SPDY_HEADER_SIZE + length);
      out.writeShort(version | 0x8000);
      out.writeShort(SPDY_HEADERS_FRAME);
      out.writeByte(flags);
      out.writeMedium(length);
      out.writeInt(spdyHeadersFrame.getStreamId());
      if (version < 3 && headerBlockLength != 0) {
        out.writeShort(0);
      }
      out.writeBytes(data, data.readerIndex(), headerBlockLength);

    } else if (msg instanceof SpdyWindowUpdateFrame) {

      SpdyWindowUpdateFrame spdyWindowUpdateFrame = (SpdyWindowUpdateFrame) msg;
      out.ensureWritable(SPDY_HEADER_SIZE + 8);
      out.writeShort(version | 0x8000);
      out.writeShort(SPDY_WINDOW_UPDATE_FRAME);
      out.writeInt(8);
      out.writeInt(spdyWindowUpdateFrame.getStreamId());
      out.writeInt(spdyWindowUpdateFrame.getDeltaWindowSize());
    } else {
      throw new UnsupportedMessageTypeException(msg);
    }
  }
 @Override
 public MessageBuffer<ByteBuf> writeMedium(int value) {
   buffer.writeMedium(value);
   return this;
 }
 @Override
 public ByteBuf writeMedium(int value) {
   return buf.writeMedium(value);
 }
 @Override
 public ByteBuf writeMedium(int var1) {
   return a.writeMedium(var1);
 }