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