diff --git a/include/async_mqtt5/detail/async_traits.hpp b/include/async_mqtt5/detail/async_traits.hpp index 3736e16..efff434 100644 --- a/include/async_mqtt5/detail/async_traits.hpp +++ b/include/async_mqtt5/detail/async_traits.hpp @@ -28,19 +28,22 @@ void assign_tls_sni(const authority_path& ap, TlsContext& ctx, TlsStream& s); namespace detail { template -decltype(auto) tracking_executor(const Handler& handler, const DfltExecutor& ex) { +using tracking_type = std::decay_t< + typename asio::prefer_result< + asio::associated_executor_t, + asio::execution::outstanding_work_t::tracked_t + >::type +>; + +template +tracking_type +tracking_executor(const Handler& handler, const DfltExecutor& ex) { return asio::prefer( asio::get_associated_executor(handler, ex), asio::execution::outstanding_work.tracked ); } -template -using tracking_type = typename asio::prefer_result< - asio::associated_executor_t, - asio::execution::outstanding_work_t::tracked_t ->::type; - template concept has_async_write = requires(T a) { a.async_write( diff --git a/include/async_mqtt5/impl/internal/codecs/base_encoders.hpp b/include/async_mqtt5/impl/internal/codecs/base_encoders.hpp index 123544d..d141caf 100644 --- a/include/async_mqtt5/impl/internal/codecs/base_encoders.hpp +++ b/include/async_mqtt5/impl/internal/codecs/base_encoders.hpp @@ -75,7 +75,7 @@ public: return flag_def { val }; } - uint16_t byte_size() const { return sizeof(repr); } + size_t byte_size() const { return sizeof(repr); } template auto operator|(const flag_def& rhs) const { @@ -103,13 +103,13 @@ class int_val : public encoder { public: int_val(T val) : _val(val) {} - uint16_t byte_size() const { + size_t byte_size() const { if constexpr (is_optional) { - if (_val) return uint16_t(val_length(*_val)); - return uint16_t(0); + if (_val) return val_length(*_val); + return 0; } else - return uint16_t(val_length(_val)); + return val_length(_val); } std::string& encode(std::string& s) const { @@ -185,11 +185,11 @@ public: static_assert(std::is_reference_v || std::is_same_v); } - uint16_t byte_size() const { + size_t byte_size() const { if constexpr (is_optional) - return uint16_t(_val ? _with_length * 2 + val_length(*_val) : 0); + return _val ? _with_length * 2 + val_length(*_val) : 0; else - return uint16_t(_with_length * 2 + val_length(_val)); + return _with_length * 2 + val_length(_val); } std::string& encode(std::string& s) const { @@ -215,12 +215,12 @@ private: template std::string& encode_val(std::string& s, U&& u) const { using namespace boost::endian; - int16_t byte_len = int16_t(val_length(std::forward(u))); + auto byte_len = val_length(std::forward(u)); if (byte_len == 0 && !_with_length) return s; if (_with_length) { size_t sz = s.size(); s.resize(sz + 2); auto p = reinterpret_cast(s.data() + sz); - endian_store(p, byte_len); + endian_store(p, int16_t(byte_len)); } s.append(std::begin(u), std::begin(u) + byte_len); return s; @@ -266,8 +266,8 @@ public: composed_val(T lhs, U rhs) : _lhs(std::forward(lhs)), _rhs(std::forward(rhs)) {} - uint16_t byte_size() const { - return uint16_t(_lhs.byte_size() + _rhs.byte_size()); + size_t byte_size() const { + return _lhs.byte_size() + _rhs.byte_size(); } std::string& encode(std::string& s) const { diff --git a/test/unit/test/serialization.cpp b/test/unit/test/serialization.cpp index dd2bdbb..132eefc 100644 --- a/test/unit/test/serialization.cpp +++ b/test/unit/test/serialization.cpp @@ -114,13 +114,40 @@ BOOST_AUTO_TEST_CASE(test_publish) { BOOST_CHECK(packet_id); BOOST_CHECK_EQUAL(*packet_id_, packet_id); BOOST_CHECK_EQUAL(topic_, topic); - BOOST_CHECK_EQUAL(payload_, payload_); + BOOST_CHECK_EQUAL(payload_, payload); BOOST_CHECK_EQUAL(*pprops[prop::message_expiry_interval], message_expiry); BOOST_CHECK_EQUAL(*pprops[prop::content_type], content_type); BOOST_CHECK_EQUAL(pprops[prop::user_property][0], publish_prop_1); BOOST_CHECK_EQUAL(pprops[prop::user_property][1], publish_prop_2); } +BOOST_AUTO_TEST_CASE(test_large_publish) { + // testing variables + uint16_t packet_id = 40001; + std::string_view topic = "publish_topic"; + std::string large_payload(1'000'000, 'a'); + + auto msg = encoders::encode_publish( + packet_id, topic, large_payload, + qos_e::at_least_once, retain_e::yes, dup_e::no, + publish_props{} + ); + + byte_citer it = msg.cbegin(), last = msg.cend(); + auto header = decoders::decode_fixed_header(it, last); + BOOST_CHECK_MESSAGE(header, "Parsing PUBLISH fixed header failed."); + + const auto& [control_byte, remain_length] = *header; + auto rv = decoders::decode_publish(control_byte, remain_length, it); + BOOST_CHECK_MESSAGE(rv, "Parsing PUBLISH failed."); + + const auto& [topic_, packet_id_, flags, pprops, payload_] = *rv; + BOOST_CHECK(packet_id); + BOOST_CHECK_EQUAL(*packet_id_, packet_id); + BOOST_CHECK_EQUAL(topic_, topic); + BOOST_CHECK_EQUAL(payload_, large_payload); +} + BOOST_AUTO_TEST_CASE(test_puback) { // testing variables uint16_t packet_id = 9199;