/* * Copyright (c) 2019, 2022, Oracle and/or its affiliates. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2.0, * as published by the Free Software Foundation. * * This program is also distributed with certain software (including * but not limited to OpenSSL) that is licensed under separate terms, * as designated in a particular file or component or in included license * documentation. The authors of MySQL hereby grant you an additional * permission to link the program and your derivative works with the * separately licensed software that they have included with MySQL. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License, version 2.0, for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include namespace protocol { namespace primitives { namespace base { template struct Varint_length_value { static void encode(uint8_t *&) { static_assert(0 == length, "Length must be grater then zero."); static_assert(length, "You have specified unsupported version of length, currently " "supported 1-10."); } }; template struct Varint_length_value<1, value> { static void encode(uint8_t *&out) { // NOLINT *(out++) = static_cast(value & 0x7F); } }; template struct Varint_length_value<2, value> { static void encode(uint8_t *&out) { // NOLINT *(out++) = static_cast((value & 0x7F) | 0x80); *(out++) = static_cast((value >> 7) & 0x7F); } }; template struct Varint_length_value<3, value> { static void encode(uint8_t *&out) { // NOLINT *(out++) = static_cast((value & 0x7F) | 0x80); *(out++) = static_cast(((value >> 7) & 0x7F) | 0x80); *(out++) = static_cast((value >> 14) & 0x7F); } }; template struct Varint_length_value<4, value> { static void encode(uint8_t *&out) { // NOLINT *(out++) = static_cast((value & 0x7F) | 0x80); *(out++) = static_cast(((value >> 7) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 14) & 0x7F) | 0x80); *(out++) = static_cast((value >> 21) & 0x7F); } }; template struct Varint_length_value<5, value> { static void encode(uint8_t *&out) { // NOLINT *(out++) = static_cast((value & 0x7F) | 0x80); *(out++) = static_cast(((value >> 7) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 14) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 21) & 0x7F) | 0x80); *(out++) = static_cast((value >> 28) & 0x7F); } }; template struct Varint_length_value<6, value> { static void encode(uint8_t *&out) { // NOLINT *(out++) = static_cast((value & 0x7F) | 0x80); *(out++) = static_cast(((value >> 7) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 14) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 21) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 28) & 0x7F) | 0x80); *(out++) = static_cast((value >> 35) & 0x7F); } }; template struct Varint_length_value<7, value> { static void encode(uint8_t *&out) { // NOLINT *(out++) = static_cast((value & 0x7F) | 0x80); *(out++) = static_cast(((value >> 7) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 14) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 21) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 28) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 35) & 0x7F) | 0x80); *(out++) = static_cast((value >> 42) & 0x7F); } }; template struct Varint_length_value<8, value> { static void encode(uint8_t *&out) { // NOLINT *(out++) = static_cast((value & 0x7F) | 0x80); *(out++) = static_cast(((value >> 7) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 14) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 21) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 28) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 35) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 42) & 0x7F) | 0x80); *(out++) = static_cast((value >> 49) & 0x7F); } }; template struct Varint_length_value<9, value> { static void encode(uint8_t *&out) { // NOLINT *(out++) = static_cast((value & 0x7F) | 0x80); *(out++) = static_cast(((value >> 7) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 14) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 21) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 28) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 35) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 42) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 49) & 0x7F) | 0x80); *(out++) = static_cast((value >> 56) & 0x7F); } }; template struct Varint_length_value<10, value> { static void encode(uint8_t *&out) { // NOLINT *(out++) = static_cast((value & 0x7F) | 0x80); *(out++) = static_cast(((value >> 7) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 14) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 21) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 28) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 35) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 42) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 49) & 0x7F) | 0x80); *(out++) = static_cast(((value >> 56) & 0x7F) | 0x80); *(out++) = static_cast((value >> 63) & 0x7F); } }; template struct Varint_length { static void encode(uint8_t *&, const uint64_t) { static_assert(0 == length, "Length must be grater then zero."); static_assert(length, "You have specified unsupported version of length, currently " "supported 1-10."); } }; template <> struct Varint_length<1> { static void encode(uint8_t *&out, const uint64_t value) { // NOLINT *(out++) = static_cast(value & 0x7F); } }; template <> struct Varint_length<2> { static void encode(uint8_t *&out, const uint64_t value) { // NOLINT *(out++) = static_cast(value & 0x7F) | 0x80; *(out++) = static_cast((value >> 7) & 0x7F); } }; template <> struct Varint_length<3> { static void encode(uint8_t *&out, const uint64_t value) { // NOLINT *(out++) = static_cast(value & 0x7F) | 0x80; *(out++) = static_cast((value >> 7) & 0x7F) | 0x80; *(out++) = static_cast((value >> 14) & 0x7F); } }; template <> struct Varint_length<4> { static void encode(uint8_t *&out, const uint64_t value) { // NOLINT *(out++) = static_cast(value & 0x7F) | 0x80; *(out++) = static_cast((value >> 7) & 0x7F) | 0x80; *(out++) = static_cast((value >> 14) & 0x7F) | 0x80; *(out++) = static_cast((value >> 21) & 0x7F); } }; template <> struct Varint_length<5> { static void encode(uint8_t *&out, const uint64_t value) { // NOLINT *(out++) = static_cast(value & 0x7F) | 0x80; *(out++) = static_cast((value >> 7) & 0x7F) | 0x80; *(out++) = static_cast((value >> 14) & 0x7F) | 0x80; *(out++) = static_cast((value >> 21) & 0x7F) | 0x80; *(out++) = static_cast((value >> 28) & 0x7F); } }; template <> struct Varint_length<6> { static void encode(uint8_t *&out, const uint64_t value) { // NOLINT *(out++) = static_cast(value & 0x7F) | 0x80; *(out++) = static_cast((value >> 7) & 0x7F) | 0x80; *(out++) = static_cast((value >> 14) & 0x7F) | 0x80; *(out++) = static_cast((value >> 21) & 0x7F) | 0x80; *(out++) = static_cast((value >> 28) & 0x7F) | 0x80; *(out++) = static_cast((value >> 35) & 0x7F); } }; template <> struct Varint_length<7> { static void encode(uint8_t *&out, const uint64_t value) { // NOLINT *(out++) = static_cast(value & 0x7F) | 0x80; *(out++) = static_cast((value >> 7) & 0x7F) | 0x80; *(out++) = static_cast((value >> 14) & 0x7F) | 0x80; *(out++) = static_cast((value >> 21) & 0x7F) | 0x80; *(out++) = static_cast((value >> 28) & 0x7F) | 0x80; *(out++) = static_cast((value >> 35) & 0x7F) | 0x80; *(out++) = static_cast((value >> 42) & 0x7F); } }; template <> struct Varint_length<8> { static void encode(uint8_t *&out, const uint64_t value) { // NOLINT *(out++) = static_cast(value & 0x7F) | 0x80; *(out++) = static_cast((value >> 7) & 0x7F) | 0x80; *(out++) = static_cast((value >> 14) & 0x7F) | 0x80; *(out++) = static_cast((value >> 21) & 0x7F) | 0x80; *(out++) = static_cast((value >> 28) & 0x7F) | 0x80; *(out++) = static_cast((value >> 35) & 0x7F) | 0x80; *(out++) = static_cast((value >> 42) & 0x7F) | 0x80; *(out++) = static_cast((value >> 49) & 0x7F); } }; template <> struct Varint_length<9> { static void encode(uint8_t *&out, const uint64_t value) { // NOLINT *(out++) = static_cast(value & 0x7F) | 0x80; *(out++) = static_cast((value >> 7) & 0x7F) | 0x80; *(out++) = static_cast((value >> 14) & 0x7F) | 0x80; *(out++) = static_cast((value >> 21) & 0x7F) | 0x80; *(out++) = static_cast((value >> 28) & 0x7F) | 0x80; *(out++) = static_cast((value >> 35) & 0x7F) | 0x80; *(out++) = static_cast((value >> 42) & 0x7F) | 0x80; *(out++) = static_cast((value >> 49) & 0x7F) | 0x80; *(out++) = static_cast((value >> 56) & 0x7F); } }; template <> struct Varint_length<10> { static void encode(uint8_t *&out, const uint64_t value) { // NOLINT *(out++) = static_cast(value & 0x7F) | 0x80; *(out++) = static_cast((value >> 7) & 0x7F) | 0x80; *(out++) = static_cast((value >> 14) & 0x7F) | 0x80; *(out++) = static_cast((value >> 21) & 0x7F) | 0x80; *(out++) = static_cast((value >> 28) & 0x7F) | 0x80; *(out++) = static_cast((value >> 35) & 0x7F) | 0x80; *(out++) = static_cast((value >> 42) & 0x7F) | 0x80; *(out++) = static_cast((value >> 49) & 0x7F) | 0x80; *(out++) = static_cast((value >> 56) & 0x7F) | 0x80; *(out++) = static_cast((value >> 63) & 0x7F); } }; struct Varint { template static void encode(uint8_t *&out, Value_type value) { // NOLINT while (value > 0x7F) { *(out++) = static_cast(value & 0x7F) | 0x80; value >>= 7; } *(out++) = static_cast(value & 0x7F); } }; struct Fixint {}; template struct Fixint_length {}; template <> struct Fixint_length<1> { template static void encode(uint8_t *&out) { // NOLINT *(out++) = value; } static void encode_value(uint8_t *&out, const uint8_t value) { // NOLINT *(out++) = value; } }; template <> struct Fixint_length<4> { template static void encode(uint8_t *&out) { // NOLINT #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) *reinterpret_cast(out) = __builtin_bswap32(value); out += 4; #else *reinterpret_cast(out) = value; out += 4; #endif } static void encode_value(uint8_t *&out, const uint32_t value) { // NOLINT #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) *reinterpret_cast(out) = __builtin_bswap32(value); out += 4; #else *reinterpret_cast(out) = value; out += 4; #endif } }; template <> struct Fixint_length<8> { template static void encode(uint8_t *&out) { // NOLINT #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) *reinterpret_cast(out) = __builtin_bswap64(value); out += 8; #else *reinterpret_cast(out) = value; out += 8; #endif } static void encode_value(uint8_t *&out, const uint64_t value) { // NOLINT #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) *reinterpret_cast(out) = __builtin_bswap64(value); out += 8; #else *reinterpret_cast(out) = value; out += 8; #endif } }; class Helper { public: using WireType = google::protobuf::internal::WireFormatLite::WireType; static constexpr uint32_t encode_field_tag(const uint32_t field_no, const WireType wt) { return static_cast( field_no << ::google::protobuf::internal::WireFormatLite::kTagTypeBits | wt); } static constexpr uint64_t encode_zigzag(const int64_t value) { return static_cast(value >> 63) ^ (static_cast(value) << 1); } static constexpr uint32_t encode_zigzag(const int32_t value) { return (value >> 31) ^ (value << 1); } constexpr static int get_varint_length(const uint64_t value, uint64_t shift, uint8_t level) { return (value < shift) ? level : get_varint_length(value, shift << 7, level + 1); } static int get_varint_length(const uint64_t value) { if (value < 0x0000000000000080) return 1; if (value < 0x0000000000004000) return 2; if (value < 0x0000000000200000) return 3; if (value < 0x0000000010000000) return 4; if (value < 0x0000000800000000) return 5; if (value < 0x0000040000000000) return 6; if (value < 0x0002000000000000) return 7; if (value < 0x0100000000000000) return 8; if (value < 0x8000000000000000) return 9; return 10; } }; } // namespace base } // namespace primitives } // namespace protocol