mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-11 10:25:47 +02:00
Add redis parser + test
This commit is contained in:
parent
2bce379341
commit
f2bc27e283
9 changed files with 958 additions and 1 deletions
91
server/redis_parser.h
Normal file
91
server/redis_parser.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
// Copyright 2021, Beeri 15. All rights reserved.
|
||||
// Author: Roman Gershman (romange@gmail.com)
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <absl/container/inlined_vector.h>
|
||||
|
||||
#include "resp_expr.h"
|
||||
|
||||
namespace dfly {
|
||||
|
||||
/**
|
||||
* @brief Zero-copy (best-effort) parser.
|
||||
*
|
||||
*/
|
||||
class RedisParser {
|
||||
public:
|
||||
enum Result {
|
||||
OK,
|
||||
INPUT_PENDING,
|
||||
BAD_ARRAYLEN,
|
||||
BAD_BULKLEN,
|
||||
BAD_STRING,
|
||||
BAD_INT
|
||||
};
|
||||
using Buffer = RespExpr::Buffer;
|
||||
|
||||
explicit RedisParser() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parses str into res. "consumed" stores number of bytes consumed from str.
|
||||
*
|
||||
* A caller should not invalidate str if the parser returns RESP_OK as long as he continues
|
||||
* accessing res. However, if parser returns MORE_INPUT a caller may discard consumed
|
||||
* part of str because parser caches the intermediate state internally according to 'consumed'
|
||||
* result.
|
||||
*
|
||||
* Note: A parser does not always guarantee progress, i.e. if a small buffer was passed it may
|
||||
* returns MORE_INPUT with consumed == 0.
|
||||
*
|
||||
*/
|
||||
|
||||
Result Parse(Buffer str, uint32_t* consumed, RespVec* res);
|
||||
|
||||
size_t stash_size() const { return stash_.size(); }
|
||||
const std::vector<std::unique_ptr<RespVec>>& stash() const { return stash_;}
|
||||
|
||||
private:
|
||||
void InitStart(uint8_t prefix_b, RespVec* res);
|
||||
void StashState(RespVec* res);
|
||||
|
||||
// Skips the first character (*).
|
||||
Result ConsumeArrayLen(Buffer str);
|
||||
Result ParseArg(Buffer str);
|
||||
Result ConsumeBulk(Buffer str);
|
||||
Result ParseInline(Buffer str);
|
||||
|
||||
// Updates last_consumed_
|
||||
Result ParseNum(Buffer str, int64_t* res);
|
||||
void HandleFinishArg();
|
||||
void ExtendLastString(Buffer str);
|
||||
|
||||
enum State : uint8_t {
|
||||
INIT_S = 0,
|
||||
INLINE_S,
|
||||
ARRAY_LEN_S,
|
||||
PARSE_ARG_S, // Parse [$:+-]string\r\n
|
||||
BULK_STR_S,
|
||||
FINISH_ARG_S,
|
||||
CMD_COMPLETE_S,
|
||||
};
|
||||
|
||||
State state_ = INIT_S;
|
||||
Result last_result_ = OK;
|
||||
|
||||
uint32_t last_consumed_ = 0;
|
||||
uint32_t bulk_len_ = 0;
|
||||
uint32_t last_stashed_level_ = 0, last_stashed_index_ = 0;
|
||||
|
||||
// expected expression length, pointer to expression vector.
|
||||
absl::InlinedVector<std::pair<uint32_t, RespVec*>, 4> parse_stack_;
|
||||
std::vector<std::unique_ptr<RespVec>> stash_;
|
||||
|
||||
using BlobPtr = std::unique_ptr<uint8_t[]>;
|
||||
std::vector<BlobPtr> buf_stash_;
|
||||
RespVec* cached_expr_ = nullptr;
|
||||
bool is_broken_token_ = false;
|
||||
};
|
||||
|
||||
} // namespace dfly
|
Loading…
Add table
Add a link
Reference in a new issue