File indexing completed on 2025-09-18 08:51:36
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MQTT5_MESSAGE_ENCODERS_HPP
0009 #define BOOST_MQTT5_MESSAGE_ENCODERS_HPP
0010
0011 #include <boost/mqtt5/types.hpp>
0012
0013 #include <boost/mqtt5/impl/codecs/base_encoders.hpp>
0014
0015 #include <cstdint>
0016 #include <optional>
0017 #include <string>
0018 #include <string_view>
0019 #include <vector>
0020
0021 namespace boost::mqtt5::encoders {
0022
0023 template <typename encoder>
0024 std::string encode(const encoder& e) {
0025 std::string s;
0026 s.reserve(e.byte_size());
0027 s << e;
0028 return s;
0029 }
0030
0031 inline std::string encode_connect(
0032 std::string_view client_id,
0033 std::optional<std::string_view> user_name,
0034 std::optional<std::string_view> password,
0035 uint16_t keep_alive, bool clean_start,
0036 const connect_props& props,
0037 const std::optional<will>& w
0038 ) {
0039
0040 auto packet_type_ =
0041 basic::flag<4>(0b0001) |
0042 basic::flag<4>(0);
0043
0044 auto conn_flags_ =
0045 basic::flag<1>(user_name) |
0046 basic::flag<1>(password) |
0047 basic::flag<1>(w, &will::retain) |
0048 basic::flag<2>(w, &will::qos) |
0049 basic::flag<1>(w) |
0050 basic::flag<1>(clean_start) |
0051 basic::flag<1>(0);
0052
0053 auto var_header_ =
0054 basic::utf8_("MQTT") &
0055 basic::byte_(uint8_t(5)) &
0056 conn_flags_ &
0057 basic::int16_(keep_alive) &
0058 prop::props_(props);
0059
0060 auto payload_ =
0061 basic::utf8_(client_id) &
0062 prop::props_(w) &
0063 basic::utf8_(w, &will::topic) &
0064 basic::binary_(w, &will::message) &
0065 basic::utf8_(user_name) &
0066 basic::utf8_(password);
0067
0068 auto message_body_ = var_header_ & payload_;
0069
0070 auto fixed_header_ =
0071 packet_type_ &
0072 basic::varlen_(message_body_.byte_size());
0073
0074 auto connect_message_ = fixed_header_ & message_body_;
0075
0076 return encode(connect_message_);
0077 }
0078
0079 inline std::string encode_connack(
0080 bool session_present,
0081 uint8_t reason_code,
0082 const connack_props& props
0083 ) {
0084
0085 auto packet_type_ =
0086 basic::flag<4>(0b0010) |
0087 basic::flag<4>(0);
0088
0089 auto var_header_ =
0090 basic::flag<1>(session_present) &
0091 basic::byte_(reason_code) &
0092 prop::props_(props);
0093
0094 auto fixed_header_ =
0095 packet_type_ &
0096 basic::varlen_(var_header_.byte_size());
0097
0098 auto connack_message_ = fixed_header_ & var_header_;
0099
0100 return encode(connack_message_);
0101 }
0102
0103 inline std::string encode_publish(
0104 uint16_t packet_id,
0105 std::string_view topic_name,
0106 std::string_view payload,
0107 qos_e qos, retain_e retain, dup_e dup,
0108 const publish_props& props
0109 ) {
0110
0111 std::optional<uint16_t> used_packet_id;
0112 if (qos != qos_e::at_most_once) used_packet_id.emplace(packet_id);
0113
0114 auto packet_type_ =
0115 basic::flag<4>(0b0011) |
0116 basic::flag<1>(dup) |
0117 basic::flag<2>(qos) |
0118 basic::flag<1>(retain);
0119
0120 auto var_header_ =
0121 basic::utf8_(topic_name) &
0122 basic::int16_(used_packet_id) &
0123 prop::props_(props);
0124
0125 auto message_body_ = var_header_ & basic::verbatim_(payload);
0126
0127 auto fixed_header_ =
0128 packet_type_ &
0129 basic::varlen_(message_body_.byte_size());
0130
0131 auto publish_message_ = fixed_header_ & message_body_;
0132
0133 return encode(publish_message_);
0134 }
0135
0136 inline std::string encode_puback(
0137 uint16_t packet_id,
0138 uint8_t reason_code,
0139 const puback_props& props
0140 ) {
0141
0142 auto packet_type_ =
0143 basic::flag<4>(0b0100) |
0144 basic::flag<4>(0);
0145
0146 auto var_header_ =
0147 basic::int16_(packet_id) &
0148 basic::byte_(reason_code) &
0149 prop::props_may_omit_(props);
0150
0151 auto fixed_header_ =
0152 packet_type_ &
0153 basic::varlen_(var_header_.byte_size());
0154
0155 auto puback_message_ = fixed_header_ & var_header_;
0156
0157 return encode(puback_message_);
0158 }
0159
0160 inline std::string encode_pubrec(
0161 uint16_t packet_id,
0162 uint8_t reason_code,
0163 const pubrec_props& props
0164 ) {
0165
0166 auto packet_type_ =
0167 basic::flag<4>(0b0101) |
0168 basic::flag<4>(0b0000);
0169
0170 auto var_header_ =
0171 basic::int16_(packet_id) &
0172 basic::byte_(reason_code) &
0173 prop::props_may_omit_(props);
0174
0175 auto fixed_header_ =
0176 packet_type_ &
0177 basic::varlen_(var_header_.byte_size());
0178
0179 auto pubrec_message_ = fixed_header_ & var_header_;
0180
0181 return encode(pubrec_message_);
0182 }
0183
0184 inline std::string encode_pubrel(
0185 uint16_t packet_id,
0186 uint8_t reason_code,
0187 const pubrel_props& props
0188 ) {
0189
0190 auto packet_type_ =
0191 basic::flag<4>(0b0110) |
0192 basic::flag<4>(0b0010);
0193
0194 auto var_header_ =
0195 basic::int16_(packet_id) &
0196 basic::byte_(reason_code) &
0197 prop::props_may_omit_(props);
0198
0199 auto fixed_header_ =
0200 packet_type_ &
0201 basic::varlen_(var_header_.byte_size());
0202
0203 auto pubrel_message_ = fixed_header_ & var_header_;
0204
0205 return encode(pubrel_message_);
0206 }
0207
0208 inline std::string encode_pubcomp(
0209 uint16_t packet_id,
0210 uint8_t reason_code,
0211 const pubcomp_props& props
0212 ) {
0213
0214 auto packet_type_ =
0215 basic::flag<4>(0b0111) |
0216 basic::flag<4>(0b0000);
0217
0218 auto var_header_ =
0219 basic::int16_(packet_id) &
0220 basic::byte_(reason_code) &
0221 prop::props_may_omit_(props);
0222
0223 auto fixed_header_ =
0224 packet_type_ &
0225 basic::varlen_(var_header_.byte_size());
0226
0227 auto pubcomp_message_ = fixed_header_ & var_header_;
0228
0229 return encode(pubcomp_message_);
0230 }
0231
0232 inline std::string encode_subscribe(
0233 uint16_t packet_id,
0234 const std::vector<subscribe_topic>& topics,
0235 const subscribe_props& props
0236 ) {
0237
0238 auto packet_type_ =
0239 basic::flag<4>(0b1000) |
0240 basic::flag<4>(0b0010);
0241
0242 size_t payload_size = 0;
0243 for (const auto& [topic_filter, _]: topics)
0244 payload_size += basic::utf8_(topic_filter).byte_size() + 1;
0245
0246 auto var_header_ =
0247 basic::int16_(packet_id) &
0248 prop::props_(props);
0249
0250 auto message_ =
0251 packet_type_ &
0252 basic::varlen_(var_header_.byte_size() + payload_size) &
0253 var_header_;
0254
0255 auto s = encode(message_);
0256 s.reserve(s.size() + payload_size);
0257
0258 for (const auto& [topic_filter, sub_opts]: topics) {
0259 auto opts_ =
0260 basic::flag<2>(sub_opts.retain_handling) |
0261 basic::flag<1>(sub_opts.retain_as_published) |
0262 basic::flag<1>(sub_opts.no_local) |
0263 basic::flag<2>(sub_opts.max_qos);
0264 auto filter_ = basic::utf8_(topic_filter) & opts_;
0265 s << filter_;
0266 }
0267
0268 return s;
0269 }
0270
0271 inline std::string encode_suback(
0272 uint16_t packet_id,
0273 const std::vector<uint8_t>& reason_codes,
0274 const suback_props& props
0275 ) {
0276
0277 auto packet_type_ =
0278 basic::flag<4>(0b1001) |
0279 basic::flag<4>(0b0000);
0280
0281 auto var_header_ =
0282 basic::int16_(packet_id) &
0283 prop::props_(props);
0284
0285 auto message_ =
0286 packet_type_ &
0287 basic::varlen_(var_header_.byte_size() + reason_codes.size()) &
0288 var_header_;
0289
0290 auto s = encode(message_);
0291 s.reserve(s.size() + reason_codes.size());
0292
0293 for (auto reason_code: reason_codes)
0294 s << basic::byte_(reason_code);
0295
0296 return s;
0297 }
0298
0299 inline std::string encode_unsubscribe(
0300 uint16_t packet_id,
0301 const std::vector<std::string>& topics,
0302 const unsubscribe_props& props
0303 ) {
0304
0305 auto packet_type_ =
0306 basic::flag<4>(0b1010) |
0307 basic::flag<4>(0b0010);
0308
0309 size_t payload_size = 0;
0310 for (const auto& topic: topics)
0311 payload_size += basic::utf8_(topic).byte_size();
0312
0313 auto var_header_ =
0314 basic::int16_(packet_id) &
0315 prop::props_(props);
0316
0317 auto message_ =
0318 packet_type_ &
0319 basic::varlen_(var_header_.byte_size() + payload_size) &
0320 var_header_;
0321
0322 auto s = encode(message_);
0323 s.reserve(s.size() + payload_size);
0324
0325 for (const auto& topic: topics)
0326 s << basic::utf8_(topic);
0327
0328 return s;
0329 }
0330
0331 inline std::string encode_unsuback(
0332 uint16_t packet_id,
0333 const std::vector<uint8_t>& reason_codes,
0334 const unsuback_props& props
0335 ) {
0336
0337 auto packet_type_ =
0338 basic::flag<4>(0b1011) |
0339 basic::flag<4>(0b0000);
0340
0341 auto var_header_ =
0342 basic::int16_(packet_id) &
0343 prop::props_(props);
0344
0345 auto message_ =
0346 packet_type_ &
0347 basic::varlen_(var_header_.byte_size() + reason_codes.size()) &
0348 var_header_;
0349
0350 auto s = encode(message_);
0351 s.reserve(s.size() + reason_codes.size());
0352
0353 for (auto reason_code: reason_codes)
0354 s << basic::byte_(reason_code);
0355
0356 return s;
0357 }
0358
0359 inline std::string encode_pingreq() {
0360 auto packet_type_ =
0361 basic::flag<4>(0b1100) |
0362 basic::flag<4>(0);
0363
0364 auto remaining_len_ =
0365 basic::byte_(uint8_t(0));
0366
0367 auto ping_req_ = packet_type_ & remaining_len_;
0368
0369 return encode(ping_req_);
0370 }
0371
0372 inline std::string encode_pingresp() {
0373 auto packet_type_ =
0374 basic::flag<4>(0b1101) |
0375 basic::flag<4>(0);
0376
0377 auto remaining_len_ =
0378 basic::byte_(uint8_t(0));
0379
0380 auto ping_resp_ = packet_type_ & remaining_len_;
0381
0382 return encode(ping_resp_);
0383 }
0384
0385 inline std::string encode_disconnect(
0386 uint8_t reason_code,
0387 const disconnect_props& props
0388 ) {
0389
0390 auto packet_type_ =
0391 basic::flag<4>(0b1110) |
0392 basic::flag<4>(0b0000);
0393
0394 auto var_header_ =
0395 basic::byte_(reason_code) &
0396 prop::props_(props);
0397
0398 auto fixed_header_ =
0399 packet_type_ &
0400 basic::varlen_(var_header_.byte_size());
0401
0402 auto disconnect_message_ = fixed_header_ & var_header_;
0403
0404 return encode(disconnect_message_);
0405 }
0406
0407 inline std::string encode_auth(
0408 uint8_t reason_code,
0409 const auth_props& props
0410 ) {
0411
0412 auto packet_type_ =
0413 basic::flag<4>(0b1111) |
0414 basic::flag<4>(0b0000);
0415
0416 auto var_header_ =
0417 basic::byte_(reason_code) &
0418 prop::props_(props);
0419
0420 auto fixed_header_ =
0421 packet_type_ &
0422 basic::varlen_(var_header_.byte_size());
0423
0424 auto auth_message_ = fixed_header_ & var_header_;
0425
0426 return encode(auth_message_);
0427 }
0428
0429
0430 }
0431
0432 #endif