MySQL 8.0.37
Source Code Documentation
classic_protocol_codec_wire.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2019, 2024, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is designed to work with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have either included with
14 the program or referenced in the documentation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
26#ifndef MYSQL_ROUTER_CLASSIC_PROTOCOL_CODEC_WIRE_H_
27#define MYSQL_ROUTER_CLASSIC_PROTOCOL_CODEC_WIRE_H_
28
29// codecs for classic_protocol::wire::
30
31#include <algorithm> // find
32#include <cstddef> // size_t
33#include <cstdint> // uint8_t
34#include <system_error> // error_code
35#include <type_traits>
36#include <utility> // move
37
40#include "mysql/harness/stdx/type_traits.h" // endian
44
45namespace classic_protocol {
46/**
47 * codec of a FixedInt.
48 *
49 * classic proto uses 1, 2, 3, 4, 8 for IntSize
50 */
51template <int IntSize>
52class Codec<borrowable::wire::FixedInt<IntSize>> {
53 public:
54 static constexpr size_t int_size{IntSize};
55
57
58 constexpr Codec(value_type v, capabilities::value_type /* caps */) : v_{v} {}
59
60 /**
61 * size of the encoded object.
62 */
63 static constexpr size_t size() noexcept { return int_size; }
64
65 /**
66 * encode value_type into buffer.
67 */
70 if (buffer.size() < int_size) {
71 return stdx::make_unexpected(make_error_code(std::errc::no_buffer_space));
72 }
73
74 auto int_val = v_.value();
75
77 int_val = stdx::byteswap(int_val);
78 }
79
80 std::copy_n(reinterpret_cast<const std::byte *>(&int_val), int_size,
81 static_cast<std::byte *>(buffer.data()));
82
83 return int_size;
84 }
85
86 /**
87 * maximum bytes which may scanned by the decoder.
88 */
89 static constexpr size_t max_size() noexcept { return int_size; }
90
93 if (buffer.size() < int_size) {
94 // not enough data in buffers.
97 }
98
99 typename value_type::value_type value{};
100
101 std::copy_n(static_cast<const std::byte *>(buffer.data()), int_size,
102 reinterpret_cast<std::byte *>(&value));
103
105 value = stdx::byteswap(value);
106 }
107
108 return std::make_pair(int_size, value_type(value));
109 }
110
111 private:
113};
114
115/**
116 * codec for variable length integers.
117 *
118 * note: encoded as little endian
119 *
120 * 0x00
121 * ...
122 * 0xfa -> 0xfa
123 * 0xfb [undefined]
124 * 0xfc 0x.. 0x..
125 * 0xfd 0x.. 0x.. 0x..
126 *
127 * 3.21:
128 * 0xfe 0x.. 0x.. 0x.. 0x.. 0x00
129 * [1 + 5 bytes read, only 4 bytes used]
130 *
131 * 4.0:
132 * 0xfe 0x.. 0x.. 0x.. 0x.. 0x.. 0x.. 0x.. 0x..
133 * [1 + 8 bytes read, only 4 bytes used]
134 */
135template <>
136class Codec<borrowable::wire::VarInt>
137 : public impl::EncodeBase<Codec<borrowable::wire::VarInt>> {
138 template <class Accumulator>
139 constexpr auto accumulate_fields(Accumulator &&accu) const {
140 if (v_.value() < 251) {
141 return accu.step(borrowable::wire::FixedInt<1>(v_.value())).result();
142 } else if (v_.value() < 1 << 16) {
143 return accu.step(borrowable::wire::FixedInt<1>(varint_16))
144 .step(borrowable::wire::FixedInt<2>(v_.value()))
145 .result();
146 } else if (v_.value() < (1 << 24)) {
147 return accu.step(borrowable::wire::FixedInt<1>(varint_24))
148 .step(borrowable::wire::FixedInt<3>(v_.value()))
149 .result();
150 } else {
151 return accu.step(borrowable::wire::FixedInt<1>(varint_64))
152 .step(borrowable::wire::FixedInt<8>(v_.value()))
153 .result();
154 }
155 }
156
157 public:
158 static constexpr uint8_t varint_16{0xfc};
159 static constexpr uint8_t varint_24{0xfd};
160 static constexpr uint8_t varint_64{0xfe};
163
164 friend __base;
165
167 : __base{caps}, v_{v} {}
168
169 static constexpr size_t max_size() noexcept { return 9; }
170
174
175 // length
176 auto first_byte_res = accu.template step<borrowable::wire::FixedInt<1>>();
177 if (!first_byte_res) return stdx::make_unexpected(first_byte_res.error());
178
179 auto first_byte = first_byte_res->value();
180
181 if (first_byte < 251) {
182 return std::make_pair(accu.result().value(), value_type(first_byte));
183 } else if (first_byte == varint_16) {
184 auto value_res = accu.template step<borrowable::wire::FixedInt<2>>();
185 if (!value_res) return stdx::make_unexpected(value_res.error());
186 return std::make_pair(accu.result().value(),
187 value_type(value_res->value()));
188 } else if (first_byte == varint_24) {
189 auto value_res = accu.template step<borrowable::wire::FixedInt<3>>();
190 if (!value_res) return stdx::make_unexpected(value_res.error());
191 return std::make_pair(accu.result().value(),
192 value_type(value_res->value()));
193 } else if (first_byte == varint_64) {
194 auto value_res = accu.template step<borrowable::wire::FixedInt<8>>();
195 if (!value_res) return stdx::make_unexpected(value_res.error());
196 return std::make_pair(accu.result().value(),
197 value_type(value_res->value()));
198 }
199
201 }
202
203 private:
205};
206
207/**
208 * codec for a NULL value in the Resultset.
209 */
210template <>
211class Codec<borrowable::wire::Null>
212 : public Codec<borrowable::wire::FixedInt<1>> {
213 public:
215
216 static constexpr uint8_t nul_byte{0xfb};
217
219 : Codec<borrowable::wire::FixedInt<1>>(nul_byte, caps) {}
220
223 if (buffer.size() < 1) {
226 }
227
228 const uint8_t nul_val = *static_cast<const uint8_t *>(buffer.data());
229
230 if (nul_val != nul_byte) {
232 }
233
234 return std::make_pair(1, value_type());
235 }
236};
237
238/**
239 * codec for ignorable bytes.
240 *
241 * limited by length or buffer.size()
242 */
243template <>
244class Codec<void> {
245 public:
246 using value_type = size_t;
247
248 Codec(value_type val, capabilities::value_type caps) : v_(val), caps_{caps} {}
249
250 size_t size() const noexcept { return v_; }
251
252 static size_t max_size() noexcept {
253 return std::numeric_limits<size_t>::max();
254 }
255
257 const net::mutable_buffer &buffer) const {
258 if (buffer.size() < size()) {
259 return stdx::make_unexpected(make_error_code(std::errc::no_buffer_space));
260 }
261
262 auto *first = static_cast<std::uint8_t *>(buffer.data());
263 auto *last = first + size();
264
265 // fill with 0
266 std::fill(first, last, 0);
267
268 return size();
269 }
270
273 size_t buf_size = buffer.size();
274
275 return std::make_pair(buf_size, buf_size);
276 }
277
278 private:
281};
282
283/**
284 * codec for wire::String.
285 *
286 * limited by length or buffer.size()
287 */
288template <bool Borrowed>
289class Codec<borrowable::wire::String<Borrowed>> {
290 public:
292
294 : v_{std::move(v)}, caps_{caps} {}
295
296 constexpr size_t size() const noexcept { return v_.value().size(); }
297
298 static size_t max_size() noexcept {
299 // we actually don't know what the size of the null-term string is ... until
300 // the end of the buffer
301 return std::numeric_limits<size_t>::max();
302 }
303
305 const net::mutable_buffer &buffer) const {
306 if (buffer.size() < size()) {
307 return stdx::make_unexpected(make_error_code(std::errc::no_buffer_space));
308 }
309
310 // in -> out
311 std::copy_n(reinterpret_cast<const std::byte *>(v_.value().data()), size(),
312 static_cast<std::byte *>(buffer.data()));
313
314 return size();
315 }
316
319 const size_t buf_size = buffer_size(buffer);
320
321 if (0 == buf_size) return std::make_pair(buf_size, value_type());
322
323 return std::make_pair(
324 buf_size,
325 value_type({static_cast<const char *>(buffer.data()), buffer.size()}));
326 }
327
328 private:
331};
332
333/**
334 * codec for string with known length.
335 *
336 * - varint of string length
337 * - string of length
338 */
339template <bool Borrowed>
340class Codec<borrowable::wire::VarString<Borrowed>>
341 : public impl::EncodeBase<Codec<borrowable::wire::VarString<Borrowed>>> {
342 template <class Accumulator>
343 constexpr auto accumulate_fields(Accumulator &&accu) const {
344 return accu.step(borrowable::wire::VarInt(v_.value().size()))
345 .step(borrowable::wire::String<Borrowed>(v_.value()))
346 .result();
347 }
348
349 public:
352
353 friend base_type;
354
356 : base_type(caps), v_{std::move(val)} {}
357
358 static size_t max_size() noexcept {
359 // we actually don't know what the size of the null-term string is ...
360 // until the end of the buffer
361 return std::numeric_limits<size_t>::max();
362 }
363
367 // decode the length
368 auto var_string_len_res = accu.template step<borrowable::wire::VarInt>();
369 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
370
371 // decode string of length
372 auto var_string_res =
373 accu.template step<borrowable::wire::String<Borrowed>>(
374 var_string_len_res->value());
375
376 if (!accu.result()) return stdx::make_unexpected(accu.result().error());
377
378 return std::make_pair(accu.result().value(),
379 value_type(var_string_res->value()));
380 }
381
382 private:
384};
385
386/**
387 * codec for 0-terminated string.
388 */
389template <bool Borrowed>
390class Codec<borrowable::wire::NulTermString<Borrowed>>
391 : public impl::EncodeBase<
392 Codec<borrowable::wire::NulTermString<Borrowed>>> {
393 template <class Accumulator>
394 constexpr auto accumulate_fields(Accumulator &&accu) const {
395 return accu.template step<borrowable::wire::String<Borrowed>>(v_)
396 .template step<borrowable::wire::FixedInt<1>>(0)
397 .result();
398 }
399
400 public:
403
404 friend base_type;
405
407 : base_type(caps), v_{std::move(val)} {}
408
409 static size_t max_size() noexcept {
410 // we actually don't know what the size of the null-term string is ...
411 // until the end of the buffer
412 return std::numeric_limits<size_t>::max();
413 }
414
417 // length of the string before the \0
418
419 const auto *first = static_cast<const uint8_t *>(buffer.data());
420 const auto *last = first + buffer.size();
421
422 const auto *pos = std::find(first, last, '\0');
423 if (pos == last) {
424 // no 0-term found
427 }
428
429 // \0 was found
430 size_t len = std::distance(first, pos);
431 if (len == 0) {
432 return std::make_pair(len + 1, value_type()); // consume the \0 too
433 }
434
435 return std::make_pair(len + 1,
436 value_type({static_cast<const char *>(buffer.data()),
437 len})); // consume the \0 too
438 }
439
440 private:
442};
443
444} // namespace classic_protocol
445
446#endif
constexpr Codec(value_type v, capabilities::value_type)
Definition: classic_protocol_codec_wire.h:58
static constexpr size_t max_size() noexcept
maximum bytes which may scanned by the decoder.
Definition: classic_protocol_codec_wire.h:89
stdx::expected< size_t, std::error_code > encode(net::mutable_buffer buffer) const
encode value_type into buffer.
Definition: classic_protocol_codec_wire.h:68
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type)
Definition: classic_protocol_codec_wire.h:91
const value_type v_
Definition: classic_protocol_codec_wire.h:112
static constexpr size_t size() noexcept
size of the encoded object.
Definition: classic_protocol_codec_wire.h:63
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_wire.h:394
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type)
Definition: classic_protocol_codec_wire.h:415
friend base_type
Definition: classic_protocol_codec_wire.h:404
static size_t max_size() noexcept
Definition: classic_protocol_codec_wire.h:409
const value_type v_
Definition: classic_protocol_codec_wire.h:441
constexpr Codec(value_type val, capabilities::value_type caps)
Definition: classic_protocol_codec_wire.h:406
Codec(value_type, capabilities::value_type caps)
Definition: classic_protocol_codec_wire.h:218
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type)
Definition: classic_protocol_codec_wire.h:221
const capabilities::value_type caps_
Definition: classic_protocol_codec_wire.h:330
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_wire.h:293
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type)
Definition: classic_protocol_codec_wire.h:317
stdx::expected< size_t, std::error_code > encode(const net::mutable_buffer &buffer) const
Definition: classic_protocol_codec_wire.h:304
constexpr size_t size() const noexcept
Definition: classic_protocol_codec_wire.h:296
const value_type v_
Definition: classic_protocol_codec_wire.h:329
static size_t max_size() noexcept
Definition: classic_protocol_codec_wire.h:298
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_wire.h:166
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_wire.h:139
const value_type v_
Definition: classic_protocol_codec_wire.h:204
friend __base
Definition: classic_protocol_codec_wire.h:164
static constexpr size_t max_size() noexcept
Definition: classic_protocol_codec_wire.h:169
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_wire.h:171
const value_type v_
Definition: classic_protocol_codec_wire.h:383
constexpr Codec(value_type val, capabilities::value_type caps)
Definition: classic_protocol_codec_wire.h:355
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_wire.h:343
friend base_type
Definition: classic_protocol_codec_wire.h:353
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type caps)
Definition: classic_protocol_codec_wire.h:364
static size_t max_size() noexcept
Definition: classic_protocol_codec_wire.h:358
Codec(value_type val, capabilities::value_type caps)
Definition: classic_protocol_codec_wire.h:248
size_t size() const noexcept
Definition: classic_protocol_codec_wire.h:250
static stdx::expected< std::pair< size_t, value_type >, std::error_code > decode(const net::const_buffer &buffer, capabilities::value_type)
Definition: classic_protocol_codec_wire.h:271
stdx::expected< size_t, std::error_code > encode(const net::mutable_buffer &buffer) const
Definition: classic_protocol_codec_wire.h:256
const capabilities::value_type caps_
Definition: classic_protocol_codec_wire.h:280
const value_type v_
Definition: classic_protocol_codec_wire.h:279
size_t value_type
Definition: classic_protocol_codec_wire.h:246
static size_t max_size() noexcept
Definition: classic_protocol_codec_wire.h:252
Codec for a type.
Definition: classic_protocol_codec_base.h:72
Definition: classic_protocol_wire.h:106
Definition: classic_protocol_wire.h:112
Definition: classic_protocol_wire.h:118
Definition: classic_protocol_wire.h:130
Definition: classic_protocol_wire.h:103
Definition: classic_protocol_wire.h:59
Definition: classic_protocol_wire.h:135
Definition: classic_protocol_wire.h:38
Definition: classic_protocol_wire.h:97
Definition: classic_protocol_wire.h:65
Generator of decoded Types of a buffer.
Definition: classic_protocol_codec_base.h:153
result_type result() const
get result of the step().
Definition: classic_protocol_codec_base.h:219
CRTP base for the Codec's encode part.
Definition: classic_protocol_codec_base.h:375
Definition: buffer.h:135
Definition: buffer.h:113
void * data() const noexcept
Definition: buffer.h:119
size_t size() const noexcept
Definition: buffer.h:120
constexpr const value_type & value() const &
Definition: expected.h:688
constexpr const error_type & error() const &
Definition: expected.h:737
constexpr DWORD buf_size
Definition: create_def.cc:228
unsigned char byte
Blob class.
Definition: common.h:151
uint16_t value_type
Definition: vt100.h:184
borrowable::binary::Null Null
Definition: classic_protocol_binary.h:337
borrowable::wire::FixedInt< Size > FixedInt
Definition: classic_protocol_wire.h:147
borrowable::wire::VarInt VarInt
Definition: classic_protocol_wire.h:148
std::bitset< 32 > value_type
Definition: classic_protocol_constants.h:73
Definition: classic_protocol_binary.h:39
std::error_code make_error_code(codec_errc e) noexcept
Definition: classic_protocol_codec_error.h:86
const byte * find(const Pages *pages, const page_id_t &page_id) noexcept
Find a doublewrite copy of a page.
Definition: buf0dblwr.cc:3564
bool distance(const dd::Spatial_reference_system *srs, const Geometry *g1, const Geometry *g2, double *distance, bool *is_null) noexcept
Computes the distance between two geometries.
Definition: distance.cc:40
mutable_buffer buffer(void *p, size_t n) noexcept
Definition: buffer.h:420
size_t buffer_size(const ConstBufferSequence &buffers) noexcept
Definition: buffer.h:315
Definition: gcs_xcom_synode.h:64
constexpr auto make_unexpected(E &&e) -> unexpected< std::decay_t< E > >
Definition: expected.h:125
constexpr std::enable_if_t< std::is_integral< IntegerType >::value, IntegerType > byteswap(IntegerType t) noexcept
Definition: bit.h:142