2
0
mirror of https://github.com/boostorg/mysql.git synced 2026-02-15 13:12:21 +00:00

Unified (de)serialize with (de)serialize_fields

This commit is contained in:
ruben
2020-05-12 15:13:23 +01:00
parent 4b71760ff3
commit 92cd3569a3
20 changed files with 299 additions and 327 deletions

View File

@@ -56,7 +56,7 @@ public:
return;
if (msg_type == ok_packet_header)
{
err = deserialize_message(ok_packet_, ctx);
err = deserialize_message(ctx, ok_packet_);
if (err)
return;
field_count_ = 0;
@@ -72,7 +72,7 @@ public:
// of this packet, so we must rewind the context
ctx.rewind(1);
int_lenenc num_fields;
err = deserialize_message(num_fields, ctx);
err = deserialize_message(ctx, num_fields);
if (err)
return;
@@ -102,7 +102,7 @@ public:
{
column_definition_packet field_definition;
deserialization_context ctx (boost::asio::buffer(buffer_), channel_.current_capabilities());
auto err = deserialize_message(field_definition, ctx);
auto err = deserialize_message(ctx, field_definition);
if (err)
return err;

View File

@@ -49,7 +49,7 @@ inline error_code deserialize_handshake(
{
return make_error_code(errc::protocol_value_error);
}
return deserialize_message(output, ctx);
return deserialize_message(ctx, output);
}
// When receiving an auth response from the server, several things can happen:
@@ -176,7 +176,7 @@ public:
{
// We have received an auth switch request. Deserialize it
auth_switch_request_packet auth_sw;
err = deserialize_message(auth_sw, ctx);
err = deserialize_message(ctx, auth_sw);
if (err)
return err;
@@ -202,7 +202,7 @@ public:
{
// We have received an auth more data request. Deserialize it
auth_more_data_packet more_data;
err = deserialize_message(more_data, ctx);
err = deserialize_message(ctx, more_data);
if (err)
return err;

View File

@@ -46,7 +46,7 @@ public:
}
else
{
err = deserialize_message(response_, ctx);
err = deserialize_message(ctx, response_);
}
}
auto& get_buffer() noexcept { return channel_.shared_buffer(); }

View File

@@ -36,7 +36,7 @@ inline read_row_result process_read_message(
if (msg_type == eof_packet_header)
{
// end of resultset
err = deserialize_message(output_ok_packet, ctx);
err = deserialize_message(ctx, output_ok_packet);
return err ? read_row_result::error : read_row_result::eof;
if (err)
return read_row_result::error;

View File

@@ -16,13 +16,13 @@ namespace mysql {
namespace detail {
inline std::size_t get_binary_value_size(
const value& input,
const serialization_context& ctx
const serialization_context& ctx,
const value& input
) noexcept;
inline void serialize_binary_value(
const value& input,
serialization_context& ctx
serialization_context& ctx,
const value& input
) noexcept;

View File

@@ -61,7 +61,7 @@ template <>
struct serialization_traits<ok_packet, serialization_tag::struct_with_fields> :
noop_serialize<ok_packet>
{
static inline errc deserialize_(ok_packet& output, deserialization_context& ctx) noexcept;
static inline errc deserialize_(deserialization_context& ctx, ok_packet& output) noexcept;
};
// err packet
@@ -123,7 +123,7 @@ template <>
struct serialization_traits<column_definition_packet, serialization_tag::struct_with_fields> :
noop_serialize<column_definition_packet>
{
static inline errc deserialize_(column_definition_packet& output, deserialization_context& ctx) noexcept;
static inline errc deserialize_(deserialization_context& ctx, column_definition_packet& output) noexcept;
};
// connection quit

View File

@@ -48,7 +48,7 @@ template <>
struct serialization_traits<handshake_packet, serialization_tag::struct_with_fields> :
noop_serialize<handshake_packet>
{
static inline errc deserialize_(handshake_packet& output, deserialization_context& ctx) noexcept;
static inline errc deserialize_(deserialization_context& ctx, handshake_packet& output) noexcept;
};
// response
@@ -83,8 +83,10 @@ template <>
struct serialization_traits<handshake_response_packet, serialization_tag::struct_with_fields> :
noop_deserialize<handshake_response_packet>
{
static inline std::size_t get_size_(const handshake_response_packet& value, const serialization_context& ctx) noexcept;
static inline void serialize_(const handshake_response_packet& value, serialization_context& ctx) noexcept;
static inline std::size_t get_size_(const serialization_context& ctx,
const handshake_response_packet& value) noexcept;
static inline void serialize_(serialization_context& ctx,
const handshake_response_packet& value) noexcept;
};
// SSL request
@@ -141,7 +143,8 @@ template <>
struct serialization_traits<auth_switch_request_packet, serialization_tag::struct_with_fields> :
noop_serialize<auth_switch_request_packet>
{
static inline errc deserialize_(auth_switch_request_packet& output, deserialization_context& ctx) noexcept;
static inline errc deserialize_(deserialization_context& ctx,
auth_switch_request_packet& output) noexcept;
};
// more data (like auth switch request, but for the same plugin)

View File

@@ -26,7 +26,7 @@ errc deserialize_binary_value_value_holder(
) noexcept
{
DeserializableType deser;
auto err = deserialize(deser, ctx);
auto err = deserialize(ctx, deser);
if (err != errc::ok)
return err;
output = TargetType(deser.value);
@@ -95,7 +95,7 @@ inline errc deserialize_binary_ymd(
int1 day;
// Deserialize
auto err = deserialize_fields(ctx, year, month, day);
auto err = deserialize(ctx, year, month, day);
if (err != errc::ok)
return err;
@@ -123,7 +123,7 @@ inline errc deserialize_binary_value_date(
{
// Deserialize length
int1 length;
auto err = deserialize(length, ctx);
auto err = deserialize(ctx, length);
if (err != errc::ok)
return err;
@@ -166,7 +166,7 @@ inline errc deserialize_binary_value_datetime(
// Deserialize length
int1 length;
auto err = deserialize(length, ctx);
auto err = deserialize(ctx, length);
if (err != errc::ok)
return err;
@@ -189,7 +189,7 @@ inline errc deserialize_binary_value_datetime(
// Hours, minutes, seconds
if (length.value >= datetime_dhms_sz)
{
err = deserialize_fields(ctx, hours, minutes, seconds);
err = deserialize(ctx, hours, minutes, seconds);
if (err != errc::ok)
return err;
}
@@ -197,7 +197,7 @@ inline errc deserialize_binary_value_datetime(
// Microseconds
if (length.value >= datetime_dhmsu_sz)
{
err = deserialize(micros, ctx);
err = deserialize(ctx, micros);
if (err != errc::ok)
return err;
}
@@ -248,7 +248,7 @@ inline errc deserialize_binary_value_time(
// Deserialize length
int1 length;
auto err = deserialize(length, ctx);
auto err = deserialize(ctx, length);
if (err != errc::ok)
return err;
@@ -263,7 +263,7 @@ inline errc deserialize_binary_value_time(
// Sign, days, hours, minutes, seconds
if (length.value >= time_dhms_sz)
{
err = deserialize_fields(
err = deserialize(
ctx,
is_negative,
days,
@@ -278,7 +278,7 @@ inline errc deserialize_binary_value_time(
// Microseconds
if (length.value >= time_dhmsu_sz)
{
err = deserialize(microseconds, ctx);
err = deserialize(ctx, microseconds);
if (err != errc::ok)
return err;
}

View File

@@ -18,8 +18,8 @@ namespace detail {
template <typename T>
std::enable_if_t<std::is_floating_point_v<T>>
serialize_binary_value_impl(
T input,
serialization_context& ctx
serialization_context& ctx,
T input
)
{
// Endianness conversion
@@ -37,11 +37,11 @@ serialize_binary_value_impl(
// Does not add the length prefix byte
inline void serialize_binary_ymd(
const ::date::year_month_day& ymd,
serialization_context& ctx
serialization_context& ctx,
const ::date::year_month_day& ymd
) noexcept
{
serialize_fields(
serialize(
ctx,
int2(static_cast<std::uint16_t>(static_cast<int>(ymd.year()))),
int1(static_cast<std::uint8_t>(static_cast<unsigned>(ymd.month()))),
@@ -50,20 +50,20 @@ inline void serialize_binary_ymd(
}
inline void serialize_binary_value_impl(
const date& input,
serialization_context& ctx
serialization_context& ctx,
const date& input
)
{
::date::year_month_day ymd (input);
assert(ymd.ok());
serialize(int1(binc::date_sz), ctx);
serialize_binary_ymd(ymd, ctx);
serialize(ctx, int1(binc::date_sz));
serialize_binary_ymd(ctx, ymd);
}
inline void serialize_binary_value_impl(
const datetime& input,
serialization_context& ctx
serialization_context& ctx,
const datetime& input
)
{
// Break datetime
@@ -73,9 +73,9 @@ inline void serialize_binary_value_impl(
assert(ymd.ok());
// Serialize
serialize(int1(binc::datetime_dhmsu_sz), ctx);
serialize_binary_ymd(ymd, ctx);
serialize_fields(
serialize(ctx, int1(binc::datetime_dhmsu_sz));
serialize_binary_ymd(ctx, ymd);
serialize(
ctx,
int1(static_cast<std::uint8_t>(tod.hours().count())),
int1(static_cast<std::uint8_t>(tod.minutes().count())),
@@ -85,8 +85,8 @@ inline void serialize_binary_value_impl(
}
inline void serialize_binary_value_impl(
const time& input,
serialization_context& ctx
serialization_context& ctx,
const time& input
)
{
// Break time
@@ -98,7 +98,7 @@ inline void serialize_binary_value_impl(
int1 is_negative (input.count() < 0 ? 1 : 0);
// Serialize
serialize_fields(
serialize(
ctx,
int1(binc::time_dhmsu_sz),
is_negative,
@@ -121,7 +121,7 @@ struct size_visitor
template <typename T>
std::size_t operator()(T) noexcept { return sizeof(T); }
std::size_t operator()(std::string_view v) noexcept { return get_size(string_lenenc(v), ctx); }
std::size_t operator()(std::string_view v) noexcept { return get_size(ctx, string_lenenc(v)); }
std::size_t operator()(const date&) noexcept { return binc::date_sz + binc::length_sz; }
std::size_t operator()(const datetime&) noexcept { return binc::datetime_dhmsu_sz + binc::length_sz; }
std::size_t operator()(const time&) noexcept { return binc::time_dhmsu_sz + binc::length_sz; }
@@ -135,13 +135,13 @@ struct serialize_visitor
serialize_visitor(serialization_context& ctx) noexcept: ctx(ctx) {}
template <typename T>
void operator()(const T& v) noexcept { serialize_binary_value_impl(v, ctx); }
void operator()(const T& v) noexcept { serialize_binary_value_impl(ctx, v); }
void operator()(std::int32_t v) noexcept { serialize(int4_signed(v), ctx); }
void operator()(std::uint32_t v) noexcept { serialize(int4(v), ctx); }
void operator()(std::int64_t v) noexcept { serialize(int8_signed(v), ctx); }
void operator()(std::uint64_t v) noexcept { serialize(int8(v), ctx); }
void operator()(std::string_view v) noexcept { serialize(string_lenenc(v), ctx); }
void operator()(std::int32_t v) noexcept { serialize(ctx, int4_signed(v)); }
void operator()(std::uint32_t v) noexcept { serialize(ctx, int4(v)); }
void operator()(std::int64_t v) noexcept { serialize(ctx, int8_signed(v)); }
void operator()(std::uint64_t v) noexcept { serialize(ctx, int8(v)); }
void operator()(std::string_view v) noexcept { serialize(ctx, string_lenenc(v)); }
void operator()(std::nullptr_t) noexcept {}
};
@@ -151,16 +151,16 @@ struct serialize_visitor
inline std::size_t boost::mysql::detail::get_binary_value_size(
const value& input,
const serialization_context& ctx
const serialization_context& ctx,
const value& input
) noexcept
{
return std::visit(size_visitor(ctx), input);
}
inline void boost::mysql::detail::serialize_binary_value(
const value& input,
serialization_context& ctx
serialization_context& ctx,
const value& input
) noexcept
{
std::visit(serialize_visitor(ctx), input);

View File

@@ -57,7 +57,7 @@ boost::mysql::error_code boost::mysql::detail::channel<Stream>::process_header_r
{
packet_header header;
deserialization_context ctx (boost::asio::buffer(header_buffer_), capabilities(0)); // unaffected by capabilities
[[maybe_unused]] errc err = deserialize(header, ctx);
[[maybe_unused]] errc err = deserialize(ctx, header);
assert(err == errc::ok); // this should always succeed
if (!process_sequence_number(header.sequence_number.value))
{
@@ -76,7 +76,7 @@ void boost::mysql::detail::channel<Stream>::process_header_write(
header.packet_size.value = size_to_write;
header.sequence_number.value = next_sequence_number();
serialization_context ctx (capabilities(0), header_buffer_.data()); // capabilities not relevant here
serialize(header, ctx);
serialize(ctx, header);
}
template <typename Stream>

View File

@@ -13,12 +13,12 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::ok_packet,
boost::mysql::detail::serialization_tag::struct_with_fields
>::deserialize_(
ok_packet& output,
deserialization_context& ctx
deserialization_context& ctx,
ok_packet& output
) noexcept
{
{
auto err = deserialize_fields(
auto err = deserialize(
ctx,
output.affected_rows,
output.last_insert_id,
@@ -27,7 +27,7 @@ boost::mysql::detail::serialization_traits<
);
if (err == errc::ok && ctx.enough_size(1)) // message is optional, may be omitted
{
err = deserialize(output.info, ctx);
err = deserialize(ctx, output.info);
}
return err;
}
@@ -38,13 +38,13 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::column_definition_packet,
boost::mysql::detail::serialization_tag::struct_with_fields
>::deserialize_(
column_definition_packet& output,
deserialization_context& ctx
deserialization_context& ctx,
column_definition_packet& output
) noexcept
{
int_lenenc length_of_fixed_fields;
int2 final_padding;
return deserialize_fields(
return deserialize(
ctx,
output.catalog,
output.schema,
@@ -68,7 +68,7 @@ inline boost::mysql::error_code boost::mysql::detail::process_error_packet(
)
{
err_packet error_packet;
auto code = deserialize_message(error_packet, ctx);
auto code = deserialize_message(ctx, error_packet);
if (code)
return code;
info.set_message(std::string(error_packet.error_message.value));

View File

@@ -14,8 +14,8 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::handshake_packet,
boost::mysql::detail::serialization_tag::struct_with_fields
>::deserialize_(
handshake_packet& output,
deserialization_context& ctx
deserialization_context& ctx,
handshake_packet& output
) noexcept
{
constexpr std::uint8_t auth1_length = 8;
@@ -26,7 +26,7 @@ boost::mysql::detail::serialization_traits<
int1 auth_plugin_data_len;
string_fixed<10> reserved;
auto err = deserialize_fields(
auto err = deserialize(
ctx,
output.server_version,
output.connection_id,
@@ -52,7 +52,7 @@ boost::mysql::detail::serialization_traits<
return errc::server_unsupported;
// Deserialize following fields
err = deserialize_fields(
err = deserialize(
ctx,
auth_plugin_data_len,
reserved
@@ -69,7 +69,7 @@ boost::mysql::detail::serialization_traits<
ctx.advance(auth2_length);
// Auth plugin name
err = deserialize(output.auth_plugin_name, ctx);
err = deserialize(ctx, output.auth_plugin_name);
if (err != errc::ok)
return err;
@@ -86,22 +86,23 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::handshake_response_packet,
boost::mysql::detail::serialization_tag::struct_with_fields
>::get_size_(
const handshake_response_packet& value,
const serialization_context& ctx
const serialization_context& ctx,
const handshake_response_packet& value
) noexcept
{
std::size_t res =
get_size(value.client_flag, ctx) +
get_size(value.max_packet_size, ctx) +
get_size(value.character_set, ctx) +
23 + // filler
get_size(value.username, ctx) +
get_size(value.auth_response, ctx);
std::size_t res = get_size(
ctx,
value.client_flag,
value.max_packet_size,
value.character_set,
value.username,
value.auth_response
) + 23; // filler
if (ctx.get_capabilities().has(CLIENT_CONNECT_WITH_DB))
{
res += get_size(value.database, ctx);
res += get_size(ctx, value.database);
}
res += get_size(value.client_plugin_name, ctx);
res += get_size(ctx, value.client_plugin_name);
return res;
}
@@ -110,22 +111,25 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::handshake_response_packet,
boost::mysql::detail::serialization_tag::struct_with_fields
>::serialize_(
const handshake_response_packet& value,
serialization_context& ctx
serialization_context& ctx,
const handshake_response_packet& value
) noexcept
{
serialize(value.client_flag, ctx);
serialize(value.max_packet_size, ctx);
serialize(value.character_set, ctx);
std::uint8_t buffer [23] {};
ctx.write(buffer, sizeof(buffer));
serialize(value.username, ctx);
serialize(value.auth_response, ctx);
serialize(
ctx,
value.client_flag,
value.max_packet_size,
value.character_set,
string_fixed<23>{},
value.username,
value.auth_response
);
if (ctx.get_capabilities().has(CLIENT_CONNECT_WITH_DB))
{
serialize(value.database, ctx);
serialize(ctx, value.database);
}
serialize(value.client_plugin_name, ctx);
serialize(ctx, value.client_plugin_name);
}
inline boost::mysql::errc
@@ -133,11 +137,11 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::auth_switch_request_packet,
boost::mysql::detail::serialization_tag::struct_with_fields
>::deserialize_(
auth_switch_request_packet& output,
deserialization_context& ctx
deserialization_context& ctx,
auth_switch_request_packet& output
) noexcept
{
auto err = deserialize_fields(ctx, output.plugin_name, output.auth_plugin_data);
auto err = deserialize(ctx, output.plugin_name, output.auth_plugin_data);
auto& auth_data = output.auth_plugin_data.value;
// Discard an additional NULL at the end of auth data
if (!auth_data.empty())

View File

@@ -47,39 +47,6 @@ inline bool is_unsigned(
std::holds_alternative<std::uint64_t>(input);
}
// Performs a mapping from T to a type that can be serialized
template <typename T>
struct get_serializable_type { using type = T; };
template <typename T>
using get_serializable_type_t = typename get_serializable_type<T>::type;
// Indicate no serialization is required
struct dummy_serializable
{
explicit dummy_serializable(std::nullptr_t) {}
};
template <>
struct serialization_traits<dummy_serializable, serialization_tag::none> :
noop_serialize<dummy_serializable>
{
};
template <> struct get_serializable_type<std::uint32_t> { using type = int4; };
template <> struct get_serializable_type<std::int32_t> { using type = int4_signed; };
template <> struct get_serializable_type<std::uint64_t> { using type = int8; };
template <> struct get_serializable_type<std::int64_t> { using type = int8_signed; };
template <> struct get_serializable_type<std::string_view> { using type = string_lenenc; };
template <> struct get_serializable_type<std::nullptr_t> { using type = dummy_serializable; };
template <typename T>
inline get_serializable_type_t<T> to_serializable_type(T input) noexcept
{
return get_serializable_type_t<T>(input);
}
} // detail
} // mysql
} // boost
@@ -89,12 +56,12 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::com_stmt_prepare_ok_packet,
boost::mysql::detail::serialization_tag::struct_with_fields
>::deserialize_(
com_stmt_prepare_ok_packet& output,
deserialization_context& ctx
deserialization_context& ctx,
com_stmt_prepare_ok_packet& output
) noexcept
{
int1 reserved;
return deserialize_fields(
return deserialize(
ctx,
output.statement_id,
output.num_columns,
@@ -110,22 +77,20 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::com_stmt_execute_packet<ForwardIterator>,
boost::mysql::detail::serialization_tag::struct_with_fields
>::get_size_(
const com_stmt_execute_packet<ForwardIterator>& value,
const serialization_context& ctx
const serialization_context& ctx,
const com_stmt_execute_packet<ForwardIterator>& value
) noexcept
{
std::size_t res = 1 + // command ID
get_size(value.statement_id, ctx) +
get_size(value.flags, ctx) +
get_size(value.iteration_count, ctx);
get_size(ctx, value.statement_id, value.flags, value.iteration_count);
auto num_params = std::distance(value.params_begin, value.params_end);
assert(num_params >= 0 && num_params <= 255);
res += null_bitmap_traits(stmt_execute_null_bitmap_offset, num_params).byte_count();
res += get_size(value.new_params_bind_flag, ctx);
res += get_size(com_stmt_execute_param_meta_packet{}, ctx) * num_params;
res += get_size(ctx, value.new_params_bind_flag);
res += get_size(ctx, com_stmt_execute_param_meta_packet{}) * num_params;
for (auto it = value.params_begin; it != value.params_end; ++it)
{
res += get_binary_value_size(*it, ctx);
res += get_binary_value_size(ctx, *it);
}
return res;
}
@@ -136,14 +101,17 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::com_stmt_execute_packet<ForwardIterator>,
boost::mysql::detail::serialization_tag::struct_with_fields
>::serialize_(
const com_stmt_execute_packet<ForwardIterator>& input,
serialization_context& ctx
serialization_context& ctx,
const com_stmt_execute_packet<ForwardIterator>& input
) noexcept
{
serialize(int1(com_stmt_execute_packet<ForwardIterator>::command_id), ctx);
serialize(input.statement_id, ctx);
serialize(input.flags, ctx);
serialize(input.iteration_count, ctx);
serialize(
ctx,
int1(com_stmt_execute_packet<ForwardIterator>::command_id),
input.statement_id,
input.flags,
input.iteration_count
);
// Number of parameters
auto num_params = std::distance(input.params_begin, input.params_end);
@@ -163,7 +131,7 @@ boost::mysql::detail::serialization_traits<
ctx.advance(traits.byte_count());
// new parameters bind flag
serialize(input.new_params_bind_flag, ctx);
serialize(ctx, input.new_params_bind_flag);
// value metadata
com_stmt_execute_param_meta_packet meta;
@@ -171,13 +139,13 @@ boost::mysql::detail::serialization_traits<
{
meta.type = get_protocol_field_type(*it);
meta.unsigned_flag.value = is_unsigned(*it) ? 0x80 : 0;
serialize(meta, ctx);
serialize(ctx, meta);
}
// actual values
for (auto it = input.params_begin; it != input.params_end; ++it)
{
serialize_binary_value(*it, ctx);
serialize_binary_value(ctx, *it);
}
}

View File

@@ -38,109 +38,125 @@ struct is_command : decltype(is_command_helper::get<T>(nullptr))
{
};
template <std::size_t index, typename T>
template <typename T>
using struct_index_sequence = std::make_index_sequence<std::tuple_size_v<
decltype(get_struct_fields<T>::value)
>>;
template <typename T, std::size_t... index>
errc deserialize_struct(
[[maybe_unused]] T& output,
[[maybe_unused]] deserialization_context& ctx
deserialization_context& ctx,
T& output,
std::index_sequence<index...>
) noexcept
{
constexpr auto fields = get_struct_fields<T>::value;
if constexpr (index == std::tuple_size<decltype(fields)>::value)
{
return errc::ok;
}
else
{
constexpr auto pmem = std::get<index>(fields);
errc err = deserialize(output.*pmem, ctx);
if (err != errc::ok)
{
return err;
}
else
{
return deserialize_struct<index+1>(output, ctx);
}
}
return deserialize(ctx, (output.*(std::get<index>(fields)))...);
}
template <std::size_t index, typename T>
template <typename T, std::size_t... index>
void serialize_struct(
[[maybe_unused]] const T& value,
[[maybe_unused]] serialization_context& ctx
serialization_context& ctx,
const T& input,
std::index_sequence<index...>
) noexcept
{
constexpr auto fields = get_struct_fields<T>::value;
if constexpr (index < std::tuple_size<decltype(fields)>::value)
{
auto pmem = std::get<index>(fields);
serialize(value.*pmem, ctx);
serialize_struct<index+1>(value, ctx);
}
serialize(ctx, (input.*(std::get<index>(fields)))...);
}
template <std::size_t index, typename T>
template <typename T, std::size_t... index>
std::size_t get_size_struct(
[[maybe_unused]] const T& input,
[[maybe_unused]] const serialization_context& ctx
const serialization_context& ctx,
const T& input,
std::index_sequence<index...>
) noexcept
{
constexpr auto fields = get_struct_fields<T>::value;
if constexpr (index == std::tuple_size<decltype(fields)>::value)
{
return 0;
}
else
{
constexpr auto pmem = std::get<index>(fields);
return get_size_struct<index+1>(input, ctx) +
get_size(input.*pmem, ctx);
}
return get_size(ctx, (input.*(std::get<index>(fields)))...);
}
// Helpers for (de)serialize_fields
template <typename FirstType>
errc deserialize_fields_helper(deserialization_context& ctx, FirstType& field) noexcept
inline errc deserialize_helper(deserialization_context&) noexcept
{
return deserialize(field, ctx);
return errc::ok;
}
template <typename FirstType, typename... Types>
errc deserialize_fields_helper(
errc deserialize_helper(
deserialization_context& ctx,
FirstType& field,
Types&... fields_tail
FirstType& first,
Types&... tail
) noexcept
{
errc err = deserialize(field, ctx);
errc err = serialization_traits<FirstType>::deserialize_(ctx, first);
if (err == errc::ok)
{
err = deserialize_fields_helper(ctx, fields_tail...);
err = deserialize_helper(ctx, tail...);
}
return err;
}
template <typename FirstType>
void serialize_fields_helper(serialization_context& ctx, const FirstType& field) noexcept
inline void serialize_helper(serialization_context&) noexcept {}
template <typename FirstType, typename... Types>
void serialize_helper(
serialization_context& ctx,
const FirstType& first,
const Types&... tail
)
{
serialize(field, ctx);
serialization_traits<FirstType>::serialize_(ctx, first);
serialize_helper(ctx, tail...);
}
inline std::size_t get_size_helper(const serialization_context&) noexcept
{
return 0;
}
template <typename FirstType, typename... Types>
void serialize_fields_helper(
serialization_context& ctx,
const FirstType& field,
const Types&... fields_tail
)
std::size_t get_size_helper(
const serialization_context& ctx,
const FirstType& input,
const Types&... tail
) noexcept
{
serialize(field, ctx);
serialize_fields_helper(ctx, fields_tail...);
return serialization_traits<FirstType>::get_size_(ctx, input) +
get_size_helper(ctx, tail...);
}
} // detail
} // mysql
} // boost
// Common
template <typename... Types>
boost::mysql::errc boost::mysql::detail::deserialize(
deserialization_context& ctx,
Types&... output
) noexcept
{
return deserialize_helper(ctx, output...);
}
template <typename... Types>
void boost::mysql::detail::serialize(
serialization_context& ctx,
const Types&... input
) noexcept
{
serialize_helper(ctx, input...);
}
template <typename... Types>
std::size_t boost::mysql::detail::get_size(
const serialization_context& ctx,
const Types&... input
) noexcept
{
return get_size_helper(ctx, input...);
}
// Fixed size ints
template <typename T>
constexpr bool boost::mysql::detail::is_fixed_size_int()
@@ -157,8 +173,8 @@ boost::mysql::detail::serialization_traits<
T,
boost::mysql::detail::serialization_tag::fixed_size_int
>::deserialize_(
T& output,
deserialization_context& ctx
deserialization_context& ctx,
T& output
) noexcept
{
static_assert(std::is_standard_layout_v<decltype(T::value)>);
@@ -182,8 +198,8 @@ void boost::mysql::detail::serialization_traits<
T,
boost::mysql::detail::serialization_tag::fixed_size_int
>::serialize_(
T input,
serialization_context& ctx
serialization_context& ctx,
T input
) noexcept
{
boost::endian::native_to_little_inplace(input.value);
@@ -194,7 +210,7 @@ template <typename T>
constexpr std::size_t boost::mysql::detail::serialization_traits<
T,
boost::mysql::detail::serialization_tag::fixed_size_int
>::get_size_(T, const serialization_context&) noexcept
>::get_size_(const serialization_context&, T) noexcept
{
return get_int_size<T>();
}
@@ -205,8 +221,8 @@ boost::mysql::errc boost::mysql::detail::serialization_traits<
boost::mysql::detail::string_fixed<N>,
boost::mysql::detail::serialization_tag::none
>::deserialize_(
string_fixed<N>& output,
deserialization_context& ctx
deserialization_context& ctx,
string_fixed<N>& output
) noexcept
{
if (!ctx.enough_size(N))
@@ -225,12 +241,12 @@ boost::mysql::detail::serialization_traits<
T,
boost::mysql::detail::serialization_tag::enumeration
>::deserialize_(
T& output,
deserialization_context& ctx
deserialization_context& ctx,
T& output
) noexcept
{
serializable_type value;
errc err = deserialize(value, ctx);
errc err = deserialize(ctx, value);
if (err != errc::ok)
{
return err;
@@ -243,7 +259,7 @@ template <typename T>
std::size_t boost::mysql::detail::serialization_traits<
T,
boost::mysql::detail::serialization_tag::enumeration
>::get_size_(T, const serialization_context&) noexcept
>::get_size_(const serialization_context&, T) noexcept
{
return get_int_size<serializable_type>();
}
@@ -263,9 +279,12 @@ boost::mysql::errc
boost::mysql::detail::serialization_traits<
T,
boost::mysql::detail::serialization_tag::struct_with_fields
>::deserialize_(T& output, deserialization_context& ctx) noexcept
>::deserialize_(
deserialization_context& ctx,
T& output
) noexcept
{
return deserialize_struct<0>(output, ctx);
return deserialize_struct(ctx, output, struct_index_sequence<T>());
}
template <typename T>
@@ -274,17 +293,17 @@ boost::mysql::detail::serialization_traits<
T,
boost::mysql::detail::serialization_tag::struct_with_fields
>::serialize_(
[[maybe_unused]] const T& input,
[[maybe_unused]] serialization_context& ctx
[[maybe_unused]] serialization_context& ctx,
[[maybe_unused]] const T& input
) noexcept
{
// For commands, add the command ID. Commands are only sent by the client,
// so this is not considered in the deserialization functions.
if constexpr (is_command<T>::value)
{
serialize(int1(T::command_id), ctx);
serialize(ctx, int1(T::command_id));
}
serialize_struct<0>(input, ctx);
serialize_struct(ctx, input, struct_index_sequence<T>());
}
template <typename T>
@@ -292,10 +311,10 @@ std::size_t
boost::mysql::detail::serialization_traits<
T,
boost::mysql::detail::serialization_tag::struct_with_fields
>::get_size_(const T& input, const serialization_context& ctx) noexcept
>::get_size_(const serialization_context& ctx, const T& input) noexcept
{
std::size_t res = is_command<T>::value ? 1 : 0;
res += get_size_struct<0>(input, ctx);
res += get_size_struct(ctx, input, struct_index_sequence<T>());
return res;
}
@@ -308,20 +327,20 @@ void boost::mysql::detail::serialize_message(
)
{
serialization_context ctx (caps);
std::size_t size = get_size(input, ctx);
std::size_t size = get_size(ctx, input);
buffer.resize(size);
ctx.set_first(buffer.data());
serialize(input, ctx);
serialize(ctx, input);
assert(ctx.first() == buffer.data() + buffer.size());
}
template <typename Deserializable>
boost::mysql::error_code boost::mysql::detail::deserialize_message(
Deserializable& output,
deserialization_context& ctx
deserialization_context& ctx,
Deserializable& output
)
{
auto err = deserialize(output, ctx);
auto err = deserialize(ctx, output);
if (err != errc::ok)
return make_error_code(err);
if (!ctx.empty())
@@ -329,16 +348,6 @@ boost::mysql::error_code boost::mysql::detail::deserialize_message(
return error_code();
}
template <typename... Types>
boost::mysql::errc
boost::mysql::detail::deserialize_fields(
deserialization_context& ctx,
Types&... fields
) noexcept
{
return deserialize_fields_helper(ctx, fields...);
}
template <typename... Types>
void boost::mysql::detail::serialize_fields(
serialization_context& ctx,

View File

@@ -31,12 +31,12 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::int_lenenc,
boost::mysql::detail::serialization_tag::none
>::deserialize_(
int_lenenc& output,
deserialization_context& ctx
deserialization_context& ctx,
int_lenenc& output
) noexcept
{
int1 first_byte;
errc err = deserialize(first_byte, ctx);
errc err = deserialize(ctx, first_byte);
if (err != errc::ok)
{
return err;
@@ -45,19 +45,19 @@ boost::mysql::detail::serialization_traits<
if (first_byte.value == 0xFC)
{
int2 value;
err = deserialize(value, ctx);
err = deserialize(ctx, value);
output.value = value.value;
}
else if (first_byte.value == 0xFD)
{
int3 value;
err = deserialize(value, ctx);
err = deserialize(ctx, value);
output.value = value.value;
}
else if (first_byte.value == 0xFE)
{
int8 value;
err = deserialize(value, ctx);
err = deserialize(ctx, value);
output.value = value.value;
}
else
@@ -74,28 +74,28 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::int_lenenc,
boost::mysql::detail::serialization_tag::none
>::serialize_(
int_lenenc input,
serialization_context& ctx
serialization_context& ctx,
int_lenenc input
) noexcept
{
if (input.value < 251)
{
serialize(int1(static_cast<std::uint8_t>(input.value)), ctx);
serialize(ctx, int1(static_cast<std::uint8_t>(input.value)));
}
else if (input.value < 0x10000)
{
ctx.write(0xfc);
serialize(int2(static_cast<std::uint16_t>(input.value)), ctx);
serialize(ctx, int2(static_cast<std::uint16_t>(input.value)));
}
else if (input.value < 0x1000000)
{
ctx.write(0xfd);
serialize(int3(static_cast<std::uint32_t>(input.value)), ctx);
serialize(ctx, int3(static_cast<std::uint32_t>(input.value)));
}
else
{
ctx.write(0xfe);
serialize(int8(static_cast<std::uint64_t>(input.value)), ctx);
serialize(ctx, int8(static_cast<std::uint64_t>(input.value)));
}
}
@@ -104,8 +104,8 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::int_lenenc,
boost::mysql::detail::serialization_tag::none
>::get_size_(
int_lenenc input,
const serialization_context&
const serialization_context&,
int_lenenc input
) noexcept
{
if (input.value < 251)
@@ -123,8 +123,8 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::string_null,
boost::mysql::detail::serialization_tag::none
>::deserialize_(
string_null& output,
deserialization_context& ctx
deserialization_context& ctx,
string_null& output
) noexcept
{
auto string_end = std::find(ctx.first(), ctx.last(), 0);
@@ -142,8 +142,8 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::string_eof,
boost::mysql::detail::serialization_tag::none
>::deserialize_(
string_eof& output,
deserialization_context& ctx
deserialization_context& ctx,
string_eof& output
) noexcept
{
output.value = get_string(ctx.first(), ctx.last()-ctx.first());
@@ -156,12 +156,12 @@ boost::mysql::detail::serialization_traits<
boost::mysql::detail::string_lenenc,
boost::mysql::detail::serialization_tag::none
>::deserialize_(
string_lenenc& output,
deserialization_context& ctx
deserialization_context& ctx,
string_lenenc& output
) noexcept
{
int_lenenc length;
errc err = deserialize(length, ctx);
errc err = deserialize(ctx, length);
if (err != errc::ok)
{
return err;
@@ -188,7 +188,7 @@ boost::mysql::detail::deserialize_message_type(
{
int1 msg_type;
std::pair<mysql::error_code, std::uint8_t> res {};
auto err = deserialize(msg_type, ctx);
auto err = deserialize(ctx, msg_type);
if (err == errc::ok)
{
res.second = msg_type.value;

View File

@@ -371,7 +371,7 @@ boost::mysql::error_code boost::mysql::detail::deserialize_text_row(
else
{
string_lenenc value_str;
errc err = deserialize(value_str, ctx);
errc err = deserialize(ctx, value_str);
if (err != errc::ok)
return make_error_code(err);
err = deserialize_text_value(value_str.value, fields[i], output[i]);

View File

@@ -59,8 +59,8 @@ template <>
struct serialization_traits<com_stmt_prepare_ok_packet, serialization_tag::struct_with_fields> :
noop_serialize<com_stmt_prepare_ok_packet>
{
static inline errc deserialize_(com_stmt_prepare_ok_packet& output,
deserialization_context& ctx) noexcept;
static inline errc deserialize_(deserialization_context& ctx,
com_stmt_prepare_ok_packet& output) noexcept;
};
// execute
@@ -95,10 +95,10 @@ struct serialization_traits<
serialization_tag::struct_with_fields
> : noop_deserialize<com_stmt_execute_packet<ForwardIterator>>
{
static inline std::size_t get_size_(const com_stmt_execute_packet<ForwardIterator>& value,
const serialization_context& ctx) noexcept;
static inline void serialize_(const com_stmt_execute_packet<ForwardIterator>& input,
serialization_context& ctx) noexcept;
static inline std::size_t get_size_(const serialization_context& ctx,
const com_stmt_execute_packet<ForwardIterator>& value) noexcept;
static inline void serialize_(serialization_context& ctx,
const com_stmt_execute_packet<ForwardIterator>& input) noexcept;
};
struct com_stmt_execute_param_meta_packet

View File

@@ -36,23 +36,14 @@ constexpr serialization_tag get_serialization_tag();
template <typename T, serialization_tag=get_serialization_tag<T>()>
struct serialization_traits;
template <typename T>
errc deserialize(T& output, deserialization_context& ctx) noexcept
{
return serialization_traits<T>::deserialize_(output, ctx);
}
template <typename... Types>
errc deserialize(deserialization_context& ctx, Types&... output) noexcept;
template <typename T>
void serialize(const T& input, serialization_context& ctx) noexcept
{
serialization_traits<T>::serialize_(input, ctx);
}
template <typename... Types>
void serialize(serialization_context& ctx, const Types&... input) noexcept;
template <typename T>
std::size_t get_size(const T& input, const serialization_context& ctx) noexcept
{
return serialization_traits<T>::get_size_(input, ctx);
}
template <typename... Types>
std::size_t get_size(const serialization_context& ctx, const Types&... input) noexcept;
// Fixed-size integers
template <typename T>
@@ -61,18 +52,18 @@ constexpr bool is_fixed_size_int();
template <typename T>
struct serialization_traits<T, serialization_tag::fixed_size_int>
{
static errc deserialize_(T& output, deserialization_context& ctx) noexcept;
static void serialize_(T input, serialization_context& ctx) noexcept;
static constexpr std::size_t get_size_(T, const serialization_context&) noexcept;
static errc deserialize_(deserialization_context& ctx, T& output) noexcept;
static void serialize_(serialization_context& ctx, T input) noexcept;
static constexpr std::size_t get_size_(const serialization_context&, T) noexcept;
};
// int_lenenc
template <>
struct serialization_traits<int_lenenc, serialization_tag::none>
{
static inline errc deserialize_(int_lenenc& output, deserialization_context& ctx) noexcept;
static inline void serialize_(int_lenenc input, serialization_context& ctx) noexcept;
static inline std::size_t get_size_(int_lenenc input, const serialization_context&) noexcept;
static inline errc deserialize_(deserialization_context& ctx, int_lenenc& output) noexcept;
static inline void serialize_(serialization_context& ctx, int_lenenc input) noexcept;
static inline std::size_t get_size_(const serialization_context&, int_lenenc input) noexcept;
};
@@ -80,12 +71,12 @@ struct serialization_traits<int_lenenc, serialization_tag::none>
template <std::size_t N>
struct serialization_traits<string_fixed<N>, serialization_tag::none>
{
static errc deserialize_(string_fixed<N>& output, deserialization_context& ctx) noexcept;
static void serialize_(const string_fixed<N>& input, serialization_context& ctx) noexcept
static errc deserialize_(deserialization_context& ctx, string_fixed<N>& output) noexcept;
static void serialize_(serialization_context& ctx, const string_fixed<N>& input) noexcept
{
ctx.write(input.data(), N);
}
static constexpr std::size_t get_size_(const string_fixed<N>&, const serialization_context&) noexcept
static constexpr std::size_t get_size_(const serialization_context&, const string_fixed<N>&) noexcept
{
return N;
}
@@ -96,13 +87,13 @@ struct serialization_traits<string_fixed<N>, serialization_tag::none>
template <>
struct serialization_traits<string_null, serialization_tag::none>
{
static inline errc deserialize_(string_null& output, deserialization_context& ctx) noexcept;
static inline void serialize_(string_null input, serialization_context& ctx) noexcept
static inline errc deserialize_(deserialization_context& ctx, string_null& output) noexcept;
static inline void serialize_(serialization_context& ctx, string_null input) noexcept
{
ctx.write(input.value.data(), input.value.size());
ctx.write(0); // null terminator
}
static inline std::size_t get_size_(string_null input, const serialization_context&) noexcept
static inline std::size_t get_size_(const serialization_context&, string_null input) noexcept
{
return input.value.size() + 1;
}
@@ -112,12 +103,12 @@ struct serialization_traits<string_null, serialization_tag::none>
template <>
struct serialization_traits<string_eof, serialization_tag::none>
{
static inline errc deserialize_(string_eof& output, deserialization_context& ctx) noexcept;
static inline void serialize_(string_eof input, serialization_context& ctx) noexcept
static inline errc deserialize_(deserialization_context& ctx, string_eof& output) noexcept;
static inline void serialize_(serialization_context& ctx, string_eof input) noexcept
{
ctx.write(input.value.data(), input.value.size());
}
static inline std::size_t get_size_(string_eof input, const serialization_context&) noexcept
static inline std::size_t get_size_(const serialization_context&, string_eof input) noexcept
{
return input.value.size();
}
@@ -127,15 +118,15 @@ struct serialization_traits<string_eof, serialization_tag::none>
template <>
struct serialization_traits<string_lenenc, serialization_tag::none>
{
static inline errc deserialize_(string_lenenc& output, deserialization_context& ctx) noexcept;
static inline void serialize_(string_lenenc input, serialization_context& ctx) noexcept
static inline errc deserialize_(deserialization_context& ctx, string_lenenc& output) noexcept;
static inline void serialize_(serialization_context& ctx, string_lenenc input) noexcept
{
serialize(int_lenenc(input.value.size()), ctx);
serialize(ctx, int_lenenc(input.value.size()));
ctx.write(input.value.data(), input.value.size());
}
static inline std::size_t get_size_(string_lenenc input, const serialization_context& ctx) noexcept
static inline std::size_t get_size_(const serialization_context& ctx, string_lenenc input) noexcept
{
return get_size(int_lenenc(input.value.size()), ctx) + input.value.size();
return get_size(ctx, int_lenenc(input.value.size())) + input.value.size();
}
};
@@ -146,12 +137,12 @@ struct serialization_traits<T, serialization_tag::enumeration>
using underlying_type = std::underlying_type_t<T>;
using serializable_type = value_holder<underlying_type>;
static errc deserialize_(T& output, deserialization_context& ctx) noexcept;
static void serialize_(T input, serialization_context& ctx) noexcept
static errc deserialize_(deserialization_context& ctx, T& output) noexcept;
static void serialize_(serialization_context& ctx, T input) noexcept
{
serialize(serializable_type(static_cast<underlying_type>(input)), ctx);
serialize(ctx, serializable_type(static_cast<underlying_type>(input)));
}
static std::size_t get_size_(T, const serialization_context&) noexcept;
static std::size_t get_size_(const serialization_context&, T) noexcept;
};
// Structs and commands (messages)
@@ -173,9 +164,9 @@ constexpr bool is_struct_with_fields();
template <typename T>
struct serialization_traits<T, serialization_tag::struct_with_fields>
{
static errc deserialize_(T& output, deserialization_context& ctx) noexcept;
static void serialize_(const T& input, serialization_context& ctx) noexcept;
static std::size_t get_size_(const T& input, const serialization_context& ctx) noexcept;
static errc deserialize_(deserialization_context& ctx, T& output) noexcept;
static void serialize_(serialization_context& ctx, const T& input) noexcept;
static std::size_t get_size_(const serialization_context& ctx, const T& input) noexcept;
};
// Use these to make all messages implement all methods, leaving the not required
@@ -184,14 +175,14 @@ struct serialization_traits<T, serialization_tag::struct_with_fields>
template <typename T>
struct noop_serialize
{
static inline std::size_t get_size_(const T&, const serialization_context&) noexcept { return 0; }
static inline void serialize_(const T&, serialization_context&) noexcept {}
static inline std::size_t get_size_(const serialization_context&, const T&) noexcept { return 0; }
static inline void serialize_(serialization_context&, const T&) noexcept {}
};
template <typename T>
struct noop_deserialize
{
static inline errc deserialize_(T&, deserialization_context&) noexcept { return errc::ok; }
static inline errc deserialize_(deserialization_context&, T&) noexcept { return errc::ok; }
};
// Helper to serialize top-level messages
@@ -204,14 +195,11 @@ void serialize_message(
template <typename Deserializable>
error_code deserialize_message(
Deserializable& output,
deserialization_context& ctx
deserialization_context& ctx,
Deserializable& output
);
// Helpers for (de) serializing a set of fields
template <typename... Types>
errc deserialize_fields(deserialization_context& ctx, Types&... fields) noexcept;
template <typename... Types>
void serialize_fields(serialization_context& ctx, const Types&... fields) noexcept;