File indexing completed on 2025-09-18 08:51:36
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MQTT5_MESSAGE_DECODERS_HPP
0009 #define BOOST_MQTT5_MESSAGE_DECODERS_HPP
0010
0011 #include <boost/mqtt5/types.hpp>
0012
0013 #include <boost/mqtt5/detail/internal_types.hpp>
0014
0015 #include <boost/mqtt5/impl/codecs/base_decoders.hpp>
0016
0017 #include <cstdint>
0018 #include <optional>
0019 #include <string>
0020 #include <utility>
0021 #include <vector>
0022
0023 namespace boost::mqtt5::decoders {
0024
0025 using byte_citer = detail::byte_citer;
0026
0027 using fixed_header = std::tuple<
0028 uint8_t,
0029 uint32_t
0030 >;
0031
0032 inline std::optional<fixed_header> decode_fixed_header(
0033 byte_citer& it, const byte_citer last
0034 ) {
0035 auto fixed_header_ = x3::byte_ >> basic::varint_;
0036 return type_parse(it, last, fixed_header_);
0037 }
0038
0039 using packet_id = uint16_t;
0040
0041 inline std::optional<packet_id> decode_packet_id(
0042 byte_citer& it
0043 ) {
0044 auto packet_id_ = x3::big_word;
0045 return type_parse(it, it + sizeof(uint16_t), packet_id_);
0046 }
0047
0048 using connect_message = std::tuple<
0049 std::string,
0050 std::optional<std::string>,
0051 std::optional<std::string>,
0052 uint16_t,
0053 bool,
0054 connect_props,
0055 std::optional<will>
0056 >;
0057
0058 inline std::optional<connect_message> decode_connect(
0059 uint32_t remain_length, byte_citer& it
0060 ) {
0061 auto var_header_ =
0062 basic::utf8_ >>
0063 x3::byte_ >>
0064 x3::byte_ >>
0065 x3::big_word >>
0066 prop::props_<connect_props>;
0067
0068 const byte_citer end = it + remain_length;
0069 auto vh = type_parse(it, end, var_header_);
0070 if (!vh)
0071 return std::optional<connect_message>{};
0072
0073 auto& [mqtt_str, version, flags, keep_alive, cprops] = *vh;
0074
0075 if (mqtt_str != "MQTT" || version != 5)
0076 return std::optional<connect_message>{};
0077
0078 bool has_will = (flags & 0b00000100);
0079 bool has_uname = (flags & 0b10000000);
0080 bool has_pwd = (flags & 0b01000000);
0081
0082 auto payload_ =
0083 basic::utf8_ >>
0084 basic::if_(has_will)[prop::props_<will_props>] >>
0085 basic::if_(has_will)[basic::utf8_] >>
0086 basic::if_(has_will)[basic::binary_] >>
0087 basic::if_(has_uname)[basic::utf8_] >>
0088 basic::if_(has_pwd)[basic::utf8_];
0089
0090 auto pload = type_parse(it, end, payload_);
0091 if (!pload)
0092 return std::optional<connect_message>{};
0093
0094 std::optional<will> w;
0095
0096 if (has_will)
0097 w.emplace(
0098 std::move(*std::get<2>(*pload)),
0099 std::move(*std::get<3>(*pload)),
0100 qos_e((flags & 0b00011000) >> 3),
0101 retain_e((flags & 0b00100000) >> 5),
0102 std::move(*std::get<1>(*pload))
0103 );
0104
0105 connect_message retval = {
0106 std::move(std::get<0>(*pload)),
0107 std::move(std::get<4>(*pload)),
0108 std::move(std::get<5>(*pload)),
0109 keep_alive,
0110 flags & 0b00000010,
0111 std::move(cprops),
0112 std::move(w)
0113 };
0114
0115 return std::optional<connect_message> { std::move(retval) };
0116 }
0117
0118 using connack_message = std::tuple<
0119 uint8_t,
0120 uint8_t,
0121 connack_props
0122 >;
0123
0124 inline std::optional<connack_message> decode_connack(
0125 uint32_t remain_length, byte_citer& it
0126 ) {
0127 auto connack_ = basic::scope_limit_(remain_length)[
0128 x3::byte_ >> x3::byte_ >> prop::props_<connack_props>
0129 ];
0130 return type_parse(it, it + remain_length, connack_);
0131 }
0132
0133 using publish_message = std::tuple<
0134 std::string,
0135 std::optional<uint16_t>,
0136 uint8_t,
0137 publish_props,
0138 std::string
0139 >;
0140
0141 inline std::optional<publish_message> decode_publish(
0142 uint8_t control_byte, uint32_t remain_length, byte_citer& it
0143 ) {
0144 uint8_t flags = control_byte & 0b1111;
0145 auto qos = qos_e((flags >> 1) & 0b11);
0146
0147 auto publish_ = basic::scope_limit_(remain_length)[
0148 basic::utf8_ >> basic::if_(qos != qos_e::at_most_once)[x3::big_word] >>
0149 x3::attr(flags) >> prop::props_<publish_props> >> basic::verbatim_
0150 ];
0151 return type_parse(it, it + remain_length, publish_);
0152 }
0153
0154 using puback_message = std::tuple<
0155 uint8_t,
0156 puback_props
0157 >;
0158
0159 inline std::optional<puback_message> decode_puback(
0160 uint32_t remain_length, byte_citer& it
0161 ) {
0162 if (remain_length == 0)
0163 return puback_message {};
0164 auto puback_ = basic::scope_limit_(remain_length)[
0165 x3::byte_ >> prop::props_<puback_props>
0166 ];
0167 return type_parse(it, it + remain_length, puback_);
0168 }
0169
0170 using pubrec_message = std::tuple<
0171 uint8_t,
0172 pubrec_props
0173 >;
0174
0175 inline std::optional<pubrec_message> decode_pubrec(
0176 uint32_t remain_length, byte_citer& it
0177 ) {
0178 if (remain_length == 0)
0179 return pubrec_message {};
0180 auto pubrec_ = basic::scope_limit_(remain_length)[
0181 x3::byte_ >> prop::props_<pubrec_props>
0182 ];
0183 return type_parse(it, it + remain_length, pubrec_);
0184 }
0185
0186 using pubrel_message = std::tuple<
0187 uint8_t,
0188 pubrel_props
0189 >;
0190
0191 inline std::optional<pubrel_message> decode_pubrel(
0192 uint32_t remain_length, byte_citer& it
0193 ) {
0194 if (remain_length == 0)
0195 return pubrel_message {};
0196 auto pubrel_ = basic::scope_limit_(remain_length)[
0197 x3::byte_ >> prop::props_<pubrel_props>
0198 ];
0199 return type_parse(it, it + remain_length, pubrel_);
0200 }
0201
0202 using pubcomp_message = std::tuple<
0203 uint8_t,
0204 pubcomp_props
0205 >;
0206
0207 inline std::optional<pubcomp_message> decode_pubcomp(
0208 uint32_t remain_length, byte_citer& it
0209 ) {
0210 if (remain_length == 0)
0211 return pubcomp_message {};
0212 auto pubcomp_ = basic::scope_limit_(remain_length)[
0213 x3::byte_ >> prop::props_<pubcomp_props>
0214 ];
0215 return type_parse(it, it + remain_length, pubcomp_);
0216 }
0217
0218 using subscribe_message = std::tuple<
0219 subscribe_props,
0220 std::vector<std::tuple<std::string, uint8_t>>
0221 >;
0222
0223 inline std::optional<subscribe_message> decode_subscribe(
0224 uint32_t remain_length, byte_citer& it
0225 ) {
0226 auto subscribe_ = basic::scope_limit_(remain_length)[
0227 prop::props_<subscribe_props> >> +(basic::utf8_ >> x3::byte_)
0228 ];
0229 return type_parse(it, it + remain_length, subscribe_);
0230 }
0231
0232 using suback_message = std::tuple<
0233 suback_props,
0234 std::vector<uint8_t>
0235 >;
0236
0237 inline std::optional<suback_message> decode_suback(
0238 uint32_t remain_length, byte_citer& it
0239 ) {
0240 auto suback_ = basic::scope_limit_(remain_length)[
0241 prop::props_<suback_props> >> +x3::byte_
0242 ];
0243 return type_parse(it, it + remain_length, suback_);
0244 }
0245
0246 using unsubscribe_message = std::tuple<
0247 unsubscribe_props,
0248 std::vector<std::string>
0249 >;
0250
0251 inline std::optional<unsubscribe_message> decode_unsubscribe(
0252 uint32_t remain_length, byte_citer& it
0253 ) {
0254 auto unsubscribe_ = basic::scope_limit_(remain_length)[
0255 prop::props_<unsubscribe_props> >> +basic::utf8_
0256 ];
0257 return type_parse(it, it + remain_length, unsubscribe_);
0258 }
0259
0260 using unsuback_message = std::tuple<
0261 unsuback_props,
0262 std::vector<uint8_t>
0263 >;
0264
0265 inline std::optional<unsuback_message> decode_unsuback(
0266 uint32_t remain_length, byte_citer& it
0267 ) {
0268 auto unsuback_ = basic::scope_limit_(remain_length)[
0269 prop::props_<unsuback_props> >> +x3::byte_
0270 ];
0271 return type_parse(it, it + remain_length, unsuback_);
0272 }
0273
0274 using disconnect_message = std::tuple<
0275 uint8_t,
0276 disconnect_props
0277 >;
0278
0279 inline std::optional<disconnect_message> decode_disconnect(
0280 uint32_t remain_length, byte_citer& it
0281 ) {
0282 if (remain_length == 0)
0283 return disconnect_message {};
0284 auto disconnect_ = basic::scope_limit_(remain_length)[
0285 x3::byte_ >> prop::props_<disconnect_props>
0286 ];
0287 return type_parse(it, it + remain_length, disconnect_);
0288 }
0289
0290 using auth_message = std::tuple<
0291 uint8_t,
0292 auth_props
0293 >;
0294
0295 inline std::optional<auth_message> decode_auth(
0296 uint32_t remain_length, byte_citer& it
0297 ) {
0298 if (remain_length == 0)
0299 return auth_message {};
0300 auto auth_ = basic::scope_limit_(remain_length)[
0301 x3::byte_ >> prop::props_<auth_props>
0302 ];
0303 return type_parse(it, it + remain_length, auth_);
0304 }
0305
0306
0307 }
0308
0309 #endif