All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jetdrone.vertx.mods.redis.RedisDecoder Maven / Gradle / Ivy

The newest version!
package com.jetdrone.vertx.mods.redis;

import com.jetdrone.vertx.mods.redis.reply.*;
import io.netty.buffer.ByteBuf;

import java.io.IOException;
import java.nio.charset.Charset;

/**
 * Netty codec for Redis
 */

public class RedisDecoder {

  public static final char CR = '\r';
  public static final char LF = '\n';
  private static final char ZERO = '0';

  // We track the current multibulk reply in the case
  // where we do not get a complete reply in a single
  // decode invocation.
  private MultiBulkReply reply;

  public ByteBuf readBytes(ByteBuf is) throws IOException {
    long size = readLong(is);
    if (size == -1) {
      return null;
    }
    if (size > Integer.MAX_VALUE) {
      throw new IllegalArgumentException("Java only supports arrays up to " + Integer.MAX_VALUE + " in size");
    }
    ByteBuf buffer = is.readSlice((int) size);
    int cr = is.readByte();
    int lf = is.readByte();
    if (cr != CR || lf != LF) {
      throw new IOException("Improper line ending: " + cr + ", " + lf);
    }
    return buffer;
  }

  public static long readLong(ByteBuf is) throws IOException {
    long size = 0;
    int sign = 1;
    int read = is.readByte();
    if (read == '-') {
      read = is.readByte();
      sign = -1;
    }
    do {
      if (read == CR) {
        if (is.readByte() == LF) {
          break;
        }
      }
      int value = read - ZERO;
      if (value >= 0 && value < 10) {
        size *= 10;
        size += value;
      } else {
        throw new IOException("Invalid character in integer");
      }
      read = is.readByte();
    } while (true);
    return size * sign;
  }

  public Reply receive(final ByteBuf is) throws IOException {
    int code = is.readByte();
    switch (code) {
      case StatusReply.MARKER: {
        // TODO: should verify if it is really \r\n
        String status = is.readBytes(is.bytesBefore((byte) '\r')).toString(Charset.forName("UTF-8"));
        is.skipBytes(2);
        return new StatusReply(status);
      }
      case ErrorReply.MARKER: {
        // TODO: should verify if it is really \r\n
        String error = is.readBytes(is.bytesBefore((byte) '\r')).toString(Charset.forName("UTF-8"));
        is.skipBytes(2);
        return new ErrorReply(error);
      }
      case IntegerReply.MARKER: {
        return new IntegerReply(readLong(is));
      }
      case BulkReply.MARKER: {
        return new BulkReply(readBytes(is));
      }
      case MultiBulkReply.MARKER: {
        return decodeMultiBulkReply(is);
      }
      default: {
        throw new IOException("Unexpected character in stream: " + code);
      }
    }
  }

  public MultiBulkReply decodeMultiBulkReply(ByteBuf is) throws IOException {
    try {
      if (reply == null) {
        reply = new MultiBulkReply(this, is);
      } else {
        reply.read(this, is);
      }
      return reply;
    } finally {
      reply = null;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy