Kagome
Polkadot Runtime Engine in C++17
jrpc_handle_batch.cpp
Go to the documentation of this file.
1 
7 
8 #include <jsonrpc-lean/server.h>
9 
10 namespace kagome::api {
15  template <typename Cb>
16  struct Parser {
17  Cb cb;
18 
19  rapidjson::MemoryStream stream{nullptr, 0};
20  size_t level = 0;
21  size_t begin = 0;
22 
23  bool parse(std::string_view request) {
24  stream = {request.data(), request.size()};
25  rapidjson::Reader reader;
26  return reader.Parse(stream, *this);
27  }
28 
29  bool scalar() const {
30  return level > 1;
31  }
32  bool Null() {
33  return scalar();
34  }
35  bool Bool(bool) {
36  return scalar();
37  }
38  bool Int(int) {
39  return scalar();
40  }
41  bool Uint(unsigned) {
42  return scalar();
43  }
44  bool Int64(int64_t) {
45  return scalar();
46  }
47  bool Uint64(uint64_t) {
48  return scalar();
49  }
50  bool Double(double) {
51  return scalar();
52  }
53  bool RawNumber(const char *, size_t, bool) {
54  return scalar();
55  }
56  bool String(const char *, size_t, bool) {
57  return scalar();
58  }
59  bool Key(const char *, size_t, bool) {
60  return scalar();
61  }
62  bool StartArray() {
63  if (level == 1) {
64  return false;
65  }
66  ++level;
67  return true;
68  }
69  bool EndArray(size_t) {
70  --level;
71  return true;
72  }
73  bool StartObject() {
74  if (level == 0) {
75  return false;
76  }
77  if (level == 1) {
78  begin = stream.Tell() - 1;
79  }
80  ++level;
81  return true;
82  }
83  bool EndObject(size_t) {
84  --level;
85  if (level == 1) {
86  const size_t end = stream.Tell();
87  std::string_view request(stream.begin_ + begin, end - begin);
88  cb(request);
89  }
90  return true;
91  }
92  };
93 
94  JrpcHandleBatch::JrpcHandleBatch(jsonrpc::Server &handler,
95  std::string_view request) {
96  std::string request_string;
97  if (!request.empty() && request[0] == '[') {
98  const auto cb = [&](std::string_view request) {
99  request_string = request;
100  auto formatted = handler.HandleRequest(request_string);
101  if (formatted->GetSize() == 0) {
102  return;
103  }
104  if (batch_.empty()) {
105  batch_.push_back('[');
106  } else {
107  batch_.push_back(',');
108  }
109  batch_.append(formatted->GetData(), formatted->GetSize());
110  };
111  Parser<decltype(cb) &> parser{cb};
112  if (parser.parse(request)) {
113  if (!batch_.empty()) {
114  batch_.push_back(']');
115  }
116  return;
117  }
118  }
119  request_string = request;
120  formatted_ = handler.HandleRequest(request_string);
121  }
122 
123  std::string_view JrpcHandleBatch::response() const {
124  if (formatted_ == nullptr) {
125  return batch_;
126  }
127  return {formatted_->GetData(), formatted_->GetSize()};
128  }
129 } // namespace kagome::api
bool Key(const char *, size_t, bool)
bool RawNumber(const char *, size_t, bool)
std::string_view response() const
bool parse(std::string_view request)
bool String(const char *, size_t, bool)
rapidjson::MemoryStream stream
JrpcHandleBatch(jsonrpc::Server &handler, std::string_view request)