2
0
mirror of https://github.com/boostorg/mysql.git synced 2026-02-14 12:52:17 +00:00

Refactored basic_types header

Split into value_holder, bytestring and protocol_types
This commit is contained in:
ruben
2020-03-20 13:06:55 +00:00
parent bddc3fd37e
commit faa7d52db4
13 changed files with 228 additions and 163 deletions

View File

@@ -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"

View File

@@ -0,0 +1,21 @@
#ifndef INCLUDE_BOOST_MYSQL_DETAIL_AUX_BYTESTRING_HPP_
#define INCLUDE_BOOST_MYSQL_DETAIL_AUX_BYTESTRING_HPP_
#include <vector>
namespace boost {
namespace mysql {
namespace detail {
template <typename Allocator>
using basic_bytestring = std::vector<std::uint8_t, Allocator>;
using bytestring = std::vector<std::uint8_t>;
}
}
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUX_BYTESTRING_HPP_ */

View File

@@ -0,0 +1,54 @@
#ifndef INCLUDE_BOOST_MYSQL_DETAIL_AUX_VALUE_HOLDER_HPP_
#define INCLUDE_BOOST_MYSQL_DETAIL_AUX_VALUE_HOLDER_HPP_
#include <utility>
namespace boost {
namespace mysql {
namespace detail {
template <typename T>
struct value_holder
{
using value_type = T;
value_type value;
value_holder(): value{} {};
template <typename U>
explicit constexpr value_holder(U&& u): value(std::forward<U>(u)) {}
constexpr bool operator==(const value_holder<T>& rhs) const { return value == rhs.value; }
constexpr bool operator!=(const value_holder<T>& rhs) const { return value != rhs.value; }
};
// Operations on value holders
struct get_value_type_helper
{
struct no_value_type {};
template <typename T>
static constexpr typename T::value_type get(typename T::value_type*);
template <typename T>
static constexpr no_value_type get(...);
};
template <typename T>
struct get_value_type
{
using type = decltype(get_value_type_helper().get<T>(nullptr));
using no_value_type = get_value_type_helper::no_value_type;
};
template <typename T>
using get_value_type_t = typename get_value_type<T>::type;
}
}
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUX_VALUE_HOLDER_HPP_ */

View File

@@ -3,7 +3,7 @@
#include <string_view>
#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 {

View File

@@ -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 <boost/asio/buffer.hpp>
#include <boost/asio/async_result.hpp>

View File

@@ -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 {

View File

@@ -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<std::uint8_t>(input.value)), ctx);
}
else if (input.value < 0x10000)
{
ctx.write(0xfc);
serialize(int2(static_cast<std::uint16_t>(input.value)), ctx);
}
else if (input.value < 0x1000000)
{
ctx.write(0xfd);
serialize(int3(static_cast<std::uint32_t>(input.value)), ctx);
}
else
{
ctx.write(0xfe);
serialize(int8(static_cast<std::uint64_t>(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_ */

View File

@@ -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 <string>

View File

@@ -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 <cstdint>
#include <string_view>
#include <array>
@@ -11,22 +12,6 @@ namespace boost {
namespace mysql {
namespace detail {
template <typename T>
struct value_holder
{
using value_type = T;
value_type value;
value_holder(): value{} {};
template <typename U>
explicit constexpr value_holder(U&& u): value(std::forward<U>(u)) {}
constexpr bool operator==(const value_holder<T>& rhs) const { return value == rhs.value; }
constexpr bool operator!=(const value_holder<T>& rhs) const { return value != rhs.value; }
};
struct int1 : value_holder<std::uint8_t> { using value_holder::value_holder; };
struct int2 : value_holder<std::uint16_t> { using value_holder::value_holder; };
struct int3 : value_holder<std::uint32_t> { using value_holder::value_holder; };
@@ -53,10 +38,6 @@ struct string_null : value_holder<std::string_view> { using value_holder::value_
struct string_eof : value_holder<std::string_view> { using value_holder::value_holder; };
struct string_lenenc : value_holder<std::string_view> { using value_holder::value_holder; };
template <typename Allocator>
using basic_bytestring = std::vector<std::uint8_t, Allocator>;
using bytestring = std::vector<std::uint8_t>;
} // detail
} // mysql

View File

@@ -6,9 +6,10 @@
#include <type_traits>
#include <algorithm>
#include <variant>
#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 <typename T>
static constexpr typename T::value_type get(typename T::value_type*);
template <typename T>
static constexpr no_value_type get(...);
};
template <typename T>
struct get_value_type
{
using type = decltype(get_value_type_helper().get<T>(nullptr));
using no_value_type = get_value_type_helper::no_value_type;
};
template <typename T>
struct is_fixed_size
{
private:
using value_type = typename get_value_type<T>::type;
public:
static constexpr bool value =
std::is_integral_v<value_type> &&
std::is_base_of_v<value_holder<value_type>, T>;
std::is_integral<get_value_type_t<T>>::value &&
std::is_base_of<value_holder<get_value_type_t<T>>, T>::value;
};
// Serialization of these types relies on this fact
static_assert(std::numeric_limits<float>::is_iec559);
static_assert(std::numeric_limits<double>::is_iec559);
template <> struct is_fixed_size<int_lenenc> : std::false_type {};
template <std::size_t N> struct is_fixed_size<string_fixed<N>>: 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<std::uint8_t>(input.value)), ctx);
}
else if (input.value < 0x10000)
{
ctx.write(0xfc);
serialize(int2(static_cast<std::uint16_t>(input.value)), ctx);
}
else if (input.value < 0x1000000)
{
ctx.write(0xfd);
serialize(int3(static_cast<std::uint32_t>(input.value)), ctx);
}
else
{
ctx.write(0xfe);
serialize(int8(static_cast<std::uint64_t>(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<float>::is_iec559);
static_assert(std::numeric_limits<double>::is_iec559);
template <typename T, typename=std::enable_if_t<std::is_floating_point_v<T>>>
errc deserialize(value_holder<T>& 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 <typename T>
constexpr bool is_fixed_size_fn() { return is_fixed_size<T>::value; }
} // detail
} // mysql
} // boost
#include "boost/mysql/detail/protocol/impl/serialization.ipp"
#endif

View File

@@ -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 {

View File

@@ -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 <boost/asio/ip/tcp.hpp>
#include <cassert>

View File

@@ -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 <algorithm>
namespace boost {