BinaryMemcacheDecoder extends ByteToMessageDecoder { @Override protected void decode(final ChannelHandlerContext ctx, final ByteBuf buf, final List<Object> out) throws Exception { for (int i = 0; i < BATCH_SIZE; i++) { if (buf.readableBytes() < 24) { return; } buf.markReaderIndex(); final int magicNumber = buf.readUnsignedByte(); if (magicNumber != 0x81) { throw fail(buf, String.format("Invalid magic number: 0x%2x", magicNumber)); } final OpCode opcode = OpCode.of(buf.readByte()); final int keyLength = buf.readUnsignedShort(); final int extrasLength = buf.readUnsignedByte(); buf.skipBytes(1); final int statusCode = buf.readUnsignedShort(); final MemcacheStatus status = MemcacheStatus.fromInt(statusCode); final int totalLength = buf.readInt(); final int opaque = buf.readInt(); final long cas = buf.readLong(); if (buf.readableBytes() < totalLength) { buf.resetReaderIndex(); return; } buf.skipBytes(extrasLength); byte[] keyBytes; if (keyLength == 0) { keyBytes = NO_BYTES; } else { keyBytes = new byte[keyLength]; } buf.readBytes(keyBytes); final int valueLength = totalLength - keyLength - extrasLength; byte[] valueBytes; if (valueLength == 0) { valueBytes = NO_BYTES; } else { valueBytes = new byte[valueLength]; } buf.readBytes(valueBytes); if (opcode == OpCode.STAT) { boolean endPacket = keyLength == 0; if (endPacket) { out.add(replies); replies = new BinaryResponse(); } else { replies.add(new ResponsePacket(opcode, status, opaque, cas, keyBytes, valueBytes)); } } else { replies.add(new ResponsePacket(opcode, status, opaque, cas, keyBytes, valueBytes)); if ((opaque & 0xFF) == 0) { out.add(replies); replies = new BinaryResponse(); } } } } BinaryMemcacheDecoder();   }
@Test public void test() throws Exception { GetRequest request = new GetRequest(KEY.getBytes(StandardCharsets.UTF_8), OpCode.GET, 123); BinaryMemcacheDecoder decoder = new BinaryMemcacheDecoder(); ByteBuf cb = Unpooled.buffer(30); cb.writeByte(0x81); cb.writeByte(OpCode.GET.value()); cb.writeShort(3); cb.writeByte(0); cb.writeZero(1); cb.writeShort(0); cb.writeInt(6); cb.writeInt(request.opaque); cb.writeLong(258); cb.writeBytes(KEY.getBytes()); cb.writeBytes(VALUE.getBytes()); List<Object> out = new ArrayList<>(); decoder.decode(null, cb, out); @SuppressWarnings("unchecked") List<ResponsePacket> replies = (List<ResponsePacket>) out.get(0); request.handle(replies, HostAndPort.fromHost("server")); GetResult<byte[]> getResult = request.get(); assertEquals(258, getResult.getCas()); assertEquals(VALUE, TRANSCODER.decode(getResult.getValue())); }