File indexing completed on 2025-01-18 09:42:42
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MYSQL_IMPL_INTERNAL_PROTOCOL_SERIALIZATION_HPP
0009 #define BOOST_MYSQL_IMPL_INTERNAL_PROTOCOL_SERIALIZATION_HPP
0010
0011 #include <boost/mysql/client_errc.hpp>
0012 #include <boost/mysql/error_code.hpp>
0013 #include <boost/mysql/field_view.hpp>
0014 #include <boost/mysql/string_view.hpp>
0015
0016 #include <boost/mysql/impl/internal/protocol/basic_types.hpp>
0017 #include <boost/mysql/impl/internal/protocol/capabilities.hpp>
0018 #include <boost/mysql/impl/internal/protocol/protocol_field_type.hpp>
0019
0020 #include <boost/assert.hpp>
0021 #include <boost/core/span.hpp>
0022 #include <boost/endian/conversion.hpp>
0023 #include <boost/endian/detail/endian_load.hpp>
0024 #include <boost/endian/detail/endian_store.hpp>
0025
0026 #include <cstddef>
0027 #include <cstdint>
0028 #include <cstring>
0029 #include <type_traits>
0030
0031 namespace boost {
0032 namespace mysql {
0033 namespace detail {
0034
0035
0036
0037 enum class deserialize_errc
0038 {
0039 ok = 0,
0040 incomplete_message = 1,
0041 protocol_value_error,
0042 server_unsupported
0043 };
0044 inline error_code to_error_code(deserialize_errc v) noexcept
0045 {
0046 switch (v)
0047 {
0048 case deserialize_errc::ok: return error_code();
0049 case deserialize_errc::incomplete_message: return error_code(client_errc::incomplete_message);
0050 case deserialize_errc::protocol_value_error: return error_code(client_errc::protocol_value_error);
0051 case deserialize_errc::server_unsupported: return error_code(client_errc::server_unsupported);
0052 default: BOOST_ASSERT(false); return error_code();
0053 }
0054 }
0055
0056 class serialization_context
0057 {
0058 std::uint8_t* first_;
0059
0060 public:
0061 explicit serialization_context(std::uint8_t* first) noexcept : first_(first) {}
0062 std::uint8_t* first() const noexcept { return first_; }
0063 void advance(std::size_t size) noexcept { first_ += size; }
0064 void write(const void* buffer, std::size_t size) noexcept
0065 {
0066 if (size)
0067 {
0068 BOOST_ASSERT(buffer != nullptr);
0069 std::memcpy(first_, buffer, size);
0070 advance(size);
0071 }
0072 }
0073 void write(std::uint8_t elm) noexcept
0074 {
0075 *first_ = elm;
0076 ++first_;
0077 }
0078 };
0079
0080 class deserialization_context
0081 {
0082 const std::uint8_t* first_;
0083 const std::uint8_t* last_;
0084
0085 public:
0086 deserialization_context(span<const std::uint8_t> data) noexcept
0087 : deserialization_context(data.data(), data.size())
0088 {
0089 }
0090 deserialization_context(const std::uint8_t* first, std::size_t size) noexcept
0091 : first_(first), last_(first + size){};
0092 const std::uint8_t* first() const noexcept { return first_; }
0093 const std::uint8_t* last() const noexcept { return last_; }
0094 void advance(std::size_t sz) noexcept
0095 {
0096 first_ += sz;
0097 BOOST_ASSERT(last_ >= first_);
0098 }
0099 void rewind(std::size_t sz) noexcept { first_ -= sz; }
0100 std::size_t size() const noexcept { return last_ - first_; }
0101 bool empty() const noexcept { return last_ == first_; }
0102 bool enough_size(std::size_t required_size) const noexcept { return size() >= required_size; }
0103 deserialize_errc copy(void* to, std::size_t sz) noexcept
0104 {
0105 if (!enough_size(sz))
0106 return deserialize_errc::incomplete_message;
0107 memcpy(to, first_, sz);
0108 advance(sz);
0109 return deserialize_errc::ok;
0110 }
0111 string_view get_string(std::size_t sz) const noexcept
0112 {
0113 return string_view(reinterpret_cast<const char*>(first_), sz);
0114 }
0115 error_code check_extra_bytes() const noexcept
0116 {
0117 return empty() ? error_code() : error_code(client_errc::extra_bytes);
0118 }
0119 span<const std::uint8_t> to_span() const noexcept { return span<const std::uint8_t>(first_, size()); }
0120 };
0121
0122
0123 template <class T, class = typename std::enable_if<std::is_integral<T>::value>::type>
0124 deserialize_errc deserialize(deserialization_context& ctx, T& output) noexcept
0125 {
0126 constexpr std::size_t sz = sizeof(T);
0127 if (!ctx.enough_size(sz))
0128 {
0129 return deserialize_errc::incomplete_message;
0130 }
0131 output = endian::endian_load<T, sz, boost::endian::order::little>(ctx.first());
0132 ctx.advance(sz);
0133 return deserialize_errc::ok;
0134 }
0135
0136 template <class T, class = typename std::enable_if<std::is_integral<T>::value>::type>
0137 void serialize(serialization_context& ctx, T input) noexcept
0138 {
0139 endian::endian_store<T, sizeof(T), endian::order::little>(ctx.first(), input);
0140 ctx.advance(sizeof(T));
0141 }
0142
0143 template <class T, class = typename std::enable_if<std::is_integral<T>::value>::type>
0144 constexpr std::size_t get_size(T) noexcept
0145 {
0146 return sizeof(T);
0147 }
0148
0149
0150 inline deserialize_errc deserialize(deserialization_context& ctx, int3& output) noexcept
0151 {
0152 if (!ctx.enough_size(3))
0153 return deserialize_errc::incomplete_message;
0154 output.value = endian::load_little_u24(ctx.first());
0155 ctx.advance(3);
0156 return deserialize_errc::ok;
0157 }
0158 inline void serialize(serialization_context& ctx, int3 input) noexcept
0159 {
0160 endian::store_little_u24(ctx.first(), input.value);
0161 ctx.advance(3);
0162 }
0163 constexpr std::size_t get_size(int3) noexcept { return 3; }
0164
0165
0166 inline deserialize_errc deserialize(deserialization_context& ctx, int_lenenc& output) noexcept
0167 {
0168 std::uint8_t first_byte = 0;
0169 auto err = deserialize(ctx, first_byte);
0170 if (err != deserialize_errc::ok)
0171 {
0172 return err;
0173 }
0174
0175 if (first_byte == 0xFC)
0176 {
0177 std::uint16_t value = 0;
0178 err = deserialize(ctx, value);
0179 output.value = value;
0180 }
0181 else if (first_byte == 0xFD)
0182 {
0183 int3 value{};
0184 err = deserialize(ctx, value);
0185 output.value = value.value;
0186 }
0187 else if (first_byte == 0xFE)
0188 {
0189 std::uint64_t value = 0;
0190 err = deserialize(ctx, value);
0191 output.value = value;
0192 }
0193 else
0194 {
0195 err = deserialize_errc::ok;
0196 output.value = first_byte;
0197 }
0198 return err;
0199 }
0200 inline void serialize(serialization_context& ctx, int_lenenc input) noexcept
0201 {
0202 if (input.value < 251)
0203 {
0204 serialize(ctx, static_cast<std::uint8_t>(input.value));
0205 }
0206 else if (input.value < 0x10000)
0207 {
0208 ctx.write(0xfc);
0209 serialize(ctx, static_cast<std::uint16_t>(input.value));
0210 }
0211 else if (input.value < 0x1000000)
0212 {
0213 ctx.write(0xfd);
0214 serialize(ctx, int3{static_cast<std::uint32_t>(input.value)});
0215 }
0216 else
0217 {
0218 ctx.write(0xfe);
0219 serialize(ctx, static_cast<std::uint64_t>(input.value));
0220 }
0221 }
0222 inline std::size_t get_size(int_lenenc input) noexcept
0223 {
0224 if (input.value < 251)
0225 return 1;
0226 else if (input.value < 0x10000)
0227 return 3;
0228 else if (input.value < 0x1000000)
0229 return 4;
0230 else
0231 return 9;
0232 }
0233
0234
0235 inline deserialize_errc deserialize(deserialization_context& ctx, protocol_field_type& output) noexcept
0236 {
0237 std::underlying_type<protocol_field_type>::type value = 0;
0238 auto err = deserialize(ctx, value);
0239 output = static_cast<protocol_field_type>(value);
0240 return err;
0241 }
0242 inline void serialize(serialization_context& ctx, protocol_field_type input) noexcept
0243 {
0244 serialize(ctx, static_cast<std::underlying_type<protocol_field_type>::type>(input));
0245 }
0246 constexpr std::size_t get_size(protocol_field_type) noexcept { return sizeof(protocol_field_type); }
0247
0248
0249 template <std::size_t N>
0250 deserialize_errc deserialize(deserialization_context& ctx, string_fixed<N>& output) noexcept
0251 {
0252 if (!ctx.enough_size(N))
0253 return deserialize_errc::incomplete_message;
0254 memcpy(output.value.data(), ctx.first(), N);
0255 ctx.advance(N);
0256 return deserialize_errc::ok;
0257 }
0258
0259 template <std::size_t N>
0260 void serialize(serialization_context& ctx, const string_fixed<N>& input) noexcept
0261 {
0262 ctx.write(input.value.data(), N);
0263 }
0264
0265 template <std::size_t N>
0266 constexpr std::size_t get_size(const string_fixed<N>&) noexcept
0267 {
0268 return N;
0269 }
0270
0271
0272 inline deserialize_errc deserialize(deserialization_context& ctx, string_null& output) noexcept
0273 {
0274 auto string_end = std::find(ctx.first(), ctx.last(), 0);
0275 if (string_end == ctx.last())
0276 {
0277 return deserialize_errc::incomplete_message;
0278 }
0279 std::size_t length = string_end - ctx.first();
0280 output.value = ctx.get_string(length);
0281 ctx.advance(length + 1);
0282 return deserialize_errc::ok;
0283 }
0284 inline void serialize(serialization_context& ctx, string_null input) noexcept
0285 {
0286 ctx.write(input.value.data(), input.value.size());
0287 ctx.write(0);
0288 }
0289 inline std::size_t get_size(string_null input) noexcept { return input.value.size() + 1; }
0290
0291
0292 inline deserialize_errc deserialize(deserialization_context& ctx, string_eof& output) noexcept
0293 {
0294 std::size_t size = ctx.size();
0295 output.value = ctx.get_string(size);
0296 ctx.advance(size);
0297 return deserialize_errc::ok;
0298 }
0299 inline void serialize(serialization_context& ctx, string_eof input) noexcept
0300 {
0301 ctx.write(input.value.data(), input.value.size());
0302 }
0303 inline std::size_t get_size(string_eof input) noexcept { return input.value.size(); }
0304
0305
0306 inline deserialize_errc deserialize(deserialization_context& ctx, string_lenenc& output) noexcept
0307 {
0308 int_lenenc length;
0309 auto err = deserialize(ctx, length);
0310 if (err != deserialize_errc::ok)
0311 {
0312 return err;
0313 }
0314 if (length.value > (std::numeric_limits<std::size_t>::max)())
0315 {
0316 return deserialize_errc::protocol_value_error;
0317 }
0318 auto len = static_cast<std::size_t>(length.value);
0319 if (!ctx.enough_size(len))
0320 {
0321 return deserialize_errc::incomplete_message;
0322 }
0323
0324 output.value = ctx.get_string(len);
0325 ctx.advance(len);
0326 return deserialize_errc::ok;
0327 }
0328 inline void serialize(serialization_context& ctx, string_lenenc input) noexcept
0329 {
0330 serialize(ctx, int_lenenc{input.value.size()});
0331 ctx.write(input.value.data(), input.value.size());
0332 }
0333 inline std::size_t get_size(string_lenenc input) noexcept
0334 {
0335 return get_size(int_lenenc{input.value.size()}) + input.value.size();
0336 }
0337
0338
0339 template <class FirstType, class SecondType, class... Rest>
0340 deserialize_errc deserialize(
0341 deserialization_context& ctx,
0342 FirstType& first,
0343 SecondType& second,
0344 Rest&... tail
0345 ) noexcept
0346 {
0347 deserialize_errc err = deserialize(ctx, first);
0348 if (err == deserialize_errc::ok)
0349 {
0350 err = deserialize(ctx, second, tail...);
0351 }
0352 return err;
0353 }
0354
0355 template <class FirstType, class SecondType, class... Rest>
0356 void serialize(
0357 serialization_context& ctx,
0358 const FirstType& first,
0359 const SecondType& second,
0360 const Rest&... rest
0361 ) noexcept
0362 {
0363 serialize(ctx, first);
0364 serialize(ctx, second, rest...);
0365 }
0366
0367 template <class FirstType, class SecondType, class... Rest>
0368 std::size_t get_size(const FirstType& first, const SecondType& second, const Rest&... rest) noexcept
0369 {
0370 return get_size(first) + get_size(second, rest...);
0371 }
0372
0373
0374 inline string_view to_string(span<const std::uint8_t> v) noexcept
0375 {
0376 return string_view(reinterpret_cast<const char*>(v.data()), v.size());
0377 }
0378 inline span<const std::uint8_t> to_span(string_view v) noexcept
0379 {
0380 return span<const std::uint8_t>(reinterpret_cast<const std::uint8_t*>(v.data()), v.size());
0381 }
0382
0383 }
0384 }
0385 }
0386
0387 #endif