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

com.twitter.finagle.redis.protocol.commands.CommandArguments.scala Maven / Gradle / Ivy

There is a newer version: 21.2.0
Show newest version
package com.twitter.finagle.redis.protocol

import _root_.java.lang.{Long => JLong}
import com.twitter.finagle.redis.ClientError
import com.twitter.finagle.redis.util._
import com.twitter.io.Buf
import org.jboss.netty.buffer.{ChannelBuffer, ChannelBuffers}

trait CommandArgument extends Command

case object WithScores extends CommandArgument {
  def command = "WITHSCORES"
  val WITHSCORES = command
  def commandBytes = StringToChannelBuffer(command)
  def unapply(s: String) = s.toUpperCase match {
    case WITHSCORES => Some(s)
    case _ => None
  }
  override def toString = command
  def toChannelBuffer = commandBytes
  @deprecated("Prefer option") val asArg = Some(WithScores)
  def option(opt: Boolean): Option[this.type] = if (opt) asArg else None
}

case class Limit(offset: Long, count: Long) extends CommandArgument {
  def command = Limit.LIMIT
  def commandBytes = Limit.LIMIT_CB
  override def toString = "%s %d %d".format(Limit.LIMIT, offset, count)
  def toChannelBuffer = ChannelBuffers.wrappedBuffer(toChannelBuffers.toArray:_*)
  def toChannelBuffers = Seq(Limit.LIMIT_CB,
    StringToChannelBuffer(offset.toString), StringToChannelBuffer(count.toString))
}
object Limit {
  val LIMIT = "LIMIT"
  val LIMIT_CB = StringToChannelBuffer(LIMIT)
  def apply(args: Seq[String]) = {
    RequireClientProtocol(args != null && args.length == 3, "LIMIT requires two arguments")
    RequireClientProtocol(args.head == LIMIT, "LIMIT must start with LIMIT clause")
    RequireClientProtocol.safe {
      val offset = NumberFormat.toLong(args(1))
      val count = NumberFormat.toLong(args(2))
      new Limit(offset, count)
    }
  }
}

// Represents a list of WEIGHTS
class Weights(underlying: Array[Double]) extends CommandArgument with IndexedSeq[Double] {
  def apply(idx: Int) = underlying(idx)
  def length = underlying.length
  override def toString = Weights.toString + " " + this.mkString(" ")
  def toChannelBuffer = ChannelBuffers.wrappedBuffer(toChannelBuffers.toArray:_*)
  def toChannelBuffers =
    Weights.WEIGHTS_CB +: underlying.map(w => StringToChannelBuffer(w.toString)).toSeq
  def command = Weights.WEIGHTS
}

// Handles parsing and manipulation of WEIGHTS arguments
object Weights {
  val WEIGHTS = "WEIGHTS"
  val WEIGHTS_CB = StringToChannelBuffer(WEIGHTS)

  def apply(weight: Double) = new Weights(Array(weight))
  def apply(weights: Double*) = new Weights(weights.toArray)
  def apply(weights: Array[Double]) = new Weights(weights)

  def apply(args: Seq[String]): Option[Weights] = {
    val argLength = args.length
    RequireClientProtocol(
      args != null && argLength > 0,
      "WEIGHTS can not be specified with an empty list")
    args.head.toUpperCase match {
      case WEIGHTS =>
        RequireClientProtocol(argLength > 1, "WEIGHTS requires additional arguments")
        val weights: Array[Double] = RequireClientProtocol.safe {
          args.tail.map { item => NumberFormat.toDouble(item) }(collection.breakOut)
        }
        Some(new Weights(weights))
      case _ => None
    }
  }
  override def toString = Weights.WEIGHTS
}

// Handles parsing and manipulation of AGGREGATE arguments
sealed abstract class Aggregate(val name: String) {
  override def toString = Aggregate.toString + " " + name.toUpperCase
  def toChannelBuffer = ChannelBuffers.wrappedBuffer(toChannelBuffers.toArray:_*)
  def toChannelBuffers = Seq(Aggregate.AGGREGATE_CB, StringToChannelBuffer(name.toUpperCase))
  def equals(str: String) = str.equals(name)
}
object Aggregate {
  val AGGREGATE = "AGGREGATE"
  val AGGREGATE_CB = StringToChannelBuffer(AGGREGATE)
  case object Sum extends Aggregate("SUM")
  case object Min extends Aggregate("MIN")
  case object Max extends Aggregate("MAX")
  override def toString = AGGREGATE

  def apply(args: Seq[String]): Option[Aggregate] = {
    val argLength = args.length
    RequireClientProtocol(
      args != null && argLength > 0,
      "AGGREGATE can not be specified with empty list")
    args.head.toUpperCase match {
      case AGGREGATE =>
        RequireClientProtocol(argLength == 2, "AGGREGATE requires a type (MIN, MAX, SUM)")
        args(1).toUpperCase match {
          case Aggregate.Sum.name => Some(Aggregate.Sum)
          case Aggregate.Max.name => Some(Aggregate.Max)
          case Aggregate.Min.name => Some(Aggregate.Min)
          case _ => throw new ClientError("AGGREGATE type must be one of MIN, MAX or SUM")
        }
      case _ => None
    }
  }
}


object Count {
  val COUNT: String = "COUNT"
  val COUNT_BUF: Buf = StringToBuf(COUNT)
  val COUNT_CB: ChannelBuffer = StringToChannelBuffer(COUNT)

  def apply(args: Seq[String]): Option[JLong] = {
    RequireClientProtocol(
      args != null && !args.isEmpty,
      "COUNT can not be specified with empty list")
    args.head.toUpperCase match {
      case COUNT =>
        RequireClientProtocol(args.length == 2, "COUNT requires two arguments")
        Some(RequireClientProtocol.safe { NumberFormat.toLong(args(1)) })
      case _ => None
    }
  }
}


object Pattern {
  val PATTERN: String = "PATTERN"
  val PATTERN_BUF: Buf = StringToBuf(PATTERN)
  val PATTERN_CB: ChannelBuffer = StringToChannelBuffer(PATTERN)

  def apply(args: Seq[String]): Option[String] = {
    RequireClientProtocol(
      args != null && !args.isEmpty,
      "AGGREGATE can not be specified with empty list")
    args.head.toUpperCase match {
      case PATTERN => Some(args(1))
      case _ => None
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy