MySQL 8.4.1
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 <bit> // endian
33#include <cstddef> // size_t
34#include <cstdint> // uint8_t
35#include <system_error> // error_code
36#include <type_traits>
37#include <utility> // move
38
40#include "mysql/harness/stdx/bit.h" // byteswap
45
46namespace classic_protocol {
47/**
48 * codec of a FixedInt.
49 *
50 * classic proto uses 1, 2, 3, 4, 8 for IntSize
51 */
52template <int IntSize>
53class Codec<borrowable::wire::FixedInt<IntSize>> {
54 public:
55 static constexpr size_t int_size{IntSize};
56
58
59 constexpr Codec(value_type v, capabilities::value_type /* caps */) : v_{v} {}
60
61 /**
62 * size of the encoded object.
63 */
64 static constexpr size_t size() noexcept { return int_size; }
65
66 /**
67 * encode value_type into buffer.
68 */
71 if (buffer.size() < int_size) {
72 return stdx::unexpected(make_error_code(std::errc::no_buffer_space));
73 }
74
75 auto int_val = v_.value();
76
77 if (std::endian::native == std::endian::big) {
78 int_val = stdx::byteswap(int_val);
79 }
80
81 std::copy_n(reinterpret_cast<const std::byte *>(&int_val), int_size,
82 static_cast<std::byte *>(buffer.data()));
83
84 return int_size;
85 }
86
87 /**
88 * maximum bytes which may scanned by the decoder.
89 */
90 static constexpr size_t max_size() noexcept { return int_size; }
91
94 if (buffer.size() < int_size) {
95 // 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
104 if (std::endian::native == std::endian::big) {
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::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::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::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::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) {
225 }
226
227 const uint8_t nul_val = *static_cast<const uint8_t *>(buffer.data());
228
229 if (nul_val != nul_byte) {
231 }
232
233 return std::make_pair(1, value_type());
234 }
235};
236
237/**
238 * codec for ignorable bytes.
239 *
240 * limited by length or buffer.size()
241 */
242template <>
243class Codec<void> {
244 public:
245 using value_type = size_t;
246
247 Codec(value_type val, capabilities::value_type caps) : v_(val), caps_{caps} {}
248
249 size_t size() const noexcept { return v_; }
250
251 static size_t max_size() noexcept {
252 return std::numeric_limits<size_t>::max();
253 }
254
256 const net::mutable_buffer &buffer) const {
257 if (buffer.size() < size()) {
258 return stdx::unexpected(make_error_code(std::errc::no_buffer_space));
259 }
260
261 auto *first = static_cast<std::uint8_t *>(buffer.data());
262 auto *last = first + size();
263
264 // fill with 0
265 std::fill(first, last, 0);
266
267 return size();
268 }
269
272 size_t buf_size = buffer.size();
273
274 return std::make_pair(buf_size, buf_size);
275 }
276
277 private:
280};
281
282/**
283 * codec for wire::String.
284 *
285 * limited by length or buffer.size()
286 */
287template <bool Borrowed>
288class Codec<borrowable::wire::String<Borrowed>> {
289 public:
291
293 : v_{std::move(v)}, caps_{caps} {}
294
295 constexpr size_t size() const noexcept { return v_.value().size(); }
296
297 static size_t max_size() noexcept {
298 // we actually don't know what the size of the null-term string is ... until
299 // the end of the buffer
300 return std::numeric_limits<size_t>::max();
301 }
302
304 const net::mutable_buffer &buffer) const {
305 if (buffer.size() < size()) {
306 return stdx::unexpected(make_error_code(std::errc::no_buffer_space));
307 }
308
309 // in -> out
310 std::copy_n(reinterpret_cast<const std::byte *>(v_.value().data()), size(),
311 static_cast<std::byte *>(buffer.data()));
312
313 return size();
314 }
315
318 const size_t buf_size = buffer_size(buffer);
319
320 if (0 == buf_size) return std::make_pair(buf_size, value_type());
321
322 return std::make_pair(
323 buf_size,
324 value_type({static_cast<const char *>(buffer.data()), buffer.size()}));
325 }
326
327 private:
330};
331
332/**
333 * codec for string with known length.
334 *
335 * - varint of string length
336 * - string of length
337 */
338template <bool Borrowed>
339class Codec<borrowable::wire::VarString<Borrowed>>
340 : public impl::EncodeBase<Codec<borrowable::wire::VarString<Borrowed>>> {
341 template <class Accumulator>
342 constexpr auto accumulate_fields(Accumulator &&accu) const {
343 return accu.step(borrowable::wire::VarInt(v_.value().size()))
344 .step(borrowable::wire::String<Borrowed>(v_.value()))
345 .result();
346 }
347
348 public:
351
352 friend base_type;
353
355 : base_type(caps), v_{std::move(val)} {}
356
357 static size_t max_size() noexcept {
358 // we actually don't know what the size of the null-term string is ...
359 // until the end of the buffer
360 return std::numeric_limits<size_t>::max();
361 }
362
366 // decode the length
367 auto var_string_len_res = accu.template step<borrowable::wire::VarInt>();
368 if (!accu.result()) return stdx::unexpected(accu.result().error());
369
370 // decode string of length
371 auto var_string_res =
372 accu.template step<borrowable::wire::String<Borrowed>>(
373 var_string_len_res->value());
374
375 if (!accu.result()) return stdx::unexpected(accu.result().error());
376
377 return std::make_pair(accu.result().value(),
378 value_type(var_string_res->value()));
379 }
380
381 private:
383};
384
385/**
386 * codec for 0-terminated string.
387 */
388template <bool Borrowed>
389class Codec<borrowable::wire::NulTermString<Borrowed>>
390 : public impl::EncodeBase<
391 Codec<borrowable::wire::NulTermString<Borrowed>>> {
392 template <class Accumulator>
393 constexpr auto accumulate_fields(Accumulator &&accu) const {
394 return accu.template step<borrowable::wire::String<Borrowed>>(v_)
395 .template step<borrowable::wire::FixedInt<1>>(0)
396 .result();
397 }
398
399 public:
402
403 friend base_type;
404
406 : base_type(caps), v_{std::move(val)} {}
407
408 static size_t max_size() noexcept {
409 // we actually don't know what the size of the null-term string is ...
410 // until the end of the buffer
411 return std::numeric_limits<size_t>::max();
412 }
413
416 // length of the string before the \0
417
418 const auto *first = static_cast<const uint8_t *>(buffer.data());
419 const auto *last = first + buffer.size();
420
421 const auto *pos = std::find(first, last, '\0');
422 if (pos == last) {
423 // no 0-term found
425 }
426
427 // \0 was found
428 size_t len = std::distance(first, pos);
429 if (len == 0) {
430 return std::make_pair(len + 1, value_type()); // consume the \0 too
431 }
432
433 return std::make_pair(len + 1,
434 value_type({static_cast<const char *>(buffer.data()),
435 len})); // consume the \0 too
436 }
437
438 private:
440};
441
442} // namespace classic_protocol
443
444#endif
constexpr Codec(value_type v, capabilities::value_type)
Definition: classic_protocol_codec_wire.h:59
static constexpr size_t max_size() noexcept
maximum bytes which may scanned by the decoder.
Definition: classic_protocol_codec_wire.h:90
stdx::expected< size_t, std::error_code > encode(net::mutable_buffer buffer) const
encode value_type into buffer.
Definition: classic_protocol_codec_wire.h:69
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:92
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:64
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_wire.h:393
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:414
friend base_type
Definition: classic_protocol_codec_wire.h:403
static size_t max_size() noexcept
Definition: classic_protocol_codec_wire.h:408
const value_type v_
Definition: classic_protocol_codec_wire.h:439
constexpr Codec(value_type val, capabilities::value_type caps)
Definition: classic_protocol_codec_wire.h:405
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:329
constexpr Codec(value_type v, capabilities::value_type caps)
Definition: classic_protocol_codec_wire.h:292
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:316
stdx::expected< size_t, std::error_code > encode(const net::mutable_buffer &buffer) const
Definition: classic_protocol_codec_wire.h:303
constexpr size_t size() const noexcept
Definition: classic_protocol_codec_wire.h:295
const value_type v_
Definition: classic_protocol_codec_wire.h:328
static size_t max_size() noexcept
Definition: classic_protocol_codec_wire.h:297
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:382
constexpr Codec(value_type val, capabilities::value_type caps)
Definition: classic_protocol_codec_wire.h:354
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_wire.h:342
friend base_type
Definition: classic_protocol_codec_wire.h:352
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:363
static size_t max_size() noexcept
Definition: classic_protocol_codec_wire.h:357
Codec(value_type val, capabilities::value_type caps)
Definition: classic_protocol_codec_wire.h:247
size_t size() const noexcept
Definition: classic_protocol_codec_wire.h:249
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:270
stdx::expected< size_t, std::error_code > encode(const net::mutable_buffer &buffer) const
Definition: classic_protocol_codec_wire.h:255
const capabilities::value_type caps_
Definition: classic_protocol_codec_wire.h:279
const value_type v_
Definition: classic_protocol_codec_wire.h:278
size_t value_type
Definition: classic_protocol_codec_wire.h:245
static size_t max_size() noexcept
Definition: classic_protocol_codec_wire.h:251
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:374
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 error_type & error() const &
Definition: expected.h:751
constexpr value_type & value() &
Definition: expected.h:636
Definition: expected.h:112
constexpr DWORD buf_size
Definition: create_def.cc:229
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
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
Container::const_iterator find(const Container &c, Value &&value)
Definition: generic.h:39
size_t size(const char *const c)
Definition: base64.h:46
mutable_buffer buffer(void *p, size_t n) noexcept
Definition: buffer.h:418
size_t buffer_size(const ConstBufferSequence &buffers) noexcept
Definition: buffer.h:313
Definition: gcs_xcom_synode.h:64
unexpected(E) -> unexpected< E >
constexpr T byteswap(T num) noexcept
Definition: bit.h:52