boost_redis 1.4.2
A redis client library
parser.hpp
1/* Copyright (c) 2018-2022 Marcelo Zimbres Silva (mzimbres@gmail.com)
2 *
3 * Distributed under the Boost Software License, Version 1.0. (See
4 * accompanying file LICENSE.txt)
5 */
6
7#ifndef BOOST_REDIS_RESP3_PARSER_HPP
8#define BOOST_REDIS_RESP3_PARSER_HPP
9
10#include <boost/redis/resp3/node.hpp>
11#include <boost/system/error_code.hpp>
12#include <array>
13#include <limits>
14#include <string_view>
15#include <cstdint>
16#include <optional>
17
18namespace boost::redis::resp3 {
19
20using int_type = std::uint64_t;
21
22class parser {
23public:
24 using node_type = basic_node<std::string_view>;
25 using result = std::optional<node_type>;
26
27 static constexpr std::size_t max_embedded_depth = 5;
28 static constexpr std::string_view sep = "\r\n";
29
30private:
31 // The current depth. Simple data types will have depth 0, whereas
32 // the elements of aggregates will have depth 1. Embedded types
33 // will have increasing depth.
34 std::size_t depth_ = 0;
35
36 // The parser supports up to 5 levels of nested structures. The
37 // first element in the sizes stack is a sentinel and must be
38 // different from 1.
39 std::array<std::size_t, max_embedded_depth + 1> sizes_ = {{1}};
40
41 // Contains the length expected in the next bulk read.
42 int_type bulk_length_ = (std::numeric_limits<unsigned long>::max)();
43
44 // The type of the next bulk. Contains type::invalid if no bulk is
45 // expected.
46 type bulk_ = type::invalid;
47
48 // The number of bytes consumed from the buffer.
49 std::size_t consumed_ = 0;
50
51 // Returns the number of bytes that have been consumed.
52 auto consume_impl(type t, std::string_view elem, system::error_code& ec) -> node_type;
53
54 void commit_elem() noexcept;
55
56 // The bulk type expected in the next read. If none is expected
57 // returns type::invalid.
58 [[nodiscard]]
59 auto bulk_expected() const noexcept -> bool
60 { return bulk_ != type::invalid; }
61
62public:
63 parser();
64
65 // Returns true when the parser is done with the current message.
66 [[nodiscard]]
67 auto done() const noexcept -> bool;
68
69 auto get_suggested_buffer_growth(std::size_t hint) const noexcept -> std::size_t;
70
71 auto get_consumed() const noexcept -> std::size_t;
72
73 auto consume(std::string_view view, system::error_code& ec) noexcept -> result;
74};
75
76template <class Adapter>
77bool
78parse(
79 resp3::parser& p,
80 std::string_view const& msg,
81 Adapter& adapter,
82 system::error_code& ec)
83{
84 while (!p.done()) {
85 auto const res = p.consume(msg, ec);
86 if (ec)
87 return true;
88
89 if (!res)
90 return false;
91
92 adapter(res.value(), ec);
93 if (ec)
94 return true;
95 }
96
97 return true;
98}
99
100} // boost::redis::resp3
101
102#endif // BOOST_REDIS_RESP3_PARSER_HPP
type
RESP3 data types.
Definition: type.hpp:23
system::result< Value, error > result
Stores response to individual Redis commands.
Definition: result.hpp:56