diff --git a/include/boost/mysql/connection.hpp b/include/boost/mysql/connection.hpp index c4b0afb1..e95f23cd 100644 --- a/include/boost/mysql/connection.hpp +++ b/include/boost/mysql/connection.hpp @@ -3,7 +3,7 @@ #include "boost/mysql/detail/protocol/channel.hpp" #include "boost/mysql/detail/network_algorithms/handshake.hpp" -#include "boost/mysql/detail/basic_types.hpp" +#include "boost/mysql/detail/protocol/protocol_types.hpp" #include "boost/mysql/error.hpp" #include "boost/mysql/resultset.hpp" #include "boost/mysql/prepared_statement.hpp" diff --git a/include/boost/mysql/detail/aux/bytestring.hpp b/include/boost/mysql/detail/aux/bytestring.hpp new file mode 100644 index 00000000..8737f9c0 --- /dev/null +++ b/include/boost/mysql/detail/aux/bytestring.hpp @@ -0,0 +1,21 @@ +#ifndef INCLUDE_BOOST_MYSQL_DETAIL_AUX_BYTESTRING_HPP_ +#define INCLUDE_BOOST_MYSQL_DETAIL_AUX_BYTESTRING_HPP_ + +#include + +namespace boost { +namespace mysql { +namespace detail { + +template +using basic_bytestring = std::vector; + +using bytestring = std::vector; + +} +} +} + + + +#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUX_BYTESTRING_HPP_ */ diff --git a/include/boost/mysql/detail/aux/value_holder.hpp b/include/boost/mysql/detail/aux/value_holder.hpp new file mode 100644 index 00000000..6d9bd06d --- /dev/null +++ b/include/boost/mysql/detail/aux/value_holder.hpp @@ -0,0 +1,54 @@ +#ifndef INCLUDE_BOOST_MYSQL_DETAIL_AUX_VALUE_HOLDER_HPP_ +#define INCLUDE_BOOST_MYSQL_DETAIL_AUX_VALUE_HOLDER_HPP_ + +#include + +namespace boost { +namespace mysql { +namespace detail { + +template +struct value_holder +{ + using value_type = T; + + value_type value; + + value_holder(): value{} {}; + + template + explicit constexpr value_holder(U&& u): value(std::forward(u)) {} + + constexpr bool operator==(const value_holder& rhs) const { return value == rhs.value; } + constexpr bool operator!=(const value_holder& rhs) const { return value != rhs.value; } +}; + +// Operations on value holders +struct get_value_type_helper +{ + struct no_value_type {}; + + template + static constexpr typename T::value_type get(typename T::value_type*); + + template + static constexpr no_value_type get(...); +}; + +template +struct get_value_type +{ + using type = decltype(get_value_type_helper().get(nullptr)); + using no_value_type = get_value_type_helper::no_value_type; +}; + +template +using get_value_type_t = typename get_value_type::type; + +} +} +} + + + +#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUX_VALUE_HOLDER_HPP_ */ diff --git a/include/boost/mysql/detail/network_algorithms/handshake.hpp b/include/boost/mysql/detail/network_algorithms/handshake.hpp index 74311b6c..0b9e7b82 100644 --- a/include/boost/mysql/detail/network_algorithms/handshake.hpp +++ b/include/boost/mysql/detail/network_algorithms/handshake.hpp @@ -3,7 +3,7 @@ #include #include "boost/mysql/detail/protocol/channel.hpp" -#include "boost/mysql/detail/basic_types.hpp" +#include "boost/mysql/detail/protocol/protocol_types.hpp" #include "boost/mysql/collation.hpp" namespace boost { diff --git a/include/boost/mysql/detail/protocol/channel.hpp b/include/boost/mysql/detail/protocol/channel.hpp index 7e02748f..b731a707 100644 --- a/include/boost/mysql/detail/protocol/channel.hpp +++ b/include/boost/mysql/detail/protocol/channel.hpp @@ -2,7 +2,7 @@ #define MYSQL_ASIO_IMPL_CHANNEL_HPP #include "boost/mysql/error.hpp" -#include "boost/mysql/detail/basic_types.hpp" +#include "boost/mysql/detail/aux/bytestring.hpp" #include "boost/mysql/detail/protocol/capabilities.hpp" #include #include diff --git a/include/boost/mysql/detail/protocol/constants.hpp b/include/boost/mysql/detail/protocol/constants.hpp index da5ec5cd..d70a8b5d 100644 --- a/include/boost/mysql/detail/protocol/constants.hpp +++ b/include/boost/mysql/detail/protocol/constants.hpp @@ -1,7 +1,7 @@ #ifndef MYSQL_ASIO_IMPL_CONSTANTS_HPP #define MYSQL_ASIO_IMPL_CONSTANTS_HPP -#include "boost/mysql/detail/basic_types.hpp" +#include "boost/mysql/detail/protocol/protocol_types.hpp" namespace boost { namespace mysql { diff --git a/include/boost/mysql/detail/protocol/impl/serialization.ipp b/include/boost/mysql/detail/protocol/impl/serialization.ipp new file mode 100644 index 00000000..2e0d4a46 --- /dev/null +++ b/include/boost/mysql/detail/protocol/impl/serialization.ipp @@ -0,0 +1,125 @@ +#ifndef INCLUDE_BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_SERIALIZATION_IPP_ +#define INCLUDE_BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_SERIALIZATION_IPP_ + +inline boost::mysql::errc boost::mysql::detail::deserialize( + int_lenenc& output, + deserialization_context& ctx +) noexcept +{ + int1 first_byte; + errc err = deserialize(first_byte, ctx); + if (err != errc::ok) + { + return err; + } + + if (first_byte.value == 0xFC) + { + int2 value; + err = deserialize(value, ctx); + output.value = value.value; + } + else if (first_byte.value == 0xFD) + { + int3 value; + err = deserialize(value, ctx); + output.value = value.value; + } + else if (first_byte.value == 0xFE) + { + int8 value; + err = deserialize(value, ctx); + output.value = value.value; + } + else + { + err = errc::ok; + output.value = first_byte.value; + } + return err; +} + +inline void boost::mysql::detail::serialize( + int_lenenc input, + serialization_context& ctx +) noexcept +{ + if (input.value < 251) + { + serialize(int1(static_cast(input.value)), ctx); + } + else if (input.value < 0x10000) + { + ctx.write(0xfc); + serialize(int2(static_cast(input.value)), ctx); + } + else if (input.value < 0x1000000) + { + ctx.write(0xfd); + serialize(int3(static_cast(input.value)), ctx); + } + else + { + ctx.write(0xfe); + serialize(int8(static_cast(input.value)), ctx); + } +} + +inline std::size_t boost::mysql::detail::get_size( + int_lenenc input, const + serialization_context& +) noexcept +{ + if (input.value < 251) return 1; + else if (input.value < 0x10000) return 3; + else if (input.value < 0x1000000) return 4; + else return 9; +} + +inline boost::mysql::errc boost::mysql::detail::deserialize( + string_null& output, + deserialization_context& ctx +) noexcept +{ + auto string_end = std::find(ctx.first(), ctx.last(), 0); + if (string_end == ctx.last()) + { + return errc::incomplete_message; + } + output.value = get_string(ctx.first(), string_end-ctx.first()); + ctx.set_first(string_end + 1); // skip the null terminator + return errc::ok; +} + +inline boost::mysql::errc boost::mysql::detail::deserialize( + string_eof& output, + deserialization_context& ctx +) noexcept +{ + output.value = get_string(ctx.first(), ctx.last()-ctx.first()); + ctx.set_first(ctx.last()); + return errc::ok; +} + +inline boost::mysql::errc boost::mysql::detail::deserialize( + string_lenenc& output, + deserialization_context& ctx +) noexcept +{ + int_lenenc length; + errc err = deserialize(length, ctx); + if (err != errc::ok) + { + return err; + } + if (!ctx.enough_size(length.value)) + { + return errc::incomplete_message; + } + + output.value = get_string(ctx.first(), length.value); + ctx.advance(length.value); + return errc::ok; +} + +#endif /* INCLUDE_BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_SERIALIZATION_IPP_ */ diff --git a/include/boost/mysql/detail/protocol/messages.hpp b/include/boost/mysql/detail/protocol/messages.hpp index 4f17104f..c0993034 100644 --- a/include/boost/mysql/detail/protocol/messages.hpp +++ b/include/boost/mysql/detail/protocol/messages.hpp @@ -2,8 +2,9 @@ #define MYSQL_ASIO_IMPL_MESSAGES_HPP #include "boost/mysql/detail/protocol/serialization.hpp" -#include "boost/mysql/detail/basic_types.hpp" +#include "boost/mysql/detail/protocol/protocol_types.hpp" #include "boost/mysql/detail/protocol/constants.hpp" +#include "boost/mysql/detail/aux/bytestring.hpp" #include "boost/mysql/collation.hpp" #include "boost/mysql/value.hpp" #include diff --git a/include/boost/mysql/detail/basic_types.hpp b/include/boost/mysql/detail/protocol/protocol_types.hpp similarity index 75% rename from include/boost/mysql/detail/basic_types.hpp rename to include/boost/mysql/detail/protocol/protocol_types.hpp index 692835ac..0ab0916c 100644 --- a/include/boost/mysql/detail/basic_types.hpp +++ b/include/boost/mysql/detail/protocol/protocol_types.hpp @@ -1,6 +1,7 @@ #ifndef MYSQL_ASIO_IMPL_BASIC_TYPES_HPP #define MYSQL_ASIO_IMPL_BASIC_TYPES_HPP +#include "boost/mysql/detail/aux/value_holder.hpp" #include #include #include @@ -11,22 +12,6 @@ namespace boost { namespace mysql { namespace detail { -template -struct value_holder -{ - using value_type = T; - - value_type value; - - value_holder(): value{} {}; - - template - explicit constexpr value_holder(U&& u): value(std::forward(u)) {} - - constexpr bool operator==(const value_holder& rhs) const { return value == rhs.value; } - constexpr bool operator!=(const value_holder& rhs) const { return value != rhs.value; } -}; - struct int1 : value_holder { using value_holder::value_holder; }; struct int2 : value_holder { using value_holder::value_holder; }; struct int3 : value_holder { using value_holder::value_holder; }; @@ -53,10 +38,6 @@ struct string_null : value_holder { using value_holder::value_ struct string_eof : value_holder { using value_holder::value_holder; }; struct string_lenenc : value_holder { using value_holder::value_holder; }; -template -using basic_bytestring = std::vector; - -using bytestring = std::vector; } // detail } // mysql diff --git a/include/boost/mysql/detail/protocol/serialization.hpp b/include/boost/mysql/detail/protocol/serialization.hpp index 89487529..124f5d6b 100644 --- a/include/boost/mysql/detail/protocol/serialization.hpp +++ b/include/boost/mysql/detail/protocol/serialization.hpp @@ -6,9 +6,10 @@ #include #include #include -#include "boost/mysql/detail/basic_types.hpp" +#include "boost/mysql/detail/protocol/protocol_types.hpp" #include "boost/mysql/detail/protocol/serialization_context.hpp" #include "boost/mysql/detail/protocol/deserialization_context.hpp" +#include "boost/mysql/detail/aux/value_holder.hpp" #include "boost/mysql/error.hpp" namespace boost { @@ -24,40 +25,14 @@ namespace detail { */ // Fixed-size types -struct get_value_type_helper -{ - struct no_value_type {}; - - template - static constexpr typename T::value_type get(typename T::value_type*); - - template - static constexpr no_value_type get(...); -}; - -template -struct get_value_type -{ - using type = decltype(get_value_type_helper().get(nullptr)); - using no_value_type = get_value_type_helper::no_value_type; -}; - template struct is_fixed_size { -private: - using value_type = typename get_value_type::type; -public: static constexpr bool value = - std::is_integral_v && - std::is_base_of_v, T>; + std::is_integral>::value && + std::is_base_of>, T>::value; }; -// Serialization of these types relies on this fact -static_assert(std::numeric_limits::is_iec559); -static_assert(std::numeric_limits::is_iec559); - - template <> struct is_fixed_size : std::false_type {}; template struct is_fixed_size>: std::true_type {}; @@ -117,69 +92,9 @@ get_size(T, const serialization_context&) noexcept } // int_lenenc -inline errc deserialize(int_lenenc& output, deserialization_context& ctx) noexcept -{ - int1 first_byte; - errc err = deserialize(first_byte, ctx); - if (err != errc::ok) - { - return err; - } - - if (first_byte.value == 0xFC) - { - int2 value; - err = deserialize(value, ctx); - output.value = value.value; - } - else if (first_byte.value == 0xFD) - { - int3 value; - err = deserialize(value, ctx); - output.value = value.value; - } - else if (first_byte.value == 0xFE) - { - int8 value; - err = deserialize(value, ctx); - output.value = value.value; - } - else - { - err = errc::ok; - output.value = first_byte.value; - } - return err; -} -inline void serialize(int_lenenc input, serialization_context& ctx) noexcept -{ - if (input.value < 251) - { - serialize(int1(static_cast(input.value)), ctx); - } - else if (input.value < 0x10000) - { - ctx.write(0xfc); - serialize(int2(static_cast(input.value)), ctx); - } - else if (input.value < 0x1000000) - { - ctx.write(0xfd); - serialize(int3(static_cast(input.value)), ctx); - } - else - { - ctx.write(0xfe); - serialize(int8(static_cast(input.value)), ctx); - } -} -inline std::size_t get_size(int_lenenc input, const serialization_context&) noexcept -{ - if (input.value < 251) return 1; - else if (input.value < 0x10000) return 3; - else if (input.value < 0x1000000) return 4; - else return 9; -} +inline errc deserialize(int_lenenc& output, deserialization_context& ctx) noexcept; +inline void serialize(int_lenenc input, serialization_context& ctx) noexcept; +inline std::size_t get_size(int_lenenc input, const serialization_context&) noexcept; // Helper for strings inline std::string_view get_string(const std::uint8_t* from, std::size_t size) @@ -188,17 +103,7 @@ inline std::string_view get_string(const std::uint8_t* from, std::size_t size) } // string_null -inline errc deserialize(string_null& output, deserialization_context& ctx) noexcept -{ - auto string_end = std::find(ctx.first(), ctx.last(), 0); - if (string_end == ctx.last()) - { - return errc::incomplete_message; - } - output.value = get_string(ctx.first(), string_end-ctx.first()); - ctx.set_first(string_end + 1); // skip the null terminator - return errc::ok; -} +inline errc deserialize(string_null& output, deserialization_context& ctx) noexcept; inline void serialize(string_null input, serialization_context& ctx) noexcept { ctx.write(input.value.data(), input.value.size()); @@ -210,12 +115,7 @@ inline std::size_t get_size(string_null input, const serialization_context&) noe } // string_eof -inline errc deserialize(string_eof& output, deserialization_context& ctx) noexcept -{ - output.value = get_string(ctx.first(), ctx.last()-ctx.first()); - ctx.set_first(ctx.last()); - return errc::ok; -} +inline errc deserialize(string_eof& output, deserialization_context& ctx) noexcept; inline void serialize(string_eof input, serialization_context& ctx) noexcept { ctx.write(input.value.data(), input.value.size()); @@ -226,35 +126,15 @@ inline std::size_t get_size(string_eof input, const serialization_context&) noex } // string_lenenc -inline errc deserialize(string_lenenc& output, deserialization_context& ctx) noexcept -{ - int_lenenc length; - errc err = deserialize(length, ctx); - if (err != errc::ok) - { - return err; - } - if (!ctx.enough_size(length.value)) - { - return errc::incomplete_message; - } - - output.value = get_string(ctx.first(), length.value); - ctx.advance(length.value); - return errc::ok; -} +inline errc deserialize(string_lenenc& output, deserialization_context& ctx) noexcept; inline void serialize(string_lenenc input, serialization_context& ctx) noexcept { - int_lenenc length; - length.value = input.value.size(); - serialize(length, ctx); + serialize(int_lenenc(input.value.size()), ctx); ctx.write(input.value.data(), input.value.size()); } inline std::size_t get_size(string_lenenc input, const serialization_context& ctx) noexcept { - int_lenenc length; - length.value = input.value.size(); - return get_size(length, ctx) + input.value.size(); + return get_size(int_lenenc(input.value.size()), ctx) + input.value.size(); } // Enums @@ -285,6 +165,9 @@ std::size_t get_size(T, const serialization_context&) noexcept } // Floating points +static_assert(std::numeric_limits::is_iec559); +static_assert(std::numeric_limits::is_iec559); + template >> errc deserialize(value_holder& output, deserialization_context& ctx) noexcept { @@ -486,11 +369,10 @@ inline std::size_t get_size(dummy_serializable, const serialization_context&) no inline void serialize(dummy_serializable, serialization_context&) noexcept {} inline errc deserialize(dummy_serializable, deserialization_context&) noexcept { return errc::ok; } -template -constexpr bool is_fixed_size_fn() { return is_fixed_size::value; } - } // detail } // mysql } // boost +#include "boost/mysql/detail/protocol/impl/serialization.ipp" + #endif diff --git a/include/boost/mysql/metadata.hpp b/include/boost/mysql/metadata.hpp index e289d94a..c60c9505 100644 --- a/include/boost/mysql/metadata.hpp +++ b/include/boost/mysql/metadata.hpp @@ -2,7 +2,7 @@ #define MYSQL_ASIO_METADATA_HPP #include "boost/mysql/detail/protocol/messages.hpp" -#include "boost/mysql/detail/basic_types.hpp" +#include "boost/mysql/detail/aux/bytestring.hpp" #include "boost/mysql/field_type.hpp" namespace boost { diff --git a/include/boost/mysql/resultset.hpp b/include/boost/mysql/resultset.hpp index b9bdb314..7c4f9b48 100644 --- a/include/boost/mysql/resultset.hpp +++ b/include/boost/mysql/resultset.hpp @@ -5,6 +5,7 @@ #include "boost/mysql/metadata.hpp" #include "boost/mysql/detail/protocol/messages.hpp" #include "boost/mysql/detail/protocol/channel.hpp" +#include "boost/mysql/detail/aux/bytestring.hpp" #include "boost/mysql/detail/network_algorithms/common.hpp" // deserialize_row_fn #include #include diff --git a/include/boost/mysql/row.hpp b/include/boost/mysql/row.hpp index d690b0c1..cb3aa42d 100644 --- a/include/boost/mysql/row.hpp +++ b/include/boost/mysql/row.hpp @@ -1,10 +1,10 @@ #ifndef MYSQL_ASIO_ROW_HPP #define MYSQL_ASIO_ROW_HPP -#include "boost/mysql/detail/basic_types.hpp" +#include "boost/mysql/detail/aux/bytestring.hpp" +#include "boost/mysql/detail/aux/container_equals.hpp" #include "boost/mysql/value.hpp" #include "boost/mysql/metadata.hpp" -#include "boost/mysql/detail/aux/container_equals.hpp" #include namespace boost {