File indexing completed on 2025-01-18 09:42:41
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MYSQL_IMPL_INTERNAL_PROTOCOL_DESERIALIZE_BINARY_FIELD_IPP
0009 #define BOOST_MYSQL_IMPL_INTERNAL_PROTOCOL_DESERIALIZE_BINARY_FIELD_IPP
0010
0011 #pragma once
0012
0013 #include <boost/mysql/field_kind.hpp>
0014 #include <boost/mysql/field_view.hpp>
0015 #include <boost/mysql/metadata.hpp>
0016
0017 #include <boost/mysql/detail/config.hpp>
0018 #include <boost/mysql/detail/datetime.hpp>
0019
0020 #include <boost/mysql/impl/internal/protocol/bit_deserialization.hpp>
0021 #include <boost/mysql/impl/internal/protocol/constants.hpp>
0022 #include <boost/mysql/impl/internal/protocol/deserialize_binary_field.hpp>
0023 #include <boost/mysql/impl/internal/protocol/serialization.hpp>
0024
0025 #include <cmath>
0026 #include <cstddef>
0027
0028 namespace boost {
0029 namespace mysql {
0030 namespace detail {
0031
0032
0033 BOOST_MYSQL_STATIC_OR_INLINE
0034 deserialize_errc deserialize_binary_field_string(
0035 deserialization_context& ctx,
0036 field_view& output,
0037 bool is_blob
0038 ) noexcept
0039 {
0040 string_lenenc deser;
0041 auto err = deserialize(ctx, deser);
0042 if (err != deserialize_errc::ok)
0043 return err;
0044 if (is_blob)
0045 {
0046 output = field_view(
0047 blob_view(reinterpret_cast<const unsigned char*>(deser.value.data()), deser.value.size())
0048 );
0049 }
0050 else
0051 {
0052 output = field_view(deser.value);
0053 }
0054 return deserialize_errc::ok;
0055 }
0056
0057
0058 template <class TargetType, class DeserializableType>
0059 BOOST_MYSQL_STATIC_OR_INLINE deserialize_errc
0060 deserialize_binary_field_int_impl(deserialization_context& ctx, field_view& output) noexcept
0061 {
0062 DeserializableType deser;
0063 auto err = deserialize(ctx, deser);
0064 if (err != deserialize_errc::ok)
0065 return err;
0066 output = field_view(static_cast<TargetType>(deser));
0067 return deserialize_errc::ok;
0068 }
0069
0070 template <class DeserializableTypeUnsigned, class DeserializableTypeSigned>
0071 BOOST_MYSQL_STATIC_OR_INLINE deserialize_errc
0072 deserialize_binary_field_int(const metadata& meta, deserialization_context& ctx, field_view& output) noexcept
0073 {
0074 return meta.is_unsigned()
0075 ? deserialize_binary_field_int_impl<std::uint64_t, DeserializableTypeUnsigned>(ctx, output)
0076 : deserialize_binary_field_int_impl<std::int64_t, DeserializableTypeSigned>(ctx, output);
0077 }
0078
0079
0080
0081 BOOST_MYSQL_STATIC_OR_INLINE deserialize_errc
0082 deserialize_binary_field_bit(deserialization_context& ctx, field_view& output) noexcept
0083 {
0084 string_lenenc buffer;
0085 auto err = deserialize(ctx, buffer);
0086 if (err != deserialize_errc::ok)
0087 return err;
0088 return boost::mysql::detail::deserialize_bit(buffer.value, output);
0089 }
0090
0091
0092 template <class T>
0093 BOOST_MYSQL_STATIC_OR_INLINE deserialize_errc
0094 deserialize_binary_field_float(deserialization_context& ctx, field_view& output) noexcept
0095 {
0096
0097 if (!ctx.enough_size(sizeof(T)))
0098 return deserialize_errc::incomplete_message;
0099
0100
0101 T v = boost::endian::endian_load<T, sizeof(T), boost::endian::order::little>(ctx.first());
0102
0103
0104 if (std::isnan(v) || std::isinf(v))
0105 return deserialize_errc::protocol_value_error;
0106
0107
0108 ctx.advance(sizeof(T));
0109 output = field_view(v);
0110 return deserialize_errc::ok;
0111 }
0112
0113
0114 BOOST_MYSQL_STATIC_OR_INLINE
0115 deserialize_errc deserialize_binary_ymd(deserialization_context& ctx, boost::mysql::date& output)
0116 {
0117 using namespace boost::mysql::detail;
0118
0119 std::uint16_t year;
0120 std::uint8_t month;
0121 std::uint8_t day;
0122
0123
0124 auto err = deserialize(ctx, year, month, day);
0125 if (err != deserialize_errc::ok)
0126 return err;
0127
0128
0129 if (year > max_year || month > max_month || day > max_day)
0130 {
0131 return deserialize_errc::protocol_value_error;
0132 }
0133
0134 output = boost::mysql::date(year, month, day);
0135
0136 return deserialize_errc::ok;
0137 }
0138
0139 BOOST_MYSQL_STATIC_OR_INLINE
0140 deserialize_errc deserialize_binary_field_date(deserialization_context& ctx, field_view& output) noexcept
0141 {
0142 using namespace boost::mysql::detail::binc;
0143
0144
0145 std::uint8_t length;
0146 auto err = deserialize(ctx, length);
0147 if (err != deserialize_errc::ok)
0148 return err;
0149
0150
0151 if (length < date_sz)
0152 {
0153 output = field_view(boost::mysql::date());
0154 return deserialize_errc::ok;
0155 }
0156
0157
0158 boost::mysql::date d;
0159 err = deserialize_binary_ymd(ctx, d);
0160 if (err != deserialize_errc::ok)
0161 return err;
0162 output = field_view(d);
0163 return deserialize_errc::ok;
0164 }
0165
0166 BOOST_MYSQL_STATIC_OR_INLINE
0167 deserialize_errc deserialize_binary_field_datetime(deserialization_context& ctx, field_view& output) noexcept
0168 {
0169 using namespace binc;
0170
0171
0172 std::uint8_t length;
0173 auto err = deserialize(ctx, length);
0174 if (err != deserialize_errc::ok)
0175 return err;
0176
0177
0178
0179 boost::mysql::date d{};
0180 std::uint8_t hours = 0;
0181 std::uint8_t minutes = 0;
0182 std::uint8_t seconds = 0;
0183 std::uint32_t micros = 0;
0184
0185
0186 if (length >= datetime_d_sz)
0187 {
0188 err = deserialize_binary_ymd(ctx, d);
0189 if (err != deserialize_errc::ok)
0190 return err;
0191 }
0192
0193
0194 if (length >= datetime_dhms_sz)
0195 {
0196 err = deserialize(ctx, hours, minutes, seconds);
0197 if (err != deserialize_errc::ok)
0198 return err;
0199 }
0200
0201
0202 if (length >= datetime_dhmsu_sz)
0203 {
0204 err = deserialize(ctx, micros);
0205 if (err != deserialize_errc::ok)
0206 return err;
0207 }
0208
0209
0210 if (hours > max_hour || minutes > max_min || seconds > max_sec || micros > max_micro)
0211 {
0212 return deserialize_errc::protocol_value_error;
0213 }
0214
0215
0216 boost::mysql::datetime dt(d.year(), d.month(), d.day(), hours, minutes, seconds, micros);
0217 output = field_view(dt);
0218 return deserialize_errc::ok;
0219 }
0220
0221 BOOST_MYSQL_STATIC_OR_INLINE
0222 deserialize_errc deserialize_binary_field_time(deserialization_context& ctx, field_view& output) noexcept
0223 {
0224 using namespace boost::mysql::detail;
0225 using namespace boost::mysql::detail::binc;
0226
0227
0228 std::uint8_t length;
0229 auto err = deserialize(ctx, length);
0230 if (err != deserialize_errc::ok)
0231 return err;
0232
0233
0234 std::uint8_t is_negative = 0;
0235 std::uint32_t num_days = 0;
0236 std::uint8_t hours = 0;
0237 std::uint8_t minutes = 0;
0238 std::uint8_t seconds = 0;
0239 std::uint32_t microseconds = 0;
0240
0241
0242 if (length >= time_dhms_sz)
0243 {
0244 err = deserialize(ctx, is_negative, num_days, hours, minutes, seconds);
0245 if (err != deserialize_errc::ok)
0246 return err;
0247 }
0248
0249
0250 if (length >= time_dhmsu_sz)
0251 {
0252 err = deserialize(ctx, microseconds);
0253 if (err != deserialize_errc::ok)
0254 return err;
0255 }
0256
0257
0258 if (num_days > time_max_days || hours > max_hour || minutes > max_min || seconds > max_sec ||
0259 microseconds > max_micro)
0260 {
0261 return deserialize_errc::protocol_value_error;
0262 }
0263
0264
0265 output = field_view(boost::mysql::time(
0266 (is_negative ? -1 : 1) *
0267 (boost::mysql::days(num_days) + std::chrono::hours(hours) + std::chrono::minutes(minutes) +
0268 std::chrono::seconds(seconds) + std::chrono::microseconds(microseconds))
0269 ));
0270 return deserialize_errc::ok;
0271 }
0272
0273 }
0274 }
0275 }
0276
0277 boost::mysql::detail::deserialize_errc boost::mysql::detail::deserialize_binary_field(
0278 deserialization_context& ctx,
0279 const metadata& meta,
0280 field_view& output
0281 )
0282 {
0283 switch (meta.type())
0284 {
0285 case column_type::tinyint:
0286 return deserialize_binary_field_int<std::uint8_t, std::int8_t>(meta, ctx, output);
0287 case column_type::smallint:
0288 case column_type::year:
0289 return deserialize_binary_field_int<std::uint16_t, std::int16_t>(meta, ctx, output);
0290 case column_type::mediumint:
0291 case column_type::int_:
0292 return deserialize_binary_field_int<std::uint32_t, std::int32_t>(meta, ctx, output);
0293 case column_type::bigint:
0294 return deserialize_binary_field_int<std::uint64_t, std::int64_t>(meta, ctx, output);
0295 case column_type::bit: return deserialize_binary_field_bit(ctx, output);
0296 case column_type::float_: return deserialize_binary_field_float<float>(ctx, output);
0297 case column_type::double_: return deserialize_binary_field_float<double>(ctx, output);
0298 case column_type::timestamp:
0299 case column_type::datetime: return deserialize_binary_field_datetime(ctx, output);
0300 case column_type::date: return deserialize_binary_field_date(ctx, output);
0301 case column_type::time: return deserialize_binary_field_time(ctx, output);
0302
0303 case column_type::char_:
0304 case column_type::varchar:
0305 case column_type::text:
0306 case column_type::enum_:
0307 case column_type::set:
0308 case column_type::decimal:
0309 case column_type::json: return deserialize_binary_field_string(ctx, output, false);
0310
0311 case column_type::binary:
0312 case column_type::varbinary:
0313 case column_type::blob:
0314 case column_type::geometry:
0315 default: return deserialize_binary_field_string(ctx, output, true);
0316 }
0317 }
0318
0319 #endif