package com.github.xetorthio.jedis.codec;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ReplayingDecoder;
import java.util.List;
import java.util.Queue;
import com.github.xetorthio.jedis.result.BulkStringResultPromise;
public class RedisProtocolDecoder extends ReplayingDecoder<Void> {
public static final byte DOLLAR_BYTE = '$';
public static final byte ASTERISK_BYTE = '*';
public static final byte PLUS_BYTE = '+';
public static final byte MINUS_BYTE = '-';
public static final byte COLON_BYTE = ':';
public static byte[] CrLf = "\r\n".getBytes();
private Queue<BulkStringResultPromise> queue;
public RedisProtocolDecoder(Queue<BulkStringResultPromise> queue) {
this.queue = queue;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in,
List<Object> arg2) throws Exception {
final byte b = in.readByte();
if (b == PLUS_BYTE) {
queue.poll().setSuccessString(processStatusCodeReply(in));
} else if (b == DOLLAR_BYTE) {
queue.poll().setSuccessString(processBulkReply(in));
} else if (b == ASTERISK_BYTE) {
throw new RuntimeException("Not implemented");
// TODO: Implement
} else if (b == COLON_BYTE) {
queue.poll().setSuccessLong(processInteger(in));
} else if (b == MINUS_BYTE) {
throw new RuntimeException("Not implemented");
} else {
throw new RuntimeException("Don't know what to do here yet!");
}
}
private static Long processInteger(ByteBuf in) {
String nbs = in.readSlice(findCrLf(in)).toString();
in.readByte();
in.readByte();
Long nb = Long.parseLong(nbs);
return nb;
}
private static byte[] processBulkReply(ByteBuf in) {
ByteBuf buf = in.readSlice(findCrLf(in));
byte[] bytes = new byte[buf.readableBytes()];
buf.readBytes(bytes);
String nbs = new String(bytes);
in.readBytes(2);
Integer nb = Integer.parseInt(nbs);
bytes = new byte[nb];
in.readBytes(bytes);
in.readBytes(2);
return bytes;
}
private static byte[] processStatusCodeReply(ByteBuf in) {
ByteBuf buf = in.readSlice(findCrLf(in));
byte[] bytes = new byte[buf.readableBytes()];
buf.readBytes(bytes);
in.readBytes(2);
return bytes;
}
private static int findCrLf(final ByteBuf buffer) {
final int n = buffer.writerIndex();
for (int i = buffer.readerIndex(); i < n; i++) {
final byte b = buffer.getByte(i);
if (b == '\r' && i < n - 1 && buffer.getByte(i + 1) == '\n') {
return i - 1; // \r\n
}
}
return -1; // Not found.
}
}