Loading...
Searching...
No Matches
parser.hpp
1/* Copyright (c) 2018-2024 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
12#include <boost/system/error_code.hpp>
13
14#include <array>
15#include <cstdint>
16#include <optional>
17#include <string_view>
18
19namespace boost::redis::resp3 {
20
21class parser {
22public:
23 using node_type = basic_node<std::string_view>;
24 using result = std::optional<node_type>;
25
26 static constexpr std::size_t max_embedded_depth = 5;
27 static constexpr std::string_view sep = "\r\n";
28
29private:
30 // The current depth. Simple data types will have depth 0, whereas
31 // the elements of aggregates will have depth 1. Embedded types
32 // will have increasing depth.
33 std::size_t depth_;
34
35 // The parser supports up to 5 levels of nested structures. The
36 // first element in the sizes stack is a sentinel and must be
37 // different from 1.
38 std::array<std::size_t, max_embedded_depth + 1> sizes_;
39
40 // Contains the length expected in the next bulk read.
41 std::size_t bulk_length_;
42
43 // The type of the next bulk. Contains type::invalid if no bulk is
44 // expected.
45 type bulk_;
46
47 // The number of bytes consumed from the buffer.
48 std::size_t consumed_;
49
50 // Returns the number of bytes that have been consumed.
51 auto consume_impl(type t, std::string_view elem, system::error_code& ec) -> node_type;
52
53 void commit_elem() noexcept;
54
55 // The bulk type expected in the next read. If none is expected
56 // returns type::invalid.
57 [[nodiscard]]
58 auto bulk_expected() const noexcept -> bool
59 {
60 return bulk_ != type::invalid;
61 }
62
63public:
64 parser();
65
66 // Returns true when the parser is done with the current message.
67 [[nodiscard]]
68 auto done() const noexcept -> bool;
69
70 auto get_suggested_buffer_growth(std::size_t hint) const noexcept -> std::size_t;
71
72 auto get_consumed() const noexcept -> std::size_t;
73
74 auto consume(std::string_view view, system::error_code& ec) noexcept -> result;
75
76 void reset();
77};
78
79// Returns false if more data is needed. If true is returned the
80// parser is either done or an error occured, that can be checked on
81// ec.
82template <class Adapter>
83bool parse(resp3::parser& p, std::string_view const& msg, Adapter& adapter, system::error_code& ec)
84{
85 while (!p.done()) {
86 auto const res = p.consume(msg, ec);
87 if (ec)
88 return true;
89
90 if (!res)
91 return false;
92
93 adapter(res.value(), ec);
94 if (ec)
95 return true;
96 }
97
98 return true;
99}
100
101} // namespace boost::redis::resp3
102
103#endif // BOOST_REDIS_RESP3_PARSER_HPP
type
RESP3 data types.
Definition type.hpp:24