Remove using enum constructs

Summary: related to T13242

Reviewers: ivica

Reviewed By: ivica

Subscribers: miljen, iljazovic

Differential Revision: https://repo.mireo.local/D26841
This commit is contained in:
Korina Šimičević
2023-12-06 08:25:12 +01:00
parent 35b190ef67
commit 3640a4fb2a
6 changed files with 112 additions and 95 deletions

View File

@ -80,23 +80,21 @@ enum class error : int {
inline std::string client_error_to_string(error err) { inline std::string client_error_to_string(error err) {
using enum error;
switch (err) { switch (err) {
case malformed_packet: case error::malformed_packet:
return "Malformed packet has been detected"; return "Malformed packet has been detected";
case session_expired: case error::session_expired:
return "The Client's session does not exist or it has expired. "; return "The Client's session does not exist or it has expired. ";
case pid_overrun: case error::pid_overrun:
return "There are no more available Packet Identifiers to use."; return "There are no more available Packet Identifiers to use.";
case invalid_topic: case error::invalid_topic:
return "The Topic is invalid and " return "The Topic is invalid and "
"does not conform to the specification."; "does not conform to the specification.";
case qos_not_supported: case error::qos_not_supported:
return "The Server does not support the specified QoS"; return "The Server does not support the specified QoS";
case retain_not_available: case error::retain_not_available:
return "The Server does not support retained messages."; return "The Server does not support retained messages.";
case topic_alias_maximum_reached: case error::topic_alias_maximum_reached:
return "The Client attempted to send a Topic Alias " return "The Client attempted to send a Topic Alias "
"that is greater than Topic Alias Maximum."; "that is greater than Topic Alias Maximum.";
default: default:
@ -216,10 +214,9 @@ public:
std::string message() const { std::string message() const {
switch (_code) { switch (_code) {
case 0x00: case 0x00:
using enum reason_codes::category; if (_category == reason_codes::category::suback)
if (_category == suback)
return "The subscription is accepted with maximum QoS sent at 0"; return "The subscription is accepted with maximum QoS sent at 0";
if (_category == disconnect) if (_category == reason_codes::category::disconnect)
return "Close the connection normally. Do not send the Will Message"; return "Close the connection normally. Do not send the Will Message";
return "The operation completed successfully"; return "The operation completed successfully";
case 0x01: case 0x01:
@ -325,8 +322,6 @@ public:
namespace reason_codes { namespace reason_codes {
using enum category;
/** No Reason Code. A \ref client::error occurred.*/ /** No Reason Code. A \ref client::error occurred.*/
constexpr reason_code empty {}; constexpr reason_code empty {};
@ -334,10 +329,10 @@ constexpr reason_code empty {};
constexpr reason_code success { 0x00 }; constexpr reason_code success { 0x00 };
/** Close the connection normally. Do not send the Will Message. */ /** Close the connection normally. Do not send the Will Message. */
constexpr reason_code normal_disconnection { 0x00, disconnect }; constexpr reason_code normal_disconnection { 0x00, category::disconnect };
/** The subscription is accepted with maximum QoS sent at 0. */ /** The subscription is accepted with maximum QoS sent at 0. */
constexpr reason_code granted_qos_0 { 0x00, suback }; constexpr reason_code granted_qos_0 { 0x00, category::suback };
/** The subscription is accepted with maximum QoS sent at 1. */ /** The subscription is accepted with maximum QoS sent at 1. */
constexpr reason_code granted_qos_1 { 0x01 }; constexpr reason_code granted_qos_1 { 0x01 };
@ -475,11 +470,11 @@ constexpr reason_code wildcard_subscriptions_not_supported { 0xa2 };
namespace detail { namespace detail {
using enum category; template <
category cat,
template <category cat> std::enable_if_t<cat == category::connack, bool> = true
std::pair<reason_code*, size_t> valid_codes() >
requires (cat == connack) { std::pair<reason_code*, size_t> valid_codes() {
static reason_code valid_codes[] = { static reason_code valid_codes[] = {
success, unspecified_error, malformed_packet, success, unspecified_error, malformed_packet,
protocol_error, implementation_specific_error, protocol_error, implementation_specific_error,
@ -496,9 +491,11 @@ requires (cat == connack) {
return std::make_pair(valid_codes, len); return std::make_pair(valid_codes, len);
} }
template <category cat> template <
std::pair<reason_code*, size_t> valid_codes() category cat,
requires (cat == auth) { std::enable_if_t<cat == category::auth, bool> = true
>
std::pair<reason_code*, size_t> valid_codes() {
static reason_code valid_codes[] = { static reason_code valid_codes[] = {
success, continue_authentication success, continue_authentication
}; };
@ -506,9 +503,13 @@ requires (cat == auth) {
return std::make_pair(valid_codes, len); return std::make_pair(valid_codes, len);
} }
template <category cat> template <
std::pair<reason_code*, size_t> valid_codes() category cat,
requires (cat == puback || cat == pubrec) { std::enable_if_t<
cat == category::puback || cat == category::pubrec, bool
> = true
>
std::pair<reason_code*, size_t> valid_codes() {
static reason_code valid_codes[] = { static reason_code valid_codes[] = {
success, no_matching_subscribers, unspecified_error, success, no_matching_subscribers, unspecified_error,
implementation_specific_error, not_authorized, implementation_specific_error, not_authorized,
@ -519,9 +520,13 @@ requires (cat == puback || cat == pubrec) {
return std::make_pair(valid_codes, len); return std::make_pair(valid_codes, len);
} }
template <category cat> template <
std::pair<reason_code*, size_t> valid_codes() category cat,
requires (cat == pubrel || cat == pubcomp) { std::enable_if_t<
cat == category::pubrel || cat == category::pubcomp, bool
> = true
>
std::pair<reason_code*, size_t> valid_codes() {
static reason_code valid_codes[] = { static reason_code valid_codes[] = {
success, packet_id_not_found success, packet_id_not_found
}; };
@ -529,9 +534,11 @@ requires (cat == pubrel || cat == pubcomp) {
return std::make_pair(valid_codes, len); return std::make_pair(valid_codes, len);
} }
template <category cat> template <
std::pair<reason_code*, size_t> valid_codes() category cat,
requires (cat == suback) { std::enable_if_t<cat == category::suback, bool> = true
>
std::pair<reason_code*, size_t> valid_codes() {
static reason_code valid_codes[] = { static reason_code valid_codes[] = {
granted_qos_0, granted_qos_1, granted_qos_2, granted_qos_0, granted_qos_1, granted_qos_2,
unspecified_error, implementation_specific_error, unspecified_error, implementation_specific_error,
@ -545,9 +552,11 @@ requires (cat == suback) {
return std::make_pair(valid_codes, len); return std::make_pair(valid_codes, len);
} }
template <category cat> template <
std::pair<reason_code*, size_t> valid_codes() category cat,
requires (cat == unsuback) { std::enable_if_t<cat == category::unsuback, bool> = true
>
std::pair<reason_code*, size_t> valid_codes() {
static reason_code valid_codes[] = { static reason_code valid_codes[] = {
success, no_subscription_existed, success, no_subscription_existed,
unspecified_error, implementation_specific_error, unspecified_error, implementation_specific_error,
@ -558,9 +567,11 @@ requires (cat == unsuback) {
return std::make_pair(valid_codes, len); return std::make_pair(valid_codes, len);
} }
template <category cat> template <
std::pair<reason_code*, size_t> valid_codes() category cat,
requires (cat == disconnect) { std::enable_if_t<cat == category::disconnect, bool> = true
>
std::pair<reason_code*, size_t> valid_codes() {
static reason_code valid_codes[] = { static reason_code valid_codes[] = {
normal_disconnection, unspecified_error, normal_disconnection, unspecified_error,
malformed_packet,protocol_error, malformed_packet,protocol_error,
@ -606,4 +617,5 @@ struct is_error_code_enum <async_mqtt5::client::error> : std::true_type {};
} // end namespace boost::system } // end namespace boost::system
#endif // !ASYNC_MQTT5_ERROR_HPP #endif // !ASYNC_MQTT5_ERROR_HPP

View File

@ -171,15 +171,13 @@ public:
private: private:
static bool valid_header(uint8_t control_byte) { static bool valid_header(uint8_t control_byte) {
using enum control_code_e;
auto code = control_code_e(control_byte & 0b11110000); auto code = control_code_e(control_byte & 0b11110000);
if (code == publish) if (code == control_code_e::publish)
return true; return true;
auto res = control_byte & 0b00001111; auto res = control_byte & 0b00001111;
if (code == pubrel) if (code == control_code_e::pubrel)
return res == 0b00000010; return res == 0b00000010;
return res == 0b00000000; return res == 0b00000000;
} }
@ -189,17 +187,18 @@ private:
uint8_t control_byte, byte_citer first, byte_citer last uint8_t control_byte, byte_citer first, byte_citer last
) { ) {
using namespace decoders; using namespace decoders;
using enum control_code_e;
if (!valid_header(control_byte)) if (!valid_header(control_byte))
return complete(client::error::malformed_packet, 0, {}, {}); return complete(client::error::malformed_packet, 0, {}, {});
auto code = control_code_e(control_byte & 0b11110000); auto code = control_code_e(control_byte & 0b11110000);
if (code == pingresp) if (code == control_code_e::pingresp)
return perform(wait_for, asio::transfer_at_least(0)); return perform(wait_for, asio::transfer_at_least(0));
bool is_reply = code != publish && code != auth && code != disconnect; bool is_reply = code != control_code_e::publish &&
code != control_code_e::auth &&
code != control_code_e::disconnect;
if (is_reply) { if (is_reply) {
auto packet_id = decoders::decode_packet_id(first).value(); auto packet_id = decoders::decode_packet_id(first).value();
_svc._replies.dispatch(error_code {}, code, packet_id, first, last); _svc._replies.dispatch(error_code {}, code, packet_id, first, last);

View File

@ -83,11 +83,9 @@ private:
uint8_t control_byte, uint8_t control_byte,
byte_citer first, byte_citer last byte_citer first, byte_citer last
) { ) {
using enum control_code_e;
auto code = control_code_e(control_byte & 0b11110000); auto code = control_code_e(control_byte & 0b11110000);
switch (code) { switch (code) {
case publish: { case control_code_e::publish: {
auto msg = decoders::decode_publish( auto msg = decoders::decode_publish(
control_byte, std::distance(first, last), first control_byte, std::distance(first, last), first
); );
@ -99,12 +97,12 @@ private:
publish_rec_op { _svc_ptr }.perform(std::move(*msg)); publish_rec_op { _svc_ptr }.perform(std::move(*msg));
} }
break; break;
case disconnect: { case control_code_e::disconnect: {
_svc_ptr->close_stream(); _svc_ptr->close_stream();
_svc_ptr->open_stream(); _svc_ptr->open_stream();
} }
break; break;
case auth: { case control_code_e::auth: {
auto rv = decoders::decode_auth( auto rv = decoders::decode_auth(
std::distance(first, last), first std::distance(first, last), first
); );

View File

@ -18,17 +18,16 @@ inline qos_e extract_qos(uint8_t flags) {
} }
inline control_code_e extract_code(uint8_t control_byte) { inline control_code_e extract_code(uint8_t control_byte) {
using enum control_code_e;
constexpr uint8_t mask = 0b11110000; constexpr uint8_t mask = 0b11110000;
constexpr uint8_t publish_bits = 0b0011; constexpr uint8_t publish_bits = 0b0011;
constexpr uint8_t special_mask = 0b00000010; constexpr uint8_t special_mask = 0b00000010;
constexpr control_code_e codes_with_non_zero_end[] = { constexpr control_code_e codes_with_non_zero_end[] = {
pubrel, subscribe, unsubscribe control_code_e::pubrel, control_code_e::subscribe,
control_code_e::unsubscribe
}; };
if ((control_byte >> 4) == publish_bits) if ((control_byte >> 4) == publish_bits)
return publish; return control_code_e::publish;
if ((control_byte & mask) == control_byte) if ((control_byte & mask) == control_byte)
return control_code_e(control_byte & mask); return control_code_e(control_byte & mask);
@ -36,29 +35,27 @@ inline control_code_e extract_code(uint8_t control_byte) {
if (control_byte == (uint8_t(special_code) | special_mask)) if (control_byte == (uint8_t(special_code) | special_mask))
return special_code; return special_code;
return no_packet; return control_code_e::no_packet;
} }
inline std::string_view code_to_str(control_code_e code) { inline std::string_view code_to_str(control_code_e code) {
using enum control_code_e;
switch (code) { switch (code) {
case connect: return "CONNECT"; case control_code_e::connect: return "CONNECT";
case connack: return "CONNACK"; case control_code_e::connack: return "CONNACK";
case publish: return "PUBLISH"; case control_code_e::publish: return "PUBLISH";
case puback: return "PUBACK"; case control_code_e::puback: return "PUBACK";
case pubrec: return "PUBREC"; case control_code_e::pubrec: return "PUBREC";
case pubrel: return "PUBREL"; case control_code_e::pubrel: return "PUBREL";
case pubcomp: return "PUBCOMP"; case control_code_e::pubcomp: return "PUBCOMP";
case subscribe: return "SUBSCRIBE"; case control_code_e::subscribe: return "SUBSCRIBE";
case suback: return "SUBACK"; case control_code_e::suback: return "SUBACK";
case unsubscribe: return "UNSUBSCRIBE"; case control_code_e::unsubscribe: return "UNSUBSCRIBE";
case unsuback: return "UNSUBACK"; case control_code_e::unsuback: return "UNSUBACK";
case auth: return "AUTH"; case control_code_e::auth: return "AUTH";
case disconnect: return "DISCONNECT"; case control_code_e::disconnect: return "DISCONNECT";
case pingreq: return "PINGREQ"; case control_code_e::pingreq: return "PINGREQ";
case pingresp: return "PINGRESP"; case control_code_e::pingresp: return "PINGRESP";
} }
return "UNKNOWN"; return "UNKNOWN";
} }
@ -66,12 +63,10 @@ inline std::string_view code_to_str(control_code_e code) {
inline std::string to_readable_packet( inline std::string to_readable_packet(
std::string packet, error_code ec = {}, bool incoming = false std::string packet, error_code ec = {}, bool incoming = false
) { ) {
using enum control_code_e;
auto control_byte = uint8_t(*packet.data()); auto control_byte = uint8_t(*packet.data());
auto code = extract_code(control_byte); auto code = extract_code(control_byte);
if (code == no_packet) if (code == control_code_e::no_packet)
return {}; return {};
std::ostringstream stream; std::ostringstream stream;
@ -79,7 +74,10 @@ inline std::string to_readable_packet(
if (incoming) if (incoming)
stream << "-> "; stream << "-> ";
if (code == connect || code == connack || code == disconnect) { if (
code == control_code_e::connect || code == control_code_e::connack ||
code == control_code_e::disconnect
) {
stream << code_to_str(code) << (ec ? " ec: " + ec.message() : ""); stream << code_to_str(code) << (ec ? " ec: " + ec.message() : "");
return stream.str(); return stream.str();
} }
@ -89,7 +87,7 @@ inline std::string to_readable_packet(
begin, packet.cend(), decoders::basic::varint_ begin, packet.cend(), decoders::basic::varint_
); );
if (code == publish) { if (code == control_code_e::publish) {
auto publish = decoders::decode_publish( auto publish = decoders::decode_publish(
control_byte, *varlen, begin control_byte, *varlen, begin
); );

View File

@ -5,25 +5,24 @@
#include <boost/asio/detached.hpp> #include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp> #include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp> #include <boost/asio/steady_timer.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <async_mqtt5.hpp> #include <async_mqtt5.hpp>
using namespace async_mqtt5; using namespace async_mqtt5;
constexpr auto use_nothrow_awaitable = asio::as_tuple(asio::use_awaitable);
namespace async_mqtt5::test { namespace async_mqtt5::test {
enum cancellation_type { enum cancel_type {
ioc_stop = 1, ioc_stop = 1,
client_cancel client_cancel
}; };
} // end namespace async_mqtt5::test } // end namespace async_mqtt5::test
template <test::cancellation_type type> template <test::cancel_type type>
void cancel_async_receive() { void cancel_async_receive() {
using enum test::cancellation_type; using namespace test;
constexpr int num_handlers = 3; constexpr int num_handlers = 3;
constexpr int expected_handlers_called = type == ioc_stop ? 0 : num_handlers; constexpr int expected_handlers_called = type == ioc_stop ? 0 : num_handlers;
@ -59,9 +58,9 @@ void cancel_async_receive() {
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called); BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
} }
template <test::cancellation_type type> template <test::cancel_type type>
void cancel_async_publish() { void cancel_async_publish() {
using enum test::cancellation_type; using namespace test;
constexpr int expected_handlers_called = type == ioc_stop ? 0 : 3; constexpr int expected_handlers_called = type == ioc_stop ? 0 : 3;
int handlers_called = 0; int handlers_called = 0;
@ -113,9 +112,9 @@ void cancel_async_publish() {
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called); BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
} }
template <test::cancellation_type type> template <test::cancel_type type>
void cancel_during_connecting() { void cancel_during_connecting() {
using enum test::cancellation_type; using namespace test;
constexpr int expected_handlers_called = type == ioc_stop ? 0 : 1; constexpr int expected_handlers_called = type == ioc_stop ? 0 : 1;
int handlers_called = 0; int handlers_called = 0;
@ -155,32 +154,36 @@ BOOST_AUTO_TEST_SUITE(cancellation/*, *boost::unit_test::disabled()*/)
BOOST_AUTO_TEST_CASE(ioc_stop_async_receive) { BOOST_AUTO_TEST_CASE(ioc_stop_async_receive) {
cancel_async_receive<test::ioc_stop>(); cancel_async_receive<test::cancel_type::ioc_stop>();
} }
BOOST_AUTO_TEST_CASE(client_cancel_async_receive) { BOOST_AUTO_TEST_CASE(client_cancel_async_receive) {
cancel_async_receive<test::client_cancel>(); cancel_async_receive<test::cancel_type::client_cancel>();
} }
// passes on debian, hangs on windows in io_context destructor // passes on debian, hangs on windows in io_context destructor
BOOST_AUTO_TEST_CASE(ioc_stop_async_publish, *boost::unit_test::disabled() ) { BOOST_AUTO_TEST_CASE(ioc_stop_async_publish, *boost::unit_test::disabled() ) {
cancel_async_publish<test::ioc_stop>(); cancel_async_publish<test::cancel_type::ioc_stop>();
} }
BOOST_AUTO_TEST_CASE(client_cancel_async_publish) { BOOST_AUTO_TEST_CASE(client_cancel_async_publish) {
cancel_async_publish<test::client_cancel>(); cancel_async_publish<test::cancel_type::client_cancel>();
} }
// passes on debian, hangs on windows // passes on debian, hangs on windows
BOOST_AUTO_TEST_CASE(ioc_stop_cancel_during_connecting, *boost::unit_test::disabled() ) { BOOST_AUTO_TEST_CASE(ioc_stop_cancel_during_connecting, *boost::unit_test::disabled() ) {
cancel_during_connecting<test::ioc_stop>(); cancel_during_connecting<test::cancel_type::ioc_stop>();
} }
BOOST_AUTO_TEST_CASE(client_cancel_during_connecting) { BOOST_AUTO_TEST_CASE(client_cancel_during_connecting) {
cancel_during_connecting<test::client_cancel>(); cancel_during_connecting<test::cancel_type::client_cancel>();
} }
#ifdef BOOST_ASIO_HAS_CO_AWAIT
constexpr auto use_nothrow_awaitable = asio::as_tuple(asio::use_awaitable);
BOOST_AUTO_TEST_CASE(rerunning_the_client) { BOOST_AUTO_TEST_CASE(rerunning_the_client) {
asio::io_context ioc; asio::io_context ioc;
@ -222,4 +225,6 @@ BOOST_AUTO_TEST_CASE(rerunning_the_client) {
ioc.run(); ioc.run();
} }
#endif
BOOST_AUTO_TEST_SUITE_END(); BOOST_AUTO_TEST_SUITE_END();

View File

@ -1,11 +1,13 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <boost/asio/use_awaitable.hpp>
#ifdef BOOST_ASIO_HAS_CO_AWAIT
#include <boost/asio/as_tuple.hpp> #include <boost/asio/as_tuple.hpp>
#include <boost/asio/co_spawn.hpp> #include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp> #include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp> #include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp> #include <boost/asio/steady_timer.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/beast/websocket.hpp> #include <boost/beast/websocket.hpp>
@ -60,7 +62,7 @@ asio::awaitable<void> sanity_check(mqtt_client<StreamType, TlsContext>& c) {
auto [rec, topic, payload, publish_props] = co_await c.async_receive(use_nothrow_awaitable); auto [rec, topic, payload, publish_props] = co_await c.async_receive(use_nothrow_awaitable);
auto [unsub_ec, unsub_codes, unsub_props] = co_await c.async_unsubscribe( auto [unsub_ec, unsub_codes, unsub_props] = co_await c.async_unsubscribe(
std::vector<std::string>{"test/mqtt-test"}, unsubscribe_props{}, std::vector<std::string>{"test/mqtt-test"}, unsubscribe_props {},
use_nothrow_awaitable use_nothrow_awaitable
); );
BOOST_CHECK(!unsub_ec); BOOST_CHECK(!unsub_ec);
@ -145,3 +147,6 @@ BOOST_AUTO_TEST_CASE(websocket_tcp_client_check) {
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
#endif