MySQL 8.3.0
Source Code Documentation
classic_protocol_codec_wire.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2019, 2023, 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 also distributed 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 included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23*/
24
25#ifndef MYSQL_ROUTER_CLASSIC_PROTOCOL_CODEC_WIRE_H_
26#define MYSQL_ROUTER_CLASSIC_PROTOCOL_CODEC_WIRE_H_
27
28// codecs for classic_protocol::wire::
29
30#include <algorithm> // find
31#include <cstddef> // size_t
32#include <cstdint> // uint8_t
33#include <system_error> // error_code
34#include <type_traits>
35#include <utility> // move
36
39#include "mysql/harness/stdx/type_traits.h" // endian
43
44namespace classic_protocol {
45/**
46 * codec of a FixedInt.
47 *
48 * classic proto uses 1, 2, 3, 4, 8 for IntSize
49 */
50template <int IntSize>
51class Codec<borrowable::wire::FixedInt<IntSize>> {
52 public:
53 static constexpr size_t int_size{IntSize};
54
56
57 constexpr Codec(value_type v, capabilities::value_type /* caps */) : v_{v} {}
58
59 /**
60 * size of the encoded object.
61 */
62 static constexpr size_t size() noexcept { return int_size; }
63
64 /**
65 * encode value_type into buffer.
66 */
69 if (buffer.size() < int_size) {
70 return stdx::make_unexpected(make_error_code(std::errc::no_buffer_space));
71 }
72
73 auto int_val = v_.value();
74
76 int_val = stdx::byteswap(int_val);
77 }
78
79 std::copy_n(reinterpret_cast<const std::byte *>(&int_val), int_size,
80 static_cast<std::byte *>(buffer.data()));
81
82 return int_size;
83 }
84
85 /**
86 * maximum bytes which may scanned by the decoder.
87 */
88 static constexpr size_t max_size() noexcept { return int_size; }
89
92 if (buffer.size() < int_size) {
93 // not enough data in buffers.
96 }
97
98 typename value_type::value_type value{};
99
100 std::copy_n(static_cast<const std::byte *>(buffer.data()), int_size,
101 reinterpret_cast<std::byte *>(&value));
102
104 value = stdx::byteswap(value);
105 }
106
107 return std::make_pair(int_size, value_type(value));
108 }
109
110 private:
112};
113
114/**
115 * codec for variable length integers.
116 *
117 * note: encoded as little endian
118 *
119 * 0x00
120 * ...
121 * 0xfa -> 0xfa
122 * 0xfb [undefined]
123 * 0xfc 0x.. 0x..
124 * 0xfd 0x.. 0x.. 0x..
125 *
126 * 3.21:
127 * 0xfe 0x.. 0x.. 0x.. 0x.. 0x00
128 * [1 + 5 bytes read, only 4 bytes used]
129 *
130 * 4.0:
131 * 0xfe 0x.. 0x.. 0x.. 0x.. 0x.. 0x.. 0x.. 0x..
132 * [1 + 8 bytes read, only 4 bytes used]
133 */
134template <>
135class Codec<borrowable::wire::VarInt>
136 : public impl::EncodeBase<Codec<borrowable::wire::VarInt>> {
137 template <class Accumulator>
138 constexpr auto accumulate_fields(Accumulator &&accu) const {
139 if (v_.value() < 251) {
140 return accu.step(borrowable::wire::FixedInt<1>(v_.value())).result();
141 } else if (v_.value() < 1 << 16) {
142 return accu.step(borrowable::wire::FixedInt<1>(varint_16))
143 .step(borrowable::wire::FixedInt<2>(v_.value()))
144 .result();
145 } else if (v_.value() < (1 << 24)) {
146 return accu.step(borrowable::wire::FixedInt<1>(varint_24))
147 .step(borrowable::wire::FixedInt<3>(v_.value()))
148 .result();
149 } else {
150 return accu.step(borrowable::wire::FixedInt<1>(varint_64))
151 .step(borrowable::wire::FixedInt<8>(v_.value()))
152 .result();
153 }
154 }
155
156 public:
157 static constexpr uint8_t varint_16{0xfc};
158 static constexpr uint8_t varint_24{0xfd};
159 static constexpr uint8_t varint_64{0xfe};
162
163 friend __base;
164
166 : __base{caps}, v_{v} {}
167
168 static constexpr size_t max_size() noexcept { return 9; }
169
173
174 // length
175 auto first_byte_res = accu.template step<borrowable::wire::FixedInt<1>>();
176 if (!first_byte_res) return stdx::make_unexpected(first_byte_res.error());
177
178 auto first_byte = first_byte_res->value();
179
180 if (first_byte < 251) {
181 return std::make_pair(accu.result().value(), value_type(first_byte));
182 } else if (first_byte == varint_16) {
183 auto value_res = accu.template step<borrowable::wire::FixedInt<2>>();
184 if (!value_res) return stdx::make_unexpected(value_res.error());
185 return std::make_pair(accu.result().value(),
186 value_type(value_res->value()));
187 } else if (first_byte == varint_24) {
188 auto value_res = accu.template step<borrowable::wire::FixedInt<3>>();
189 if (!value_res) return stdx::make_unexpected(value_res.error());
190 return std::make_pair(accu.result().value(),
191 value_type(value_res->value()));
192 } else if (first_byte == varint_64) {
193 auto value_res = accu.template step<borrowable::wire::FixedInt<8>>();
194 if (!value_res) return stdx::make_unexpected(value_res.error());
195 return std::make_pair(accu.result().value(),
196 value_type(value_res->value()));
197 }
198
200 }
201
202 private:
204};
205
206/**
207 * codec for a NULL value in the Resultset.
208 */
209template <>
210class Codec<borrowable::wire::Null>
211 : public Codec<borrowable::wire::FixedInt<1>> {
212 public:
214
215 static constexpr uint8_t nul_byte{0xfb};
216
218 : Codec<borrowable::wire::FixedInt<1>>(nul_byte, caps) {}
219
222 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::make_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::make_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::make_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::make_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
426 }
427
428 // \0 was found
429 size_t len = std::distance(first, pos);
430 if (len == 0) {
431 return std::make_pair(len + 1, value_type()); // consume the \0 too
432 }
433
434 return std::make_pair(len + 1,
435 value_type({static_cast<const char *>(buffer.data()),
436 len})); // consume the \0 too
437 }
438
439 private:
441};
442
443} // namespace classic_protocol
444
445#endif
constexpr Codec(value_type v, capabilities::value_type)
Definition: classic_protocol_codec_wire.h:57
static constexpr size_t max_size() noexcept
maximum bytes which may scanned by the decoder.
Definition: classic_protocol_codec_wire.h:88
stdx::expected< size_t, std::error_code > encode(net::mutable_buffer buffer) const
encode value_type into buffer.
Definition: classic_protocol_codec_wire.h:67
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:90
const value_type v_
Definition: classic_protocol_codec_wire.h:111
static constexpr size_t size() noexcept
size of the encoded object.
Definition: classic_protocol_codec_wire.h:62
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:440
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:217
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:220
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:165
constexpr auto accumulate_fields(Accumulator &&accu) const
Definition: classic_protocol_codec_wire.h:138
const value_type v_
Definition: classic_protocol_codec_wire.h:203
friend __base
Definition: classic_protocol_codec_wire.h:163
static constexpr size_t max_size() noexcept
Definition: classic_protocol_codec_wire.h:168
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:170
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:71
Definition: classic_protocol_wire.h:105
Definition: classic_protocol_wire.h:111
Definition: classic_protocol_wire.h:117
Definition: classic_protocol_wire.h:129
Definition: classic_protocol_wire.h:102
Definition: classic_protocol_wire.h:58
Definition: classic_protocol_wire.h:134
Definition: classic_protocol_wire.h:37
Definition: classic_protocol_wire.h:96
Definition: classic_protocol_wire.h:64
Generator of decoded Types of a buffer.
Definition: classic_protocol_codec_base.h:152
result_type result() const
get result of the step().
Definition: classic_protocol_codec_base.h:218
CRTP base for the Codec's encode part.
Definition: classic_protocol_codec_base.h:374
Definition: buffer.h:134
Definition: buffer.h:112
void * data() const noexcept
Definition: buffer.h:118
size_t size() const noexcept
Definition: buffer.h:119
constexpr const value_type & value() const &
Definition: expected.h:687
constexpr const error_type & error() const &
Definition: expected.h:736
constexpr DWORD buf_size
Definition: create_def.cc:228
unsigned char byte
Blob class.
Definition: common.h:150
uint16_t value_type
Definition: vt100.h:183
borrowable::binary::Null Null
Definition: classic_protocol_binary.h:336
borrowable::wire::FixedInt< Size > FixedInt
Definition: classic_protocol_wire.h:146
borrowable::wire::VarInt VarInt
Definition: classic_protocol_wire.h:147
std::bitset< 32 > value_type
Definition: classic_protocol_constants.h:72
Definition: classic_protocol_binary.h:38
std::error_code make_error_code(codec_errc e) noexcept
Definition: classic_protocol_codec_error.h:85
const byte * find(const Pages *pages, const page_id_t &page_id) noexcept
Find a doublewrite copy of a page.
Definition: buf0dblwr.cc:3578
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:39
mutable_buffer buffer(void *p, size_t n) noexcept
Definition: buffer.h:417
size_t buffer_size(const ConstBufferSequence &buffers) noexcept
Definition: buffer.h:312
Definition: varlen_sort.h:174
constexpr auto make_unexpected(E &&e) -> unexpected< std::decay_t< E > >
Definition: expected.h:124
constexpr std::enable_if_t< std::is_integral< IntegerType >::value, IntegerType > byteswap(IntegerType t) noexcept
Definition: bit.h:141