File indexing completed on 2025-09-17 08:39:17
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/error_code.hpp>
0012 #include <boost/mysql/field_view.hpp>
0013 #include <boost/mysql/string_view.hpp>
0014
0015 #include <boost/mysql/impl/internal/protocol/capabilities.hpp>
0016 #include <boost/mysql/impl/internal/protocol/frame_header.hpp>
0017 #include <boost/mysql/impl/internal/protocol/impl/binary_protocol.hpp>
0018 #include <boost/mysql/impl/internal/protocol/impl/null_bitmap.hpp>
0019 #include <boost/mysql/impl/internal/protocol/impl/protocol_field_type.hpp>
0020 #include <boost/mysql/impl/internal/protocol/impl/protocol_types.hpp>
0021 #include <boost/mysql/impl/internal/protocol/impl/serialization_context.hpp>
0022
0023 #include <boost/assert.hpp>
0024
0025 #include <cstddef>
0026 #include <cstdint>
0027
0028 namespace boost {
0029 namespace mysql {
0030 namespace detail {
0031
0032
0033 struct quit_command
0034 {
0035 void serialize(serialization_context& ctx) const { ctx.add(0x01); }
0036 };
0037
0038
0039 struct ping_command
0040 {
0041 void serialize(serialization_context& ctx) const { ctx.add(0x0e); }
0042 };
0043
0044
0045 struct reset_connection_command
0046 {
0047 void serialize(serialization_context& ctx) const { ctx.add(0x1f); }
0048 };
0049
0050
0051 struct query_command
0052 {
0053 string_view query;
0054
0055 void serialize(serialization_context& ctx) const
0056 {
0057 ctx.add(0x03);
0058 string_eof{query}.serialize(ctx);
0059 }
0060 };
0061
0062
0063 struct prepare_stmt_command
0064 {
0065 string_view stmt;
0066
0067 void serialize(serialization_context& ctx) const
0068 {
0069 ctx.add(0x16);
0070 string_eof{stmt}.serialize(ctx);
0071 }
0072 };
0073
0074
0075 struct execute_stmt_command
0076 {
0077 std::uint32_t statement_id;
0078 span<const field_view> params;
0079
0080 inline void serialize(serialization_context& ctx) const;
0081 };
0082
0083
0084 struct close_stmt_command
0085 {
0086 std::uint32_t statement_id;
0087 void serialize(serialization_context& ctx) const { ctx.serialize_fixed(int1{0x19}, int4{statement_id}); }
0088 };
0089
0090
0091 struct login_request
0092 {
0093 capabilities negotiated_capabilities;
0094 std::uint32_t max_packet_size;
0095 std::uint32_t collation_id;
0096 string_view username;
0097 span<const std::uint8_t> auth_response;
0098 string_view database;
0099 string_view auth_plugin_name;
0100
0101 inline void serialize(serialization_context& ctx) const;
0102 };
0103
0104
0105 struct ssl_request
0106 {
0107 capabilities negotiated_capabilities;
0108 std::uint32_t max_packet_size;
0109 std::uint32_t collation_id;
0110
0111 inline void serialize(serialization_context& ctx) const;
0112 };
0113
0114
0115 struct auth_switch_response
0116 {
0117 span<const std::uint8_t> auth_plugin_data;
0118
0119 void serialize(serialization_context& ctx) const { ctx.add(auth_plugin_data); }
0120 };
0121
0122
0123
0124 struct serialize_top_level_result
0125 {
0126 error_code err;
0127 std::uint8_t seqnum{};
0128
0129 constexpr serialize_top_level_result(error_code ec) noexcept : err(ec) {}
0130 constexpr serialize_top_level_result(std::uint8_t seqnum) noexcept : seqnum(seqnum) {}
0131 };
0132
0133
0134 template <class Serializable>
0135 inline serialize_top_level_result serialize_top_level(
0136 const Serializable& input,
0137 std::vector<std::uint8_t>& to,
0138 std::uint8_t seqnum = 0,
0139 std::size_t max_buffer_size = static_cast<std::size_t>(-1),
0140 std::size_t max_frame_size = max_packet_size
0141 )
0142 {
0143 std::size_t initial_offset = to.size();
0144 serialization_context ctx(to, max_buffer_size, max_frame_size);
0145 input.serialize(ctx);
0146 auto err = ctx.error();
0147 if (err)
0148 return err;
0149 return ctx.write_frame_headers(seqnum, initial_offset);
0150 }
0151
0152
0153 template <class Serializable>
0154 inline std::uint8_t serialize_top_level_checked(
0155 const Serializable& input,
0156 std::vector<std::uint8_t>& to,
0157 std::uint8_t seqnum = 0,
0158 std::size_t max_frame_size = max_packet_size
0159 )
0160 {
0161 auto res = serialize_top_level(input, to, seqnum, static_cast<std::size_t>(-1), max_frame_size);
0162 BOOST_ASSERT(res.err == error_code());
0163 return res.seqnum;
0164 }
0165
0166 }
0167 }
0168 }
0169
0170
0171
0172
0173
0174 namespace boost {
0175 namespace mysql {
0176 namespace detail {
0177
0178
0179 inline protocol_field_type to_protocol_field_type(field_kind kind)
0180 {
0181 switch (kind)
0182 {
0183 case field_kind::null: return protocol_field_type::null;
0184 case field_kind::int64: return protocol_field_type::longlong;
0185 case field_kind::uint64: return protocol_field_type::longlong;
0186 case field_kind::string: return protocol_field_type::string;
0187 case field_kind::blob: return protocol_field_type::blob;
0188 case field_kind::float_: return protocol_field_type::float_;
0189 case field_kind::double_: return protocol_field_type::double_;
0190 case field_kind::date: return protocol_field_type::date;
0191 case field_kind::datetime: return protocol_field_type::datetime;
0192 case field_kind::time: return protocol_field_type::time;
0193 default: BOOST_ASSERT(false); return protocol_field_type::null;
0194 }
0195 }
0196
0197
0198 inline std::uint8_t get_collation_first_byte(std::uint32_t collation_id)
0199 {
0200 return static_cast<std::uint8_t>(collation_id % 0xff);
0201 }
0202
0203 }
0204 }
0205 }
0206
0207 void boost::mysql::detail::execute_stmt_command::serialize(serialization_context& ctx) const
0208 {
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222 constexpr int1 command_id{0x17};
0223 constexpr int1 flags{0};
0224 constexpr int4 iteration_count{1};
0225 constexpr int1 new_params_bind_flag{1};
0226
0227
0228 ctx.serialize_fixed(command_id, int4{statement_id}, flags, iteration_count);
0229
0230
0231 auto num_params = params.size();
0232
0233 if (num_params > 0)
0234 {
0235
0236 null_bitmap_generator null_gen(params);
0237 while (!null_gen.done())
0238 ctx.add(null_gen.next());
0239
0240
0241 new_params_bind_flag.serialize(ctx);
0242
0243
0244 for (field_view param : params)
0245 {
0246 field_kind kind = param.kind();
0247 protocol_field_type type = to_protocol_field_type(kind);
0248 std::uint8_t unsigned_flag = kind == field_kind::uint64 ? std::uint8_t(0x80) : std::uint8_t(0);
0249 ctx.serialize_fixed(int1{static_cast<std::uint8_t>(type)}, int1{unsigned_flag});
0250 }
0251
0252
0253 for (field_view param : params)
0254 {
0255 serialize_binary_field(ctx, param);
0256 }
0257 }
0258 }
0259
0260 void boost::mysql::detail::login_request::serialize(serialization_context& ctx) const
0261 {
0262 ctx.serialize_fixed(
0263 int4{negotiated_capabilities.get()},
0264 int4{max_packet_size},
0265 int1{get_collation_first_byte(collation_id)},
0266 string_fixed<23>{}
0267 );
0268 ctx.serialize(
0269 string_null{username},
0270 string_lenenc{to_string(auth_response)}
0271 );
0272 if (negotiated_capabilities.has(CLIENT_CONNECT_WITH_DB))
0273 {
0274 string_null{database}.serialize(ctx);
0275 }
0276 string_null{auth_plugin_name}.serialize(ctx);
0277 }
0278
0279 void boost::mysql::detail::ssl_request::serialize(serialization_context& ctx) const
0280 {
0281 ctx.serialize_fixed(
0282 int4{negotiated_capabilities.get()},
0283 int4{max_packet_size},
0284 int1{get_collation_first_byte(collation_id)},
0285 string_fixed<23>{}
0286 );
0287 }
0288
0289 #endif