diff options
Diffstat (limited to 'vendor/clue/redis-protocol')
16 files changed, 927 insertions, 0 deletions
diff --git a/vendor/clue/redis-protocol/composer.json b/vendor/clue/redis-protocol/composer.json new file mode 100644 index 0000000..d99e2ee --- /dev/null +++ b/vendor/clue/redis-protocol/composer.json @@ -0,0 +1,19 @@ +{ + "name": "clue/redis-protocol", + "description": "A streaming redis wire protocol parser and serializer implementation in PHP", + "keywords": ["streaming", "redis", "protocol", "parser", "serializer"], + "homepage": "https://github.com/clue/php-redis-protocol", + "license": "MIT", + "authors": [ + { + "name": "Christian Lück", + "email": "christian@lueck.tv" + } + ], + "require": { + "php": ">=5.3" + }, + "autoload": { + "psr-0": { "Clue\\Redis\\Protocol": "src" } + } +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Factory.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Factory.php new file mode 100644 index 0000000..3997f04 --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Factory.php @@ -0,0 +1,51 @@ +<?php + +namespace Clue\Redis\Protocol; + +use Clue\Redis\Protocol\Parser\ParserInterface; +use Clue\Redis\Protocol\Parser\ResponseParser; +use Clue\Redis\Protocol\Serializer\SerializerInterface; +use Clue\Redis\Protocol\Serializer\RecursiveSerializer; +use Clue\Redis\Protocol\Parser\RequestParser; + +/** + * Provides factory methods used to instantiate the best available protocol implementation + */ +class Factory +{ + /** + * instantiate the best available protocol response parser implementation + * + * This is the parser every redis client implementation should use in order + * to parse incoming response messages from a redis server. + * + * @return ParserInterface + */ + public function createResponseParser() + { + return new ResponseParser(); + } + + /** + * instantiate the best available protocol request parser implementation + * + * This is most useful for a redis server implementation which needs to + * process client requests. + * + * @return ParserInterface + */ + public function createRequestParser() + { + return new RequestParser(); + } + + /** + * instantiate the best available protocol serializer implementation + * + * @return SerializerInterface + */ + public function createSerializer() + { + return new RecursiveSerializer(); + } +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/BulkReply.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/BulkReply.php new file mode 100644 index 0000000..e069fda --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/BulkReply.php @@ -0,0 +1,34 @@ +<?php + +namespace Clue\Redis\Protocol\Model; + +use Clue\Redis\Protocol\Model\ModelInterface; +use Clue\Redis\Protocol\Serializer\SerializerInterface; + +class BulkReply implements ModelInterface +{ + private $value; + + /** + * create bulk reply (string reply) + * + * @param string|null $data + */ + public function __construct($value) + { + if ($value !== null) { + $value = (string)$value; + } + $this->value = $value; + } + + public function getValueNative() + { + return $this->value; + } + + public function getMessageSerialized(SerializerInterface $serializer) + { + return $serializer->getBulkMessage($this->value); + } +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/ErrorReply.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/ErrorReply.php new file mode 100644 index 0000000..556e93b --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/ErrorReply.php @@ -0,0 +1,34 @@ +<?php + +namespace Clue\Redis\Protocol\Model; + +use Exception; +use Clue\Redis\Protocol\Serializer\SerializerInterface; + +/** + * + * @link http://redis.io/topics/protocol#status-reply + */ +class ErrorReply extends Exception implements ModelInterface +{ + /** + * create error status reply (single line error message) + * + * @param string|ErrorReplyException $message + * @return string + */ + public function __construct($message, $code = 0, $previous = null) + { + parent::__construct($message, $code, $previous); + } + + public function getValueNative() + { + return $this->getMessage(); + } + + public function getMessageSerialized(SerializerInterface $serializer) + { + return $serializer->getErrorMessage($this->getMessage()); + } +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/IntegerReply.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/IntegerReply.php new file mode 100644 index 0000000..ba1ff05 --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/IntegerReply.php @@ -0,0 +1,31 @@ +<?php + +namespace Clue\Redis\Protocol\Model; + +use Clue\Redis\Protocol\Model\ModelInterface; +use Clue\Redis\Protocol\Serializer\SerializerInterface; + +class IntegerReply implements ModelInterface +{ + private $value; + + /** + * create integer reply + * + * @param int $data + */ + public function __construct($value) + { + $this->value = (int)$value; + } + + public function getValueNative() + { + return $this->value; + } + + public function getMessageSerialized(SerializerInterface $serializer) + { + return $serializer->getIntegerMessage($this->value); + } +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/ModelInterface.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/ModelInterface.php new file mode 100644 index 0000000..b97939e --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/ModelInterface.php @@ -0,0 +1,23 @@ +<?php + +namespace Clue\Redis\Protocol\Model; + +use Clue\Redis\Protocol\Serializer\SerializerInterface; + +interface ModelInterface +{ + /** + * Returns value of this model as a native representation for PHP + * + * @return mixed + */ + public function getValueNative(); + + /** + * Returns the serialized representation of this protocol message + * + * @param SerializerInterface $serializer; + * @return string + */ + public function getMessageSerialized(SerializerInterface $serializer); +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/MultiBulkReply.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/MultiBulkReply.php new file mode 100644 index 0000000..7198dc6 --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/MultiBulkReply.php @@ -0,0 +1,100 @@ +<?php + +namespace Clue\Redis\Protocol\Model; + +use InvalidArgumentException; +use UnexpectedValueException; +use Clue\Redis\Protocol\Serializer\SerializerInterface; + +class MultiBulkReply implements ModelInterface +{ + /** + * @var array|null + */ + private $data; + + /** + * create multi bulk reply (an array of other replies, usually bulk replies) + * + * @param array|null $data + * @throws InvalidArgumentException + */ + public function __construct(array $data = null) + { + $this->data = $data; + } + + public function getValueNative() + { + if ($this->data === null) { + return null; + } + + $ret = array(); + foreach ($this->data as $one) { + if ($one instanceof ModelInterface) { + $ret []= $one->getValueNative(); + } else { + $ret []= $one; + } + } + return $ret; + } + + public function getMessageSerialized(SerializerInterface $serializer) + { + return $serializer->getMultiBulkMessage($this->data); + } + + /** + * Checks whether this model represents a valid unified request protocol message + * + * The new unified protocol was introduced in Redis 1.2, but it became the + * standard way for talking with the Redis server in Redis 2.0. The unified + * request protocol is what Redis already uses in replies in order to send + * list of items to clients, and is called a Multi Bulk Reply. + * + * @return boolean + * @link http://redis.io/topics/protocol + */ + public function isRequest() + { + if (!$this->data) { + return false; + } + + foreach ($this->data as $one) { + if (!($one instanceof BulkReply) && !is_string($one)) { + return false; + } + } + + return true; + } + + public function getRequestModel() + { + if (!$this->data) { + throw new UnexpectedValueException('Null-multi-bulk message can not be represented as a request, must contain string/bulk values'); + } + + $command = null; + $args = array(); + + foreach ($this->data as $one) { + if ($one instanceof BulkReply) { + $one = $one->getValueNative(); + } elseif (!is_string($one)) { + throw new UnexpectedValueException('Message can not be represented as a request, must only contain string/bulk values'); + } + + if ($command === null) { + $command = $one; + } else { + $args []= $one; + } + } + + return new Request($command, $args); + } +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/Request.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/Request.php new file mode 100644 index 0000000..f5881e9 --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/Request.php @@ -0,0 +1,53 @@ +<?php + +namespace Clue\Redis\Protocol\Model; + +use Clue\Redis\Protocol\Model\ModelInterface; +use Clue\Redis\Protocol\Model\BulkReply; +use Clue\Redis\Protocol\Model\MultiBulkReply; +use Clue\Redis\Protocol\Serializer\SerializerInterface; + +class Request implements ModelInterface +{ + private $command; + private $args; + + public function __construct($command, array $args = array()) + { + $this->command = $command; + $this->args = $args; + } + + public function getCommand() + { + return $this->command; + } + + public function getArgs() + { + return $this->args; + } + + public function getReplyModel() + { + $models = array(new BulkReply($this->command)); + foreach ($this->args as $arg) { + $models []= new BulkReply($arg); + } + + return new MultiBulkReply($models); + } + + public function getValueNative() + { + $ret = $this->args; + array_unshift($ret, $this->command); + + return $ret; + } + + public function getMessageSerialized(SerializerInterface $serializer) + { + return $serializer->getRequestMessage($this->command, $this->args); + } +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/StatusReply.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/StatusReply.php new file mode 100644 index 0000000..4ea2fcd --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Model/StatusReply.php @@ -0,0 +1,34 @@ +<?php + +namespace Clue\Redis\Protocol\Model; + +use Clue\Redis\Protocol\Serializer\SerializerInterface; +/** + * + * @link http://redis.io/topics/protocol#status-reply + */ +class StatusReply implements ModelInterface +{ + private $message; + + /** + * create status reply (single line message) + * + * @param string|Status $message + * @return string + */ + public function __construct($message) + { + $this->message = $message; + } + + public function getValueNative() + { + return $this->message; + } + + public function getMessageSerialized(SerializerInterface $serializer) + { + return $serializer->getStatusMessage($this->message); + } +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/MessageBuffer.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/MessageBuffer.php new file mode 100644 index 0000000..c1e3001 --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/MessageBuffer.php @@ -0,0 +1,40 @@ +<?php + +namespace Clue\Redis\Protocol\Parser; + +use UnderflowException; + +class MessageBuffer implements ParserInterface +{ + private $parser; + private $incomingQueue = array(); + + public function __construct(ParserInterface $parser) + { + $this->parser = $parser; + } + + public function popIncomingModel() + { + if (!$this->incomingQueue) { + throw new UnderflowException('Incoming message queue is empty'); + } + return array_shift($this->incomingQueue); + } + + public function hasIncomingModel() + { + return ($this->incomingQueue) ? true : false; + } + + public function pushIncoming($data) + { + $ret = $this->parser->pushIncoming($data); + + foreach ($ret as $one) { + $this->incomingQueue []= $one; + } + + return $ret; + } +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/ParserException.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/ParserException.php new file mode 100644 index 0000000..e57c5bc --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/ParserException.php @@ -0,0 +1,10 @@ +<?php + +namespace Clue\Redis\Protocol\Parser; + +use UnexpectedValueException; + +class ParserException extends UnexpectedValueException +{ + +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/ParserInterface.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/ParserInterface.php new file mode 100644 index 0000000..a322719 --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/ParserInterface.php @@ -0,0 +1,28 @@ +<?php + +namespace Clue\Redis\Protocol\Parser; + +use Clue\Redis\Protocol\Model\ModelInterface; +use Clue\Redis\Protocol\Parser\ParserException; + +interface ParserInterface +{ + /** + * push a chunk of the redis protocol message into the buffer and parse + * + * You can push any number of bytes of a redis protocol message into the + * parser and it will try to parse messages from its data stream. So you can + * pass data directly from your socket stream and the parser will return the + * right amount of message model objects for you. + * + * If you pass an incomplete message, expect it to return an empty array. If + * your incomplete message is split to across multiple chunks, the parsed + * message model will be returned once the parser has sufficient data. + * + * @param string $dataChunk + * @return ModelInterface[] 0+ message models + * @throws ParserException if the message can not be parsed + * @see self::popIncomingModel() + */ + public function pushIncoming($dataChunk); +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/RequestParser.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/RequestParser.php new file mode 100644 index 0000000..a47d137 --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/RequestParser.php @@ -0,0 +1,125 @@ +<?php + +namespace Clue\Redis\Protocol\Parser; + +use Clue\Redis\Protocol\Parser\ParserException; +use Clue\Redis\Protocol\Model\Request; + +class RequestParser implements ParserInterface +{ + const CRLF = "\r\n"; + + private $incomingBuffer = ''; + private $incomingOffset = 0; + + public function pushIncoming($dataChunk) + { + $this->incomingBuffer .= $dataChunk; + + $parsed = array(); + + do { + $saved = $this->incomingOffset; + $message = $this->readRequest(); + if ($message === null) { + // restore previous position for next parsing attempt + $this->incomingOffset = $saved; + break; + } + + if ($message !== false) { + $parsed []= $message; + } + } while($this->incomingBuffer !== ''); + + if ($this->incomingOffset !== 0) { + $this->incomingBuffer = (string)substr($this->incomingBuffer, $this->incomingOffset); + $this->incomingOffset = 0; + } + + return $parsed; + } + + /** + * try to parse request from incoming buffer + * + * @throws ParserException if the incoming buffer is invalid + * @return Request|null + */ + private function readRequest() + { + $crlf = strpos($this->incomingBuffer, "\r\n", $this->incomingOffset); + if ($crlf === false) { + return null; + } + + // line starts with a multi-bulk header "*" + if (isset($this->incomingBuffer[$this->incomingOffset]) && $this->incomingBuffer[$this->incomingOffset] === '*') { + $line = substr($this->incomingBuffer, $this->incomingOffset + 1, $crlf - $this->incomingOffset + 1); + $this->incomingOffset = $crlf + 2; + $count = (int)$line; + + if ($count <= 0) { + return false; + } + $command = null; + $args = array(); + for ($i = 0; $i < $count; ++$i) { + $sub = $this->readBulk(); + if ($sub === null) { + return null; + } + if ($command === null) { + $command = $sub; + } else { + $args []= $sub; + } + } + return new Request($command, $args); + } + + // parse an old inline request instead + $line = substr($this->incomingBuffer, $this->incomingOffset, $crlf - $this->incomingOffset); + $this->incomingOffset = $crlf + 2; + + $args = preg_split('/ +/', trim($line, ' ')); + $command = array_shift($args); + + if ($command === '') { + return false; + } + + return new Request($command, $args); + } + + private function readBulk() + { + $crlf = strpos($this->incomingBuffer, "\r\n", $this->incomingOffset); + if ($crlf === false) { + return null; + } + + // line has to start with a bulk header "$" + if (!isset($this->incomingBuffer[$this->incomingOffset]) || $this->incomingBuffer[$this->incomingOffset] !== '$') { + throw new ParserException('ERR Protocol error: expected \'$\', got \'' . substr($this->incomingBuffer, $this->incomingOffset, 1) . '\''); + } + + $line = substr($this->incomingBuffer, $this->incomingOffset + 1, $crlf - $this->incomingOffset + 1); + $this->incomingOffset = $crlf + 2; + $size = (int)$line; + + if ($size < 0) { + throw new ParserException('ERR Protocol error: invalid bulk length'); + } + + if (!isset($this->incomingBuffer[$this->incomingOffset + $size + 1])) { + // check enough bytes + crlf are buffered + return null; + } + + $ret = substr($this->incomingBuffer, $this->incomingOffset, $size); + $this->incomingOffset += $size + 2; + + return $ret; + } +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/ResponseParser.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/ResponseParser.php new file mode 100644 index 0000000..19ac90c --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Parser/ResponseParser.php @@ -0,0 +1,151 @@ +<?php + +namespace Clue\Redis\Protocol\Parser; + +use Clue\Redis\Protocol\Parser\ParserInterface; +use Clue\Redis\Protocol\Model\ModelInterface; +use Clue\Redis\Protocol\Model\BulkReply; +use Clue\Redis\Protocol\Model\ErrorReply; +use Clue\Redis\Protocol\Model\IntegerReply; +use Clue\Redis\Protocol\Model\MultiBulkReply; +use Clue\Redis\Protocol\Model\StatusReply; +use Clue\Redis\Protocol\Parser\ParserException; + +/** + * Simple recursive redis wire protocol parser + * + * Heavily influenced by blocking parser implementation from jpd/redisent. + * + * @link https://github.com/jdp/redisent + * @link http://redis.io/topics/protocol + */ +class ResponseParser implements ParserInterface +{ + const CRLF = "\r\n"; + + private $incomingBuffer = ''; + private $incomingOffset = 0; + + public function pushIncoming($dataChunk) + { + $this->incomingBuffer .= $dataChunk; + + return $this->tryParsingIncomingMessages(); + } + + private function tryParsingIncomingMessages() + { + $messages = array(); + + do { + $message = $this->readResponse(); + if ($message === null) { + // restore previous position for next parsing attempt + $this->incomingOffset = 0; + break; + } + + $messages []= $message; + + $this->incomingBuffer = (string)substr($this->incomingBuffer, $this->incomingOffset); + $this->incomingOffset = 0; + } while($this->incomingBuffer !== ''); + + return $messages; + } + + private function readLine() + { + $pos = strpos($this->incomingBuffer, "\r\n", $this->incomingOffset); + + if ($pos === false) { + return null; + } + + $ret = (string)substr($this->incomingBuffer, $this->incomingOffset, $pos - $this->incomingOffset); + $this->incomingOffset = $pos + 2; + + return $ret; + } + + private function readLength($len) + { + $ret = substr($this->incomingBuffer, $this->incomingOffset, $len); + if (strlen($ret) !== $len) { + return null; + } + + $this->incomingOffset += $len; + + return $ret; + } + + /** + * try to parse response from incoming buffer + * + * ripped from jdp/redisent, with some minor modifications to read from + * the incoming buffer instead of issuing a blocking fread on a stream + * + * @throws ParserException if the incoming buffer is invalid + * @return ModelInterface|null + * @link https://github.com/jdp/redisent + */ + private function readResponse() + { + /* Parse the response based on the reply identifier */ + $reply = $this->readLine(); + if ($reply === null) { + return null; + } + switch (substr($reply, 0, 1)) { + /* Error reply */ + case '-': + $response = new ErrorReply(substr($reply, 1)); + break; + /* Inline reply */ + case '+': + $response = new StatusReply(substr($reply, 1)); + break; + /* Bulk reply */ + case '$': + $size = (int)substr($reply, 1); + if ($size === -1) { + return new BulkReply(null); + } + $data = $this->readLength($size); + if ($data === null) { + return null; + } + if ($this->readLength(2) === null) { /* discard crlf */ + return null; + } + $response = new BulkReply($data); + break; + /* Multi-bulk reply */ + case '*': + $count = (int)substr($reply, 1); + if ($count === -1) { + return new MultiBulkReply(null); + } + $response = array(); + for ($i = 0; $i < $count; $i++) { + $sub = $this->readResponse(); + if ($sub === null) { + return null; + } + $response []= $sub; + } + $response = new MultiBulkReply($response); + break; + /* Integer reply */ + case ':': + $response = new IntegerReply(substr($reply, 1)); + break; + default: + throw new ParserException('Invalid message can not be parsed: "' . $reply . '"'); + break; + } + /* Party on */ + return $response; + } +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Serializer/RecursiveSerializer.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Serializer/RecursiveSerializer.php new file mode 100644 index 0000000..6e25125 --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Serializer/RecursiveSerializer.php @@ -0,0 +1,111 @@ +<?php + +namespace Clue\Redis\Protocol\Serializer; + +use Clue\Redis\Protocol\Model\StatusReply; +use InvalidArgumentException; +use Exception; +use Clue\Redis\Protocol\Model\BulkReply; +use Clue\Redis\Protocol\Model\IntegerReply; +use Clue\Redis\Protocol\Model\ErrorReply; +use Clue\Redis\Protocol\Model\MultiBulkReply; +use Clue\Redis\Protocol\Model\ModelInterface; +use Clue\Redis\Protocol\Model\Request; + +class RecursiveSerializer implements SerializerInterface +{ + const CRLF = "\r\n"; + + public function getRequestMessage($command, array $args = array()) + { + $data = '*' . (count($args) + 1) . "\r\n$" . strlen($command) . "\r\n" . $command . "\r\n"; + foreach ($args as $arg) { + $data .= '$' . strlen($arg) . "\r\n" . $arg . "\r\n"; + } + return $data; + } + + public function createRequestModel($command, array $args = array()) + { + return new Request($command, $args); + } + + public function getReplyMessage($data) + { + if (is_string($data) || $data === null) { + return $this->getBulkMessage($data); + } else if (is_int($data) || is_float($data) || is_bool($data)) { + return $this->getIntegerMessage($data); + } else if ($data instanceof Exception) { + return $this->getErrorMessage($data->getMessage()); + } else if (is_array($data)) { + return $this->getMultiBulkMessage($data); + } else { + throw new InvalidArgumentException('Invalid data type passed for serialization'); + } + } + + public function createReplyModel($data) + { + if (is_string($data) || $data === null) { + return new BulkReply($data); + } else if (is_int($data) || is_float($data) || is_bool($data)) { + return new IntegerReply($data); + } else if ($data instanceof Exception) { + return new ErrorReply($data->getMessage()); + } else if (is_array($data)) { + $models = array(); + foreach ($data as $one) { + $models []= $this->createReplyModel($one); + } + return new MultiBulkReply($models); + } else { + throw new InvalidArgumentException('Invalid data type passed for serialization'); + } + } + + public function getBulkMessage($data) + { + if ($data === null) { + /* null bulk reply */ + return '$-1' . self::CRLF; + } + /* bulk reply */ + return '$' . strlen($data) . self::CRLF . $data . self::CRLF; + } + + public function getErrorMessage($data) + { + /* error status reply */ + return '-' . $data . self::CRLF; + } + + public function getIntegerMessage($data) + { + return ':' . (int)$data . self::CRLF; + } + + public function getMultiBulkMessage($data) + { + if ($data === null) { + /* null multi bulk reply */ + return '*-1' . self::CRLF; + } + /* multi bulk reply */ + $ret = '*' . count($data) . self::CRLF; + foreach ($data as $one) { + if ($one instanceof ModelInterface) { + $ret .= $one->getMessageSerialized($this); + } else { + $ret .= $this->getReplyMessage($one); + } + } + return $ret; + } + + public function getStatusMessage($data) + { + /* status reply */ + return '+' . $data . self::CRLF; + } +} diff --git a/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Serializer/SerializerInterface.php b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Serializer/SerializerInterface.php new file mode 100644 index 0000000..bb7cb3e --- /dev/null +++ b/vendor/clue/redis-protocol/src/Clue/Redis/Protocol/Serializer/SerializerInterface.php @@ -0,0 +1,83 @@ +<?php + +namespace Clue\Redis\Protocol\Serializer; + +use Clue\Redis\Protocol\Model\ErrorReplyException; +use Clue\Redis\Protocol\Model\ModelInterface; +use Clue\Redis\Protocol\Model\MultiBulkReply; + +interface SerializerInterface +{ + /** + * create a serialized unified request protocol message + * + * This is the *one* method most redis client libraries will likely want to + * use in order to send a serialized message (a request) over the* wire to + * your redis server instance. + * + * This method should be used in favor of constructing a request model and + * then serializing it. While its effect might be equivalent, this method + * is likely to (i.e. it /could/) provide a faster implementation. + * + * @param string $command + * @param array $args + * @return string + * @see self::createRequestMessage() + */ + public function getRequestMessage($command, array $args = array()); + + /** + * create a unified request protocol message model + * + * @param string $command + * @param array $args + * @return MultiBulkReply + */ + public function createRequestModel($command, array $args = array()); + + /** + * create a serialized unified protocol reply message + * + * This is most useful for a redis server implementation which needs to + * process client requests and send resulting reply messages. + * + * This method does its best to guess to right reply type and then returns + * a serialized version of the message. It follows the "redis to lua + * conversion table" (see link) which means most basic types can be mapped + * as is. + * + * This method should be used in favor of constructing a reply model and + * then serializing it. While its effect might be equivalent, this method + * is likely to (i.e. it /could/) provide a faster implementation. + * + * Note however, you may still want to explicitly create a nested reply + * model hierarchy if you need more control over the serialized message. For + * instance, a null value will always be returned as a Null-Bulk-Reply, so + * there's no way to express a Null-Multi-Bulk-Reply, unless you construct + * it explicitly. + * + * @param mixed $data + * @return string + * @see self::createReplyModel() + * @link http://redis.io/commands/eval + */ + public function getReplyMessage($data); + + /** + * create response message by determining datatype from given argument + * + * @param mixed $data + * @return ModelInterface + */ + public function createReplyModel($data); + + public function getBulkMessage($data); + + public function getErrorMessage($data); + + public function getIntegerMessage($data); + + public function getMultiBulkMessage($data); + + public function getStatusMessage($data); +} |