| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939 | 
							- // Copyright Takatoshi Kondo 2018
 
- //
 
- // Distributed under the Boost Software License, Version 1.0.
 
- // (See accompanying file LICENSE_1_0.txt or copy at
 
- // http://www.boost.org/LICENSE_1_0.txt)
 
- #if !defined(MQTT_V5_MESSAGE_HPP)
 
- #define MQTT_V5_MESSAGE_HPP
 
- #include <string>
 
- #include <vector>
 
- #include <memory>
 
- #include <algorithm>
 
- #include <numeric>
 
- #include <boost/asio/buffer.hpp>
 
- #include <boost/container/static_vector.hpp>
 
- #include <boost/numeric/conversion/cast.hpp>
 
- #include <mqtt/namespace.hpp>
 
- #include <mqtt/two_byte_util.hpp>
 
- #include <mqtt/fixed_header.hpp>
 
- #include <mqtt/remaining_length.hpp>
 
- #include <mqtt/subscribe_options.hpp>
 
- #include <mqtt/const_buffer_util.hpp>
 
- #include <mqtt/will.hpp>
 
- #include <mqtt/connect_flags.hpp>
 
- #include <mqtt/publish.hpp>
 
- #include <mqtt/exception.hpp>
 
- #include <mqtt/utf8encoded_strings.hpp>
 
- #include <mqtt/string_check.hpp>
 
- #include <mqtt/property.hpp>
 
- #include <mqtt/property_variant.hpp>
 
- #include <mqtt/property_parse.hpp>
 
- #include <mqtt/reason_code.hpp>
 
- #include <mqtt/packet_id_type.hpp>
 
- #include <mqtt/move.hpp>
 
- #include <mqtt/variant_visit.hpp>
 
- #include <mqtt/optional.hpp>
 
- #if !defined(MQTT_ALWAYS_SEND_REASON_CODE)
 
- #define MQTT_ALWAYS_SEND_REASON_CODE false
 
- #endif // !defined(MQTT_ALWAYS_SEND_REASON_CODE)
 
- namespace MQTT_NS {
 
- namespace as = boost::asio;
 
- namespace v5 {
 
- namespace detail {
 
- class header_only_message {
 
- public:
 
-     /**
 
-      * @brief Create empty header_packet_id_message.
 
-      */
 
-     header_only_message(control_packet_type type, std::uint8_t flags)
 
-         : message_ { static_cast<char>(make_fixed_header(type, flags)), 0 }
 
-     {}
 
-     /**
 
-      * @brief Create const buffer sequence
 
-      *        it is for boost asio APIs
 
-      * @return const buffer sequence
 
-      */
 
-     std::vector<as::const_buffer> const_buffer_sequence() const {
 
-         return { as::buffer(message_.data(), message_.size()) };
 
-     }
 
-     /**
 
-      * @brief Get whole size of sequence
 
-      * @return whole size
 
-      */
 
-     std::size_t size() const {
 
-         return message_.size();
 
-     }
 
-     /**
 
-      * @brief Get number of element of const_buffer_sequence
 
-      * @return number of element of const_buffer_sequence
 
-      */
 
-     static constexpr std::size_t num_of_const_buffer_sequence() {
 
-         return 1;
 
-     }
 
-     /**
 
-      * @brief Create one continuours buffer.
 
-      *        All sequence of buffers are concatinated.
 
-      *        It is useful to store to file/database.
 
-      * @return continuous buffer
 
-      */
 
-     std::string continuous_buffer() const {
 
-         return std::string(message_.data(), message_.size());
 
-     }
 
- private:
 
-     boost::container::static_vector<char, 2> message_;
 
- };
 
- } // namespace detail
 
- class connect_message {
 
- public:
 
-     connect_message(
 
-         std::uint16_t keep_alive_sec,
 
-         buffer client_id,
 
-         bool clean_start,
 
-         optional<will> w,
 
-         optional<buffer> user_name,
 
-         optional<buffer> password,
 
-         properties props
 
-     )
 
-         : fixed_header_(make_fixed_header(control_packet_type::connect, 0b0000)),
 
-           connect_flags_(0),
 
-           // protocol name length, protocol name, protocol level, connect flag, client id length, client id, keep alive
 
-           remaining_length_(
 
-               2 +                     // protocol name length
 
-               4 +                     // protocol name
 
-               1 +                     // protocol level
 
-               1 +                     // connect flag
 
-               2 +                     // keep alive
 
-               2 +                     // client id length
 
-               client_id.size()        // client id
 
-           ),
 
-           protocol_name_and_level_ { 0x00, 0x04, 'M', 'Q', 'T', 'T', 0x05 },
 
-           client_id_(force_move(client_id)),
 
-           client_id_length_buf_{ num_to_2bytes(boost::numeric_cast<std::uint16_t>(client_id_.size())) },
 
-           will_property_length_(
 
-               w ?
 
-               std::accumulate(
 
-                   w.value().props().begin(),
 
-                   w.value().props().end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::size(pv);
 
-                   }
 
-               )
 
-               : 0U
 
-           ),
 
-           will_props_(
 
-               w ?
 
-               force_move(w.value().props())
 
-               : properties()
 
-           ),
 
-           keep_alive_buf_ ({ num_to_2bytes(keep_alive_sec ) }),
 
-           property_length_(
 
-               std::accumulate(
 
-                   props.begin(),
 
-                   props.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::size(pv);
 
-                   }
 
-               )
 
-           ),
 
-           props_(force_move(props)),
 
-           num_of_const_buffer_sequence_(
 
-               1 +                   // fixed header
 
-               1 +                   // remaining length
 
-               1 +                   // protocol name and level
 
-               1 +                   // connect flags
 
-               1 +                   // keep alive
 
-               1 +                   // property length
 
-               std::accumulate(
 
-                   props_.begin(),
 
-                   props_.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::num_of_const_buffer_sequence(pv);
 
-                   }
 
-               ) +
 
-               2                     // client id length, client id
 
-           )
 
-     {
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         remaining_length_ += property_length_buf_.size() + property_length_;
 
-         utf8string_check(client_id_);
 
-         if (clean_start) connect_flags_ |= connect_flags::clean_start;
 
-         if (user_name) {
 
-             utf8string_check(user_name.value());
 
-             connect_flags_ |= connect_flags::user_name_flag;
 
-             user_name_ = force_move(user_name.value());
 
-             add_uint16_t_to_buf(user_name_length_buf_, boost::numeric_cast<std::uint16_t>(user_name_.size()));
 
-             remaining_length_ += 2 + user_name_.size();
 
-             num_of_const_buffer_sequence_ += 2; // user name length, user name
 
-         }
 
-         if (password) {
 
-             connect_flags_ |= connect_flags::password_flag;
 
-             password_ = force_move(password.value());
 
-             add_uint16_t_to_buf(password_length_buf_, boost::numeric_cast<std::uint16_t>(password_.size()));
 
-             remaining_length_ += 2 + password_.size();
 
-             num_of_const_buffer_sequence_ += 2; // password length, password
 
-         }
 
-         if (w) {
 
-             connect_flags_ |= connect_flags::will_flag;
 
-             if (w.value().get_retain() == retain::yes) connect_flags_ |= connect_flags::will_retain;
 
-             connect_flags::set_will_qos(connect_flags_, w.value().get_qos());
 
-             auto wpb = variable_bytes(will_property_length_);
 
-             for (auto e : wpb) {
 
-                 will_property_length_buf_.push_back(e);
 
-             }
 
-             utf8string_check(w.value().topic());
 
-             will_topic_name_ = force_move(w.value().topic());
 
-             add_uint16_t_to_buf(
 
-                 will_topic_name_length_buf_,
 
-                 boost::numeric_cast<std::uint16_t>(will_topic_name_.size())
 
-             );
 
-             if (w.value().message().size() > 0xffffL) throw will_message_length_error();
 
-             will_message_ = force_move(w.value().message());
 
-             add_uint16_t_to_buf(
 
-                 will_message_length_buf_,
 
-                 boost::numeric_cast<std::uint16_t>(will_message_.size()));
 
-             remaining_length_ +=
 
-                 will_property_length_buf_.size() +
 
-                 will_property_length_ +
 
-                 2 + will_topic_name_.size() + 2 + will_message_.size();
 
-             num_of_const_buffer_sequence_ +=
 
-                 std::accumulate(
 
-                   will_props_.begin(),
 
-                   will_props_.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::num_of_const_buffer_sequence(pv);
 
-                   }
 
-                 ) +
 
-                 2 +                   // will topic name length, will topic name
 
-                 2;                    // will message length, will message
 
-         }
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-     }
 
-     /**
 
-      * @brief Create const buffer sequence
 
-      *        it is for boost asio APIs
 
-      * @return const buffer sequence
 
-      */
 
-     std::vector<as::const_buffer> const_buffer_sequence() const {
 
-         std::vector<as::const_buffer> ret;
 
-         ret.reserve(num_of_const_buffer_sequence());
 
-         ret.emplace_back(as::buffer(&fixed_header_, 1));
 
-         ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
 
-         ret.emplace_back(as::buffer(protocol_name_and_level_.data(), protocol_name_and_level_.size()));
 
-         ret.emplace_back(as::buffer(&connect_flags_, 1));
 
-         ret.emplace_back(as::buffer(keep_alive_buf_.data(), keep_alive_buf_.size()));
 
-         ret.emplace_back(as::buffer(property_length_buf_.data(), property_length_buf_.size()));
 
-         for (auto const& p : props_) {
 
-             v5::add_const_buffer_sequence(ret, p);
 
-         }
 
-         ret.emplace_back(as::buffer(client_id_length_buf_.data(), client_id_length_buf_.size()));
 
-         ret.emplace_back(as::buffer(client_id_));
 
-         if (connect_flags::has_will_flag(connect_flags_)) {
 
-             ret.emplace_back(as::buffer(will_property_length_buf_.data(), will_property_length_buf_.size()));
 
-             for (auto const& p : will_props_) {
 
-                 v5::add_const_buffer_sequence(ret, p);
 
-             }
 
-             ret.emplace_back(as::buffer(will_topic_name_length_buf_.data(), will_topic_name_length_buf_.size()));
 
-             ret.emplace_back(as::buffer(will_topic_name_));
 
-             ret.emplace_back(as::buffer(will_message_length_buf_.data(), will_message_length_buf_.size()));
 
-             ret.emplace_back(as::buffer(will_message_));
 
-         }
 
-         if (connect_flags::has_user_name_flag(connect_flags_)) {
 
-             ret.emplace_back(as::buffer(user_name_length_buf_.data(), user_name_length_buf_.size()));
 
-             ret.emplace_back(as::buffer(user_name_));
 
-         }
 
-         if (connect_flags::has_password_flag(connect_flags_)) {
 
-             ret.emplace_back(as::buffer(password_length_buf_.data(), password_length_buf_.size()));
 
-             ret.emplace_back(as::buffer(password_));
 
-         }
 
-         return ret;
 
-     }
 
-     /**
 
-      * @brief Get whole size of sequence
 
-      * @return whole size
 
-      */
 
-     std::size_t size() const {
 
-         return
 
-             1 +                            // fixed header
 
-             remaining_length_buf_.size() +
 
-             remaining_length_;
 
-     }
 
-     /**
 
-      * @brief Get number of element of const_buffer_sequence
 
-      * @return number of element of const_buffer_sequence
 
-      */
 
-     constexpr std::size_t num_of_const_buffer_sequence() const {
 
-         return num_of_const_buffer_sequence_;
 
-     }
 
-     /**
 
-      * @brief Create one continuours buffer.
 
-      *        All sequence of buffers are concatinated.
 
-      *        It is useful to store to file/database.
 
-      * @return continuous buffer
 
-      */
 
-     std::string continuous_buffer() const {
 
-         std::string ret;
 
-         ret.reserve(size());
 
-         ret.push_back(static_cast<char>(fixed_header_));
 
-         ret.append(remaining_length_buf_.data(), remaining_length_buf_.size());
 
-         ret.append(protocol_name_and_level_.data(), protocol_name_and_level_.size());
 
-         ret.push_back(connect_flags_);
 
-         ret.append(keep_alive_buf_.data(), keep_alive_buf_.size());
 
-         ret.append(property_length_buf_.data(), property_length_buf_.size());
 
-         auto it = ret.end();
 
-         ret.resize(ret.size() + property_length_);
 
-         auto end = ret.end();
 
-         for (auto const& p : props_) {
 
-             v5::fill(p, it, end);
 
-             it += static_cast<std::string::difference_type>(v5::size(p));
 
-         }
 
-         ret.append(client_id_length_buf_.data(), client_id_length_buf_.size());
 
-         ret.append(client_id_.data(), client_id_.size());
 
-         if (connect_flags::has_will_flag(connect_flags_)) {
 
-             ret.append(will_property_length_buf_.data(), will_property_length_buf_.size());
 
-             auto it = ret.end();
 
-             ret.resize(ret.size() + will_property_length_);
 
-             auto end = ret.end();
 
-             for (auto const& p : will_props_) {
 
-                 v5::fill(p, it, end);
 
-                 it += static_cast<std::string::difference_type>(v5::size(p));
 
-             }
 
-             ret.append(will_topic_name_length_buf_.data(), will_topic_name_length_buf_.size());
 
-             ret.append(will_topic_name_.data(), will_topic_name_.size());
 
-             ret.append(will_message_length_buf_.data(), will_message_length_buf_.size());
 
-             ret.append(will_message_.data(), will_message_.size());
 
-         }
 
-         if (connect_flags::has_user_name_flag(connect_flags_)) {
 
-             ret.append(user_name_length_buf_.data(), user_name_length_buf_.size());
 
-             ret.append(user_name_.data(), user_name_.size());
 
-         }
 
-         if (connect_flags::has_password_flag(connect_flags_)) {
 
-             ret.append(password_length_buf_.data(), password_length_buf_.size());
 
-             ret.append(password_.data(), password_.size());
 
-         }
 
-         return ret;
 
-     }
 
- private:
 
-     std::uint8_t fixed_header_;
 
-     char connect_flags_;
 
-     std::size_t remaining_length_;
 
-     boost::container::static_vector<char, 4> remaining_length_buf_;
 
-     boost::container::static_vector<char, 7> protocol_name_and_level_;
 
-     buffer client_id_;
 
-     boost::container::static_vector<char, 2> client_id_length_buf_;
 
-     std::size_t will_property_length_;
 
-     boost::container::static_vector<char, 4> will_property_length_buf_;
 
-     properties will_props_;
 
-     buffer will_topic_name_;
 
-     boost::container::static_vector<char, 2> will_topic_name_length_buf_;
 
-     buffer will_message_;
 
-     boost::container::static_vector<char, 2> will_message_length_buf_;
 
-     buffer user_name_;
 
-     boost::container::static_vector<char, 2> user_name_length_buf_;
 
-     buffer password_;
 
-     boost::container::static_vector<char, 2> password_length_buf_;
 
-     boost::container::static_vector<char, 2> keep_alive_buf_;
 
-     std::size_t property_length_;
 
-     boost::container::static_vector<char, 4> property_length_buf_;
 
-     properties props_;
 
-     std::size_t num_of_const_buffer_sequence_;
 
- };
 
- class connack_message {
 
- public:
 
-     connack_message(
 
-         bool session_present,
 
-         connect_reason_code reason_code,
 
-         properties props
 
-     )
 
-         : fixed_header_(make_fixed_header(control_packet_type::connack, 0b0000)),
 
-           remaining_length_(
 
-               1 + // connect acknowledge flags
 
-               1   // reason code
 
-           ),
 
-           connect_acknowledge_flags_(session_present ? 1 : 0),
 
-           reason_code_(reason_code),
 
-           property_length_(
 
-               std::accumulate(
 
-                   props.begin(),
 
-                   props.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::size(pv);
 
-                   }
 
-               )
 
-           ),
 
-           props_(force_move(props)),
 
-           num_of_const_buffer_sequence_(
 
-               1 +                   // fixed header
 
-               1 +                   // remaining length
 
-               1 +                   // connect acknowledge flags
 
-               1 +                   // reason code
 
-               1 +                   // property length
 
-               std::accumulate(
 
-                   props_.begin(),
 
-                   props_.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::num_of_const_buffer_sequence(pv);
 
-                   }
 
-               )
 
-           )
 
-     {
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         remaining_length_ += property_length_buf_.size() + property_length_;
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-     }
 
-     /**
 
-      * @brief Create const buffer sequence
 
-      *        it is for boost asio APIs
 
-      * @return const buffer sequence
 
-      */
 
-     std::vector<as::const_buffer> const_buffer_sequence() const {
 
-         std::vector<as::const_buffer> ret;
 
-         ret.reserve(num_of_const_buffer_sequence());
 
-         ret.emplace_back(as::buffer(&fixed_header_, 1));
 
-         ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
 
-         ret.emplace_back(as::buffer(&connect_acknowledge_flags_, 1));
 
-         ret.emplace_back(as::buffer(&reason_code_, 1));
 
-         ret.emplace_back(as::buffer(property_length_buf_.data(), property_length_buf_.size()));
 
-         for (auto const& p : props_) {
 
-             v5::add_const_buffer_sequence(ret, p);
 
-         }
 
-         return ret;
 
-     }
 
-     /**
 
-      * @brief Get whole size of sequence
 
-      * @return whole size
 
-      */
 
-     std::size_t size() const {
 
-         return
 
-             1 +                            // fixed header
 
-             remaining_length_buf_.size() +
 
-             remaining_length_;
 
-     }
 
-     /**
 
-      * @brief Get number of element of const_buffer_sequence
 
-      * @return number of element of const_buffer_sequence
 
-      */
 
-     constexpr std::size_t num_of_const_buffer_sequence() const {
 
-         return num_of_const_buffer_sequence_;
 
-     }
 
-     /**
 
-      * @brief Create one continuours buffer.
 
-      *        All sequence of buffers are concatinated.
 
-      *        It is useful to store to file/database.
 
-      * @return continuous buffer
 
-      */
 
-     std::string continuous_buffer() const {
 
-         std::string ret;
 
-         ret.reserve(size());
 
-         ret.push_back(static_cast<char>(fixed_header_));
 
-         ret.append(remaining_length_buf_.data(), remaining_length_buf_.size());
 
-         ret.push_back(static_cast<char>(connect_acknowledge_flags_));
 
-         ret.push_back(static_cast<char>(reason_code_));
 
-         auto it = ret.end();
 
-         ret.resize(ret.size() + property_length_);
 
-         auto end = ret.end();
 
-         for (auto const& p : props_) {
 
-             v5::fill(p, it, end);
 
-             it += static_cast<std::string::difference_type>(v5::size(p));
 
-         }
 
-         return ret;
 
-     }
 
- private:
 
-     std::uint8_t fixed_header_;
 
-     std::size_t remaining_length_;
 
-     boost::container::static_vector<char, 4> remaining_length_buf_;
 
-     std::uint8_t connect_acknowledge_flags_;
 
-     connect_reason_code reason_code_;
 
-     std::size_t property_length_;
 
-     boost::container::static_vector<char, 4> property_length_buf_;
 
-     properties props_;
 
-     std::size_t num_of_const_buffer_sequence_;
 
- };
 
- template <std::size_t PacketIdBytes>
 
- class basic_publish_message {
 
- public:
 
-     template <
 
-         typename ConstBufferSequence,
 
-         typename std::enable_if<
 
-             as::is_const_buffer_sequence<ConstBufferSequence>::value,
 
-             std::nullptr_t
 
-         >::type = nullptr
 
-     >
 
-     basic_publish_message(
 
-         typename packet_id_type<PacketIdBytes>::type packet_id,
 
-         as::const_buffer topic_name,
 
-         ConstBufferSequence payloads,
 
-         publish_options pubopts,
 
-         properties props
 
-     )
 
-         : fixed_header_(make_fixed_header(control_packet_type::publish, 0b0000) | pubopts.operator std::uint8_t()),
 
-           topic_name_(topic_name),
 
-           topic_name_length_buf_ { num_to_2bytes(boost::numeric_cast<std::uint16_t>(topic_name_.size())) },
 
-           property_length_(
 
-               std::accumulate(
 
-                   props.begin(),
 
-                   props.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::size(pv);
 
-                   }
 
-               )
 
-           ),
 
-           props_(force_move(props)),
 
-           remaining_length_(
 
-               2                      // topic name length
 
-               + topic_name_.size()   // topic name
 
-               + (  (pubopts.get_qos() == qos::at_least_once || pubopts.get_qos() == qos::exactly_once)
 
-                  ? PacketIdBytes // packet_id
 
-                  : 0)
 
-           ),
 
-           num_of_const_buffer_sequence_(
 
-               1 +                   // fixed header
 
-               1 +                   // remaining length
 
-               1 +                   // topic name length
 
-               1 +                   // topic name
 
-               ((pubopts.get_qos() == qos::at_most_once) ? 0U : 1U) + // packet id
 
-               1 +                   // property length
 
-               std::accumulate(
 
-                   props_.begin(),
 
-                   props_.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::num_of_const_buffer_sequence(pv);
 
-                   }
 
-               )
 
-           )
 
-     {
 
-         auto b = as::buffer_sequence_begin(payloads);
 
-         auto e = as::buffer_sequence_end(payloads);
 
-         auto num_of_payloads = static_cast<std::size_t>(std::distance(b, e));
 
-         payloads_.reserve(num_of_payloads);
 
-         for (; b != e; ++b) {
 
-             auto const& payload = *b;
 
-             remaining_length_ += payload.size();
 
-             payloads_.push_back(payload);
 
-         }
 
-         num_of_const_buffer_sequence_ += num_of_payloads;
 
-         utf8string_check(topic_name_);
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         remaining_length_ += property_length_buf_.size() + property_length_;
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-         if (pubopts.get_qos() == qos::at_least_once ||
 
-             pubopts.get_qos() == qos::exactly_once) {
 
-             packet_id_.reserve(PacketIdBytes);
 
-             add_packet_id_to_buf<PacketIdBytes>::apply(packet_id_, packet_id);
 
-         }
 
-     }
 
-     basic_publish_message(buffer buf) {
 
-         if (buf.empty())  throw remaining_length_error();
 
-         fixed_header_ = static_cast<std::uint8_t>(buf.front());
 
-         qos qos_value = get_qos();
 
-         buf.remove_prefix(1);
 
-         if (buf.empty()) throw remaining_length_error();
 
-         auto len_consumed = remaining_length(buf.begin(), buf.end());
 
-         remaining_length_ = std::get<0>(len_consumed);
 
-         auto consumed = std::get<1>(len_consumed);
 
-         std::copy(
 
-             buf.begin(),
 
-             std::next(buf.begin(), static_cast<buffer::difference_type>(consumed)),
 
-             std::back_inserter(remaining_length_buf_));
 
-         buf.remove_prefix(consumed);
 
-         if (buf.size() < 2) throw remaining_length_error();
 
-         std::copy(buf.begin(), std::next(buf.begin(), 2), std::back_inserter(topic_name_length_buf_));
 
-         auto topic_name_length = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
 
-         buf.remove_prefix(2);
 
-         if (buf.size() < topic_name_length) throw remaining_length_error();
 
-         topic_name_ = as::buffer(buf.substr(0, topic_name_length));
 
-         utf8string_check(topic_name_);
 
-         buf.remove_prefix(topic_name_length);
 
-         switch (qos_value) {
 
-         case qos::at_most_once:
 
-             break;
 
-         case qos::at_least_once:
 
-         case qos::exactly_once:
 
-             if (buf.size() < PacketIdBytes) throw remaining_length_error();
 
-             std::copy(buf.begin(), std::next(buf.begin(), PacketIdBytes), std::back_inserter(packet_id_));
 
-             buf.remove_prefix(PacketIdBytes);
 
-             break;
 
-         default:
 
-             throw protocol_error();
 
-             break;
 
-         };
 
-         auto len_consume = variable_length(
 
-             buf.begin(),
 
-             buf.end()
 
-         );
 
-         property_length_ = std::get<0>(len_consume);
 
-         auto consume = std::get<1>(len_consume);
 
-         if (consume == 0) throw property_length_error();
 
-         std::copy(
 
-             buf.begin(),
 
-             std::next(buf.begin(), static_cast<buffer::difference_type>(consume)),
 
-             std::back_inserter(property_length_buf_)
 
-         );
 
-         buf.remove_prefix(consume);
 
-         if (buf.size() < property_length_) throw property_length_error();
 
-         props_ = property::parse(buf.substr(0, property_length_));
 
-         buf.remove_prefix(property_length_);
 
-         if (!buf.empty()) {
 
-             payloads_.emplace_back(as::buffer(buf));
 
-         }
 
-         num_of_const_buffer_sequence_ =
 
-             1 +                   // fixed header
 
-             1 +                   // remaining length
 
-             1 +                   // topic name length
 
-             1 +                   // topic name
 
-             ((qos_value == qos::at_most_once) ? 0U : 1U) + // packet id
 
-             1 +                   // property length
 
-             std::accumulate(
 
-                 props_.begin(),
 
-                 props_.end(),
 
-                 std::size_t(0U),
 
-                 [](std::size_t total, property_variant const& pv) {
 
-                     return total + v5::num_of_const_buffer_sequence(pv);
 
-                 }
 
-             ) +
 
-             payloads_.size();     // payload
 
-     }
 
-     /**
 
-      * @brief Create const buffer sequence
 
-      *        it is for boost asio APIs
 
-      * @return const buffer sequence
 
-      */
 
-     std::vector<as::const_buffer> const_buffer_sequence() const {
 
-         std::vector<as::const_buffer> ret;
 
-         ret.reserve(num_of_const_buffer_sequence());
 
-         ret.emplace_back(as::buffer(&fixed_header_, 1));
 
-         ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
 
-         ret.emplace_back(topic_name_length_buf_.data(), topic_name_length_buf_.size());
 
-         ret.emplace_back(as::buffer(topic_name_));
 
-         if (!packet_id_.empty()) {
 
-             ret.emplace_back(as::buffer(packet_id_.data(), packet_id_.size()));
 
-         }
 
-         ret.emplace_back(as::buffer(property_length_buf_.data(), property_length_buf_.size()));
 
-         for (auto const& p : props_) {
 
-             v5::add_const_buffer_sequence(ret, p);
 
-         }
 
-         std::copy(payloads_.begin(), payloads_.end(), std::back_inserter(ret));
 
-         return ret;
 
-     }
 
-     /**
 
-      * @brief Get whole size of sequence
 
-      * @return whole size
 
-      */
 
-     std::size_t size() const {
 
-         return
 
-             1 +                            // fixed header
 
-             remaining_length_buf_.size() +
 
-             remaining_length_;
 
-     }
 
-     /**
 
-      * @brief Get number of element of const_buffer_sequence
 
-      * @return number of element of const_buffer_sequence
 
-      */
 
-     constexpr std::size_t num_of_const_buffer_sequence() const {
 
-         return num_of_const_buffer_sequence_;
 
-     }
 
-     /**
 
-      * @brief Create one continuours buffer.
 
-      *        All sequence of buffers are concatinated.
 
-      *        It is useful to store to file/database.
 
-      * @return continuous buffer
 
-      */
 
-     std::string continuous_buffer() const {
 
-         std::string ret;
 
-         ret.reserve(size());
 
-         ret.push_back(static_cast<char>(fixed_header_));
 
-         ret.append(remaining_length_buf_.data(), remaining_length_buf_.size());
 
-         ret.append(topic_name_length_buf_.data(), topic_name_length_buf_.size());
 
-         ret.append(get_pointer(topic_name_), get_size(topic_name_));
 
-         ret.append(packet_id_.data(), packet_id_.size());
 
-         ret.append(property_length_buf_.data(), property_length_buf_.size());
 
-         auto it = ret.end();
 
-         ret.resize(ret.size() + property_length_);
 
-         auto end = ret.end();
 
-         for (auto const& p : props_) {
 
-             v5::fill(p, it, end);
 
-             it += static_cast<std::string::difference_type>(v5::size(p));
 
-         }
 
-         for (auto const& payload : payloads_) {
 
-             ret.append(get_pointer(payload), get_size(payload));
 
-         }
 
-         return ret;
 
-     }
 
-     /**
 
-      * @brief Get packet id
 
-      * @return packet_id
 
-      */
 
-     typename packet_id_type<PacketIdBytes>::type packet_id() const {
 
-         return make_packet_id<PacketIdBytes>::apply(packet_id_.begin(), packet_id_.end());
 
-     }
 
-     /**
 
-      * @brief Get publish_options
 
-      * @return publish_options.
 
-      */
 
-     constexpr publish_options get_options() const {
 
-         return publish_options(fixed_header_);
 
-     }
 
-     /**
 
-      * @brief Get qos
 
-      * @return qos
 
-      */
 
-     constexpr qos get_qos() const {
 
-         return publish::get_qos(fixed_header_);
 
-     }
 
-     /**
 
-      * @brief Check retain flag
 
-      * @return true if retain, otherwise return false.
 
-      */
 
-     constexpr bool is_retain() const {
 
-         return publish::is_retain(fixed_header_);
 
-     }
 
-     /**
 
-      * @brief Check dup flag
 
-      * @return true if dup, otherwise return false.
 
-      */
 
-     constexpr bool is_dup() const {
 
-         return publish::is_dup(fixed_header_);
 
-     }
 
-     /**
 
-      * @brief Get topic name
 
-      * @return topic name
 
-      */
 
-     string_view topic() const {
 
-         return string_view(get_pointer(topic_name_), get_size(topic_name_));
 
-     }
 
-     /**
 
-      * @brief Get payload
 
-      * @return payload
 
-      */
 
-     std::vector<string_view> payload() const {
 
-         std::vector<string_view> ret;
 
-         ret.reserve(payloads_.size());
 
-         for (auto const& payload : payloads_) {
 
-             ret.emplace_back(get_pointer(payload), get_size(payload));
 
-         }
 
-         return ret;
 
-     }
 
-     /**
 
-      * @brief Get payload as single buffer
 
-      * @return payload
 
-      */
 
-     buffer payload_as_buffer() const {
 
-         auto size = std::accumulate(
 
-             payloads_.begin(),
 
-             payloads_.end(),
 
-             std::size_t(0),
 
-             [](std::size_t s, as::const_buffer const& payload) {
 
-                 return s += payload.size();
 
-             }
 
-         );
 
-         if (size == 0) return buffer();
 
-         auto spa = make_shared_ptr_array(size);
 
-         auto ptr = spa.get();
 
-         auto it = ptr;
 
-         for (auto const& payload : payloads_) {
 
-             auto b = get_pointer(payload);
 
-             auto s = get_size(payload);
 
-             auto e = b + s;
 
-             std::copy(b, e, it);
 
-             it += s;
 
-         }
 
-         return buffer(string_view(ptr, size), force_move(spa));
 
-     }
 
-     /**
 
-      * @brief Get properties
 
-      * @return properties
 
-      */
 
-     properties const& props() const {
 
-         return props_;
 
-     }
 
-     /**
 
-      * @brief Add property
 
-      * @param p property to add
 
-      */
 
-     void add_prop(property_variant p) {
 
-         auto add_size = v5::size(p);
 
-         props_.push_back(force_move(p));
 
-         property_length_ += add_size;
 
-         property_length_buf_.clear();
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         remaining_length_buf_.clear();
 
-         remaining_length_ += add_size;
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-     }
 
-     /**
 
-      * @brief Update property
 
-      *        Only fixed size property can be updated.
 
-      * @param p property to update
 
-      */
 
-     template <typename Property>
 
-     std::enable_if_t<
 
-         std::is_base_of<property::detail::n_bytes_property<1>, Property>::value ||
 
-         std::is_base_of<property::detail::n_bytes_property<2>, Property>::value ||
 
-         std::is_base_of<property::detail::n_bytes_property<4>, Property>::value
 
-     >
 
-     update_prop(Property update_prop) {
 
-         for (auto& p : props_) {
 
-             MQTT_NS::visit(
 
-                 make_lambda_visitor(
 
-                     [&update_prop](Property& t) { t = std::forward<Property>(update_prop); },
 
-                     [](auto&) { }
 
-                 ),
 
-                 p
 
-             );
 
-         }
 
-     }
 
-     /**
 
-      * @brief Remove property
 
-      * @param id property::id to remove
 
-      */
 
-     void remove_prop(v5::property::id id) {
 
-         std::size_t removed_size = 0;
 
-         auto it = props_.begin();
 
-         auto end = props_.begin();
 
-         while (it != end) {
 
-             if (v5::id(*it) == id) {
 
-                 removed_size += v5::size(*it);
 
-                 it = props_.erase(it);
 
-             }
 
-             else {
 
-                 ++it;
 
-             }
 
-         }
 
-         property_length_ -= removed_size;
 
-         property_length_buf_.clear();
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         remaining_length_buf_.clear();
 
-         remaining_length_ -= removed_size;
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-     }
 
-     /**
 
-      * @brief Set dup flag
 
-      * @param dup flag value to set
 
-      */
 
-     constexpr void set_dup(bool dup) {
 
-         publish::set_dup(fixed_header_, dup);
 
-     }
 
-     /**
 
-      * @brief Set topic name
 
-      * @param topic_name value to set
 
-      */
 
-     void set_topic_name(as::const_buffer topic_name) {
 
-         auto prev_topic_name_size = get_size(topic_name_);
 
-         topic_name_ = force_move(topic_name);
 
-         topic_name_length_buf_ = boost::container::static_vector<char, 2>{
 
-             num_to_2bytes(boost::numeric_cast<std::uint16_t>(get_size(topic_name_)))
 
-         };
 
-         remaining_length_buf_.clear();
 
-         remaining_length_ =  remaining_length_ - prev_topic_name_size + get_size(topic_name_);
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-     }
 
- private:
 
-     std::uint8_t fixed_header_;
 
-     as::const_buffer topic_name_;
 
-     boost::container::static_vector<char, 2> topic_name_length_buf_;
 
-     boost::container::static_vector<char, PacketIdBytes> packet_id_;
 
-     std::size_t property_length_;
 
-     boost::container::static_vector<char, 4> property_length_buf_;
 
-     properties props_;
 
-     std::vector<as::const_buffer> payloads_;
 
-     std::size_t remaining_length_;
 
-     boost::container::static_vector<char, 4> remaining_length_buf_;
 
-     std::size_t num_of_const_buffer_sequence_;
 
- };
 
- using publish_message = basic_publish_message<2>;
 
- using publish_32_message = basic_publish_message<4>;
 
- template <std::size_t PacketIdBytes>
 
- struct basic_puback_message {
 
-     basic_puback_message(
 
-         typename packet_id_type<PacketIdBytes>::type packet_id,
 
-         v5::puback_reason_code reason_code,
 
-         properties props)
 
-         : fixed_header_(make_fixed_header(control_packet_type::puback, 0b0000)),
 
-           reason_code_(reason_code),
 
-           property_length_(
 
-               std::accumulate(
 
-                   props.begin(),
 
-                   props.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::size(pv);
 
-                   }
 
-               )
 
-           ),
 
-           props_(force_move(props)),
 
-           num_of_const_buffer_sequence_(
 
-               1 +                   // fixed header
 
-               1 +                   // remaining length
 
-               1 +                   // packet id
 
-               // TODO: This is wrong. The reason code MUST be provided
 
-               // if there are properties. Not the other way around.
 
-               // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901124
 
-               // 3.4.2.1 PUBACK Reason Code
 
-               // The Reason Code and Property Length can be omitted if
 
-               // the Reason Code is 0x00 (Success) and there are no Properties.
 
-               // In this case the PUBACK has a Remaining Length of 2.
 
-               [&] () -> std::size_t {
 
-                   if ((reason_code_ != v5::puback_reason_code::success) || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-                       // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901126
 
-                       // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-                       if (props_.empty()) {
 
-                           return 1;                 // reason code
 
-                       }
 
-                       else {
 
-                           return
 
-                               1 +                   // reason code
 
-                               1 +                   // property length
 
-                               std::accumulate(      // properties
 
-                                   props_.begin(),
 
-                                   props_.end(),
 
-                                   std::size_t(0U),
 
-                                   [](std::size_t total, property_variant const& pv) {
 
-                                       return total + v5::num_of_const_buffer_sequence(pv);
 
-                                   }
 
-                               );
 
-                       }
 
-                   }
 
-                   else {
 
-                       return 0;
 
-                   }
 
-               } ()
 
-           )
 
-     {
 
-         add_packet_id_to_buf<PacketIdBytes>::apply(packet_id_, packet_id);
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         remaining_length_ =
 
-             PacketIdBytes +       // packet id
 
-             // TODO: This is wrong. The reason code MUST be provided
 
-             // if there are properties. Not the other way around.
 
-             // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901124
 
-             // 3.4.2.1 PUBACK Reason Code
 
-             // The Reason Code and Property Length can be omitted if
 
-             // the Reason Code is 0x00 (Success) and there are no Properties.
 
-             // In this case the PUBACK has a Remaining Length of 2.
 
-             [&] () -> std::size_t {
 
-                 if ((reason_code_ != v5::puback_reason_code::success) || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-                     // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901126
 
-                     // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-                     if (props_.empty()) {
 
-                         return 1;                 // reason code
 
-                     }
 
-                     else {
 
-                         return
 
-                             1 +                   // reason code
 
-                             property_length_buf_.size() +
 
-                             property_length_;
 
-                     }
 
-                 }
 
-                 else {
 
-                     return 0;
 
-                 }
 
-             } ();
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-     }
 
-     /**
 
-      * @brief Create const buffer sequence
 
-      *        it is for boost asio APIs
 
-      * @return const buffer sequence
 
-      */
 
-     std::vector<as::const_buffer> const_buffer_sequence() const {
 
-         std::vector<as::const_buffer> ret;
 
-         ret.reserve(num_of_const_buffer_sequence());
 
-         ret.emplace_back(as::buffer(&fixed_header_, 1));
 
-         ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
 
-         ret.emplace_back(as::buffer(packet_id_.data(), packet_id_.size()));
 
-         // TODO: This is wrong. The reason code MUST be provided
 
-         // if there are properties. Not the other way around.
 
-         // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901124
 
-         // 3.4.2.1 PUBACK Reason Code
 
-         // The Reason Code and Property Length can be omitted if
 
-         // the Reason Code is 0x00 (Success) and there are no Properties.
 
-         // In this case the PUBACK has a Remaining Length of 2.
 
-         if (reason_code_ != v5::puback_reason_code::success || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-             ret.emplace_back(as::buffer(&reason_code_, 1));
 
-             // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901126
 
-             // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-             if (!props_.empty()) {
 
-                 ret.emplace_back(as::buffer(property_length_buf_.data(), property_length_buf_.size()));
 
-                 for (auto const& p : props_) {
 
-                     v5::add_const_buffer_sequence(ret, p);
 
-                 }
 
-             }
 
-         }
 
-         return ret;
 
-     }
 
-     /**
 
-      * @brief Get whole size of sequence
 
-      * @return whole size
 
-      */
 
-     std::size_t size() const {
 
-         return
 
-             1 +                            // fixed header
 
-             remaining_length_buf_.size() +
 
-             remaining_length_;
 
-     }
 
-     /**
 
-      * @brief Get number of element of const_buffer_sequence
 
-      * @return number of element of const_buffer_sequence
 
-      */
 
-     constexpr std::size_t num_of_const_buffer_sequence() const {
 
-         return num_of_const_buffer_sequence_;
 
-     }
 
-     /**
 
-      * @brief Create one continuours buffer.
 
-      *        All sequence of buffers are concatinated.
 
-      *        It is useful to store to file/database.
 
-      * @return continuous buffer
 
-      */
 
-     std::string continuous_buffer() const {
 
-         std::string ret;
 
-         auto sz = size();
 
-         ret.reserve(sz);
 
-         ret.push_back(static_cast<char>(fixed_header_));
 
-         ret.append(remaining_length_buf_.data(), remaining_length_buf_.size());
 
-         // TODO: This is wrong. The reason code MUST be provided
 
-         // if there are properties. Not the other way around.
 
-         // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901124
 
-         // 3.4.2.1 PUBACK Reason Code
 
-         // The Reason Code and Property Length can be omitted if
 
-         // the Reason Code is 0x00 (Success) and there are no Properties.
 
-         // In this case the PUBACK has a Remaining Length of 2.
 
-         if (reason_code_ != v5::puback_reason_code::success || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-             ret.push_back(static_cast<char>(reason_code_));
 
-             // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901126
 
-             // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-             if (!props_.empty()) {
 
-                 ret.append(property_length_buf_.data(), property_length_buf_.size());
 
-                 auto it = ret.end();
 
-                 ret.resize(sz);
 
-                 auto end = ret.end();
 
-                 for (auto const& p : props_) {
 
-                     v5::fill(p, it, end);
 
-                     it += static_cast<std::string::difference_type>(v5::size(p));
 
-                 }
 
-             }
 
-         }
 
-         return ret;
 
-     }
 
-     std::uint8_t fixed_header_;
 
-     std::size_t remaining_length_;
 
-     boost::container::static_vector<char, 4> remaining_length_buf_;
 
-     boost::container::static_vector<char, PacketIdBytes> packet_id_;
 
-     v5::puback_reason_code reason_code_;
 
-     std::size_t property_length_;
 
-     boost::container::static_vector<char, 4> property_length_buf_;
 
-     properties props_;
 
-     std::size_t num_of_const_buffer_sequence_;
 
- };
 
- using puback_message = basic_puback_message<2>;
 
- template <std::size_t PacketIdBytes>
 
- struct basic_pubrec_message {
 
-     basic_pubrec_message(
 
-         typename packet_id_type<PacketIdBytes>::type packet_id,
 
-         pubrec_reason_code reason_code,
 
-         properties props)
 
-         : fixed_header_(make_fixed_header(control_packet_type::pubrec, 0b0000)),
 
-           reason_code_(reason_code),
 
-           property_length_(
 
-               std::accumulate(
 
-                   props.begin(),
 
-                   props.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::size(pv);
 
-                   }
 
-               )
 
-           ),
 
-           props_(force_move(props)),
 
-           num_of_const_buffer_sequence_(
 
-               1 +                   // fixed header
 
-               1 +                   // remaining length
 
-               1 +                   // packet id
 
-               // TODO: This is wrong. The reason code MUST be provided
 
-               // if there are properties. Not the other way around.
 
-               // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901134
 
-               // 3.5.2.1 PUBREC Reason Code
 
-               // The Reason Code and Property Length can be omitted if
 
-               // the Reason Code is 0x00 (Success) and there are no Properties.
 
-               // In this case the PUBREC has a Remaining Length of 2.
 
-               [&] () -> std::size_t {
 
-                   if ((reason_code_ != v5::pubrec_reason_code::success) || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-                       // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901136
 
-                       // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-                       if (props_.empty()) {
 
-                           return 1;                 // reason code
 
-                       }
 
-                       else {
 
-                           return
 
-                               1 +                   // reason code
 
-                               1 +                   // property length
 
-                               std::accumulate(      // properties
 
-                                   props_.begin(),
 
-                                   props_.end(),
 
-                                   std::size_t(0U),
 
-                                   [](std::size_t total, property_variant const& pv) {
 
-                                       return total + v5::num_of_const_buffer_sequence(pv);
 
-                                   }
 
-                               );
 
-                       }
 
-                   }
 
-                   else {
 
-                       return 0;
 
-                   }
 
-               } ()
 
-           )
 
-     {
 
-         add_packet_id_to_buf<PacketIdBytes>::apply(packet_id_, packet_id);
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         remaining_length_ =
 
-             PacketIdBytes +       // packet id
 
-             // TODO: This is wrong. The reason code MUST be provided
 
-             // if there are properties. Not the other way around.
 
-             // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901134
 
-             // 3.5.2.1 PUBREC Reason Code
 
-             // The Reason Code and Property Length can be omitted if
 
-             // the Reason Code is 0x00 (Success) and there are no Properties.
 
-             // In this case the PUBREC has a Remaining Length of 2.
 
-             [&] () -> std::size_t {
 
-                 if ((reason_code_ != v5::pubrec_reason_code::success) || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-                     // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901136
 
-                     // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-                     if (props_.empty()) {
 
-                         return 1;                 // reason code
 
-                     }
 
-                     else {
 
-                         return
 
-                             1 +                   // reason code
 
-                             property_length_buf_.size() +
 
-                             property_length_;
 
-                     }
 
-                 }
 
-                 else {
 
-                     return 0;
 
-                 }
 
-             } ();
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-     }
 
-     /**
 
-      * @brief Create const buffer sequence
 
-      *        it is for boost asio APIs
 
-      * @return const buffer sequence
 
-      */
 
-     std::vector<as::const_buffer> const_buffer_sequence() const {
 
-         std::vector<as::const_buffer> ret;
 
-         ret.reserve(num_of_const_buffer_sequence());
 
-         ret.emplace_back(as::buffer(&fixed_header_, 1));
 
-         ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
 
-         ret.emplace_back(as::buffer(packet_id_.data(), packet_id_.size()));
 
-         // TODO: This is wrong. The reason code MUST be provided
 
-         // if there are properties. Not the other way around.
 
-         // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901134
 
-         // 3.5.2.1 PUBREC Reason Code
 
-         // The Reason Code and Property Length can be omitted if
 
-         // the Reason Code is 0x00 (Success) and there are no Properties.
 
-         // In this case the PUBREC has a Remaining Length of 2.
 
-         if (reason_code_ != v5::pubrec_reason_code::success || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-             ret.emplace_back(as::buffer(&reason_code_, 1));
 
-             // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901136
 
-             // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-             if (!props_.empty()) {
 
-                 ret.emplace_back(as::buffer(property_length_buf_.data(), property_length_buf_.size()));
 
-                 for (auto const& p : props_) {
 
-                     v5::add_const_buffer_sequence(ret, p);
 
-                 }
 
-             }
 
-         }
 
-         return ret;
 
-     }
 
-     /**
 
-      * @brief Get whole size of sequence
 
-      * @return whole size
 
-      */
 
-     std::size_t size() const {
 
-         return
 
-             1 +                            // fixed header
 
-             remaining_length_buf_.size() +
 
-             remaining_length_;
 
-     }
 
-     /**
 
-      * @brief Get number of element of const_buffer_sequence
 
-      * @return number of element of const_buffer_sequence
 
-      */
 
-     constexpr std::size_t num_of_const_buffer_sequence() const {
 
-         return num_of_const_buffer_sequence_;
 
-     }
 
-     /**
 
-      * @brief Create one continuours buffer.
 
-      *        All sequence of buffers are concatinated.
 
-      *        It is useful to store to file/database.
 
-      * @return continuous buffer
 
-      */
 
-     std::string continuous_buffer() const {
 
-         std::string ret;
 
-         auto sz = size();
 
-         ret.reserve(sz);
 
-         ret.push_back(static_cast<char>(fixed_header_));
 
-         ret.append(remaining_length_buf_.data(), remaining_length_buf_.size());
 
-         // TODO: This is wrong. The reason code MUST be provided
 
-         // if there are properties. Not the other way around.
 
-         // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901134
 
-         // 3.5.2.1 PUBREC Reason Code
 
-         // The Reason Code and Property Length can be omitted if
 
-         // the Reason Code is 0x00 (Success) and there are no Properties.
 
-         // In this case the PUBREC has a Remaining Length of 2.
 
-         if (reason_code_ != v5::pubrec_reason_code::success || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-             ret.push_back(static_cast<char>(reason_code_));
 
-             // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901136
 
-             // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-             if (!props_.empty()) {
 
-                 ret.append(property_length_buf_.data(), property_length_buf_.size());
 
-                 auto it = ret.end();
 
-                 ret.resize(sz);
 
-                 auto end = ret.end();
 
-                 for (auto const& p : props_) {
 
-                     v5::fill(p, it, end);
 
-                     it += static_cast<std::string::difference_type>(v5::size(p));
 
-                 }
 
-             }
 
-         }
 
-         return ret;
 
-     }
 
-     std::uint8_t fixed_header_;
 
-     std::size_t remaining_length_;
 
-     boost::container::static_vector<char, 4> remaining_length_buf_;
 
-     boost::container::static_vector<char, PacketIdBytes> packet_id_;
 
-     pubrec_reason_code reason_code_;
 
-     std::size_t property_length_;
 
-     boost::container::static_vector<char, 4> property_length_buf_;
 
-     properties props_;
 
-     std::size_t num_of_const_buffer_sequence_;
 
- };
 
- using pubrec_message = basic_pubrec_message<2>;
 
- template <std::size_t PacketIdBytes>
 
- struct basic_pubrel_message {
 
-     basic_pubrel_message(
 
-         typename packet_id_type<PacketIdBytes>::type packet_id,
 
-         v5::pubrel_reason_code reason_code,
 
-         properties props)
 
-         : fixed_header_(make_fixed_header(control_packet_type::pubrel, 0b0010)),
 
-           reason_code_(reason_code),
 
-           property_length_(
 
-               std::accumulate(
 
-                   props.begin(),
 
-                   props.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::size(pv);
 
-                   }
 
-               )
 
-           ),
 
-           props_(force_move(props)),
 
-           num_of_const_buffer_sequence_(
 
-               1 +                   // fixed header
 
-               1 +                   // remaining length
 
-               1 +                   // packet id
 
-               // TODO: This is wrong. The reason code MUST be provided
 
-               // if there are properties. Not the other way around.
 
-               // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144
 
-               // 3.6.2.1 PUBREL Reason Code
 
-               // The Reason Code and Property Length can be omitted if
 
-               // the Reason Code is 0x00 (Success) and there are no Properties.
 
-               // In this case the PUBREL has a Remaining Length of 2.
 
-               [&] () -> std::size_t {
 
-                   if ((reason_code_ != v5::pubrel_reason_code::success) || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-                       // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901146
 
-                       // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-                       if (props_.empty()) {
 
-                           return 1;                 // reason code
 
-                       }
 
-                       else {
 
-                           return
 
-                               1 +                   // reason code
 
-                               1 +                   // property length
 
-                               std::accumulate(      // properties
 
-                                   props_.begin(),
 
-                                   props_.end(),
 
-                                   std::size_t(0U),
 
-                                   [](std::size_t total, property_variant const& pv) {
 
-                                       return total + v5::num_of_const_buffer_sequence(pv);
 
-                                   }
 
-                               );
 
-                       }
 
-                   }
 
-                   else {
 
-                       return 0;
 
-                   }
 
-               } ()
 
-           )
 
-     {
 
-         add_packet_id_to_buf<PacketIdBytes>::apply(packet_id_, packet_id);
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         remaining_length_ =
 
-             PacketIdBytes +       // packet id
 
-             // TODO: This is wrong. The reason code MUST be provided
 
-             // if there are properties. Not the other way around.
 
-             // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144
 
-             // 3.6.2.1 PUBREL Reason Code
 
-             // The Reason Code and Property Length can be omitted if
 
-             // the Reason Code is 0x00 (Success) and there are no Properties.
 
-             // In this case the PUBREL has a Remaining Length of 2.
 
-             [&] () -> std::size_t {
 
-                 if ((reason_code_ != v5::pubrel_reason_code::success) || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-                     // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901146
 
-                     // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-                     if (props_.empty()) {
 
-                         return 1;                 // reason code
 
-                     }
 
-                     else {
 
-                         return
 
-                             1 +                   // reason code
 
-                             property_length_buf_.size() +
 
-                             property_length_;
 
-                     }
 
-                 }
 
-                 else {
 
-                     return 0;
 
-                 }
 
-             } ();
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-     }
 
-     basic_pubrel_message(buffer buf) {
 
-         if (buf.empty())  throw remaining_length_error();
 
-         fixed_header_ = static_cast<std::uint8_t>(buf.front());
 
-         buf.remove_prefix(1);
 
-         if (buf.empty()) throw remaining_length_error();
 
-         auto len_consumed = remaining_length(buf.begin(), buf.end());
 
-         remaining_length_ = std::get<0>(len_consumed);
 
-         auto consumed = std::get<1>(len_consumed);
 
-         std::copy(
 
-             buf.begin(),
 
-             std::next(buf.begin(), static_cast<buffer::difference_type>(consumed)),
 
-             std::back_inserter(remaining_length_buf_));
 
-         buf.remove_prefix(consumed);
 
-         if (buf.size() < PacketIdBytes) throw remaining_length_error();
 
-         std::copy(buf.begin(), std::next(buf.begin(), PacketIdBytes), std::back_inserter(packet_id_));
 
-         buf.remove_prefix(PacketIdBytes);
 
-         if (buf.empty()) {
 
-             num_of_const_buffer_sequence_ =
 
-                 1 +                   // fixed header
 
-                 1 +                   // remaining length
 
-                 1;                    // packet id
 
-             reason_code_ = v5::pubrel_reason_code::success;
 
-             return;
 
-         }
 
-         reason_code_ = static_cast<v5::pubrel_reason_code>(buf.front());
 
-         buf.remove_prefix(1);
 
-         if (buf.empty()) {
 
-             property_length_ = 0;
 
-         }
 
-         else {
 
-             auto len_consume = variable_length(
 
-                 buf.begin(),
 
-                 buf.end()
 
-             );
 
-             property_length_ = std::get<0>(len_consume);
 
-             auto consume = std::get<1>(len_consume);
 
-             if (consume == 0) throw property_length_error();
 
-             std::copy(
 
-                 buf.begin(),
 
-                 std::next(buf.begin(), static_cast<buffer::difference_type>(consume)),
 
-                 std::back_inserter(property_length_buf_)
 
-             );
 
-             buf.remove_prefix(consume);
 
-             if (buf.size() != property_length_) throw property_length_error();
 
-             props_ = property::parse(buf);
 
-             buf.remove_prefix(property_length_);
 
-         }
 
-         num_of_const_buffer_sequence_ =
 
-             1 +                   // fixed header
 
-             1 +                   // remaining length
 
-             1 +                   // packet id
 
-             // TODO: This is wrong. The reason code MUST be provided
 
-             // if there are properties. Not the other way around.
 
-             // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144
 
-             // 3.6.2.1 PUBREL Reason Code
 
-             // The Reason Code and Property Length can be omitted if
 
-             // the Reason Code is 0x00 (Success) and there are no Properties.
 
-             // In this case the PUBREL has a Remaining Length of 2.
 
-             [&] () -> std::size_t {
 
-                 if ((reason_code_ != v5::pubrel_reason_code::success) || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-                     // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901146
 
-                     // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-                     if (props_.empty()) {
 
-                         return 1;                 // reason code
 
-                     }
 
-                     else {
 
-                         return
 
-                             1 +                   // reason code
 
-                             1 +                   // property length
 
-                             std::accumulate(      // properties
 
-                                 props_.begin(),
 
-                                 props_.end(),
 
-                                 std::size_t(0U),
 
-                                 [](std::size_t total, property_variant const& pv) {
 
-                                     return total + v5::num_of_const_buffer_sequence(pv);
 
-                                 }
 
-                             );
 
-                     }
 
-                 }
 
-                 else {
 
-                     return 0;
 
-                 }
 
-             } ();
 
-     }
 
-     /**
 
-      * @brief Create const buffer sequence
 
-      *        it is for boost asio APIs
 
-      * @return const buffer sequence
 
-      */
 
-     std::vector<as::const_buffer> const_buffer_sequence() const {
 
-         std::vector<as::const_buffer> ret;
 
-         ret.reserve(num_of_const_buffer_sequence());
 
-         ret.emplace_back(as::buffer(&fixed_header_, 1));
 
-         ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
 
-         ret.emplace_back(as::buffer(packet_id_.data(), packet_id_.size()));
 
-         // TODO: This is wrong. The reason code MUST be provided
 
-         // if there are properties. Not the other way around.
 
-         // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144
 
-         // 3.6.2.1 PUBREL Reason Code
 
-         // The Reason Code and Property Length can be omitted if
 
-         // the Reason Code is 0x00 (Success) and there are no Properties.
 
-         // In this case the PUBREL has a Remaining Length of 2.
 
-         if(reason_code_ != v5::pubrel_reason_code::success || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-             ret.emplace_back(as::buffer(&reason_code_, 1));
 
-             // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901146
 
-             // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-             if (!props_.empty()) {
 
-                 ret.emplace_back(as::buffer(property_length_buf_.data(), property_length_buf_.size()));
 
-                 for (auto const& p : props_) {
 
-                     v5::add_const_buffer_sequence(ret, p);
 
-                 }
 
-             }
 
-         }
 
-         return ret;
 
-    }
 
-     /**
 
-      * @brief Get whole size of sequence
 
-      * @return whole size
 
-      */
 
-     std::size_t size() const {
 
-         return
 
-             1 +                            // fixed header
 
-             remaining_length_buf_.size() +
 
-             remaining_length_;
 
-     }
 
-     /**
 
-      * @brief Get number of element of const_buffer_sequence
 
-      * @return number of element of const_buffer_sequence
 
-      */
 
-     constexpr std::size_t num_of_const_buffer_sequence() const {
 
-         return num_of_const_buffer_sequence_;
 
-     }
 
-     /**
 
-      * @brief Create one continuours buffer.
 
-      *        All sequence of buffers are concatinated.
 
-      *        It is useful to store to file/database.
 
-      * @return continuous buffer
 
-      */
 
-     std::string continuous_buffer() const {
 
-         std::string ret;
 
-         auto sz = size();
 
-         ret.reserve(sz);
 
-         ret.push_back(static_cast<char>(fixed_header_));
 
-         ret.append(remaining_length_buf_.data(), remaining_length_buf_.size());
 
-         ret.append(packet_id_.data(), packet_id_.size());
 
-         // TODO: This is wrong. The reason code MUST be provided
 
-         // if there are properties. Not the other way around.
 
-         // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144
 
-         // 3.6.2.1 PUBREL Reason Code
 
-         // The Reason Code and Property Length can be omitted if
 
-         // the Reason Code is 0x00 (Success) and there are no Properties.
 
-         // In this case the PUBREL has a Remaining Length of 2.
 
-         if (reason_code_ != v5::pubrel_reason_code::success || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-             ret.push_back(static_cast<char>(reason_code_));
 
-             // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901146
 
-             // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-             if (!props_.empty()) {
 
-                 ret.append(property_length_buf_.data(), property_length_buf_.size());
 
-                 auto it = ret.end();
 
-                 ret.resize(sz);
 
-                 auto end = ret.end();
 
-                 for (auto const& p : props_) {
 
-                     v5::fill(p, it, end);
 
-                     it += static_cast<std::string::difference_type>(v5::size(p));
 
-                 }
 
-             }
 
-         }
 
-         return ret;
 
-     }
 
-     /**
 
-      * @brief Get packet id
 
-      * @return packet_id
 
-      */
 
-     decltype(auto) packet_id() const {
 
-         return make_packet_id<PacketIdBytes>::apply(packet_id_.begin(), packet_id_.end());
 
-     }
 
-     /**
 
-      * @brief Get reason_code
 
-      * @return reason_code
 
-      */
 
-     v5::pubrel_reason_code reason_code() const {
 
-         return reason_code_;
 
-     }
 
-     /**
 
-      * @brief Get properties
 
-      * @return properties
 
-      */
 
-     properties const& props() const {
 
-         return props_;
 
-     }
 
-     std::uint8_t fixed_header_;
 
-     std::size_t remaining_length_;
 
-     boost::container::static_vector<char, 4> remaining_length_buf_;
 
-     boost::container::static_vector<char, PacketIdBytes> packet_id_;
 
-     v5::pubrel_reason_code reason_code_;
 
-     std::size_t property_length_;
 
-     boost::container::static_vector<char, 4> property_length_buf_;
 
-     properties props_;
 
-     std::size_t num_of_const_buffer_sequence_;
 
- };
 
- using pubrel_message = basic_pubrel_message<2>;
 
- using pubrel_32_message = basic_pubrel_message<4>;
 
- template <std::size_t PacketIdBytes>
 
- struct basic_pubcomp_message {
 
-     basic_pubcomp_message(
 
-         typename packet_id_type<PacketIdBytes>::type packet_id,
 
-         pubcomp_reason_code reason_code,
 
-         properties props)
 
-         : fixed_header_(make_fixed_header(control_packet_type::pubcomp, 0b0000)),
 
-           reason_code_(reason_code),
 
-           property_length_(
 
-               std::accumulate(
 
-                   props.begin(),
 
-                   props.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::size(pv);
 
-                   }
 
-               )
 
-           ),
 
-           props_(force_move(props)),
 
-           num_of_const_buffer_sequence_(
 
-               1 +                   // fixed header
 
-               1 +                   // remaining length
 
-               1 +                   // packet id
 
-               // TODO: This is wrong. The reason code MUST be provided
 
-               // if there are properties. Not the other way around.
 
-               // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901154
 
-               // 3.7.2.1 PUBCOMP Reason Code
 
-               // The Reason Code and Property Length can be omitted if
 
-               // the Reason Code is 0x00 (Success) and there are no Properties.
 
-               // In this case the PUBCOMP has a Remaining Length of 2.
 
-               [&] () -> std::size_t {
 
-                   if ((reason_code_ != v5::pubcomp_reason_code::success) || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-                       // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901156
 
-                       // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-                       if (props_.empty()) {
 
-                           return 1;                 // reason code
 
-                       }
 
-                       else {
 
-                           return
 
-                               1 +                   // reason code
 
-                               1 +                   // property length
 
-                               std::accumulate(      // properties
 
-                                   props_.begin(),
 
-                                   props_.end(),
 
-                                   std::size_t(0U),
 
-                                   [](std::size_t total, property_variant const& pv) {
 
-                                       return total + v5::num_of_const_buffer_sequence(pv);
 
-                                   }
 
-                               );
 
-                       }
 
-                   }
 
-                   else {
 
-                       return 0;
 
-                   }
 
-               } ()
 
-           )
 
-     {
 
-         add_packet_id_to_buf<PacketIdBytes>::apply(packet_id_, packet_id);
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         remaining_length_ =
 
-             PacketIdBytes +       // packet id
 
-             // TODO: This is wrong. The reason code MUST be provided
 
-             // if there are properties. Not the other way around.
 
-             // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901154
 
-             // 3.7.2.1 PUBCOMP Reason Code
 
-             // The Reason Code and Property Length can be omitted if
 
-             // the Reason Code is 0x00 (Success) and there are no Properties.
 
-             // In this case the PUBCOMP has a Remaining Length of 2.
 
-             [&] () -> std::size_t {
 
-                 if ((reason_code_ != v5::pubcomp_reason_code::success) || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-                     // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901156
 
-                     // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-                     if (props_.empty()) {
 
-                         return 1;                 // reason code
 
-                     }
 
-                     else {
 
-                         return
 
-                             1 +                   // reason code
 
-                             property_length_buf_.size() +
 
-                             property_length_;
 
-                     }
 
-                 }
 
-                 else {
 
-                     return 0;
 
-                 }
 
-             } ();
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-     }
 
-     /**
 
-      * @brief Create const buffer sequence
 
-      *        it is for boost asio APIs
 
-      * @return const buffer sequence
 
-      */
 
-     std::vector<as::const_buffer> const_buffer_sequence() const {
 
-         std::vector<as::const_buffer> ret;
 
-         ret.reserve(num_of_const_buffer_sequence());
 
-         ret.emplace_back(as::buffer(&fixed_header_, 1));
 
-         ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
 
-         ret.emplace_back(as::buffer(packet_id_.data(), packet_id_.size()));
 
-         // TODO: This is wrong. The reason code MUST be provided
 
-         // if there are properties. Not the other way around.
 
-         // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901154
 
-         // 3.7.2.1 PUBCOMP Reason Code
 
-         // The Reason Code and Property Length can be omitted if
 
-         // the Reason Code is 0x00 (Success) and there are no Properties.
 
-         // In this case the PUBCOMP has a Remaining Length of 2.
 
-         if (reason_code_ != v5::pubcomp_reason_code::success || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-             ret.emplace_back(as::buffer(&reason_code_, 1));
 
-             // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901156
 
-             // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-             if (!props_.empty()) {
 
-                 ret.emplace_back(as::buffer(property_length_buf_.data(), property_length_buf_.size()));
 
-                 for (auto const& p : props_) {
 
-                     v5::add_const_buffer_sequence(ret, p);
 
-                 }
 
-             }
 
-         }
 
-        return ret;
 
-    }
 
-     /**
 
-      * @brief Get whole size of sequence
 
-      * @return whole size
 
-      */
 
-     std::size_t size() const {
 
-         return
 
-             1 +                            // fixed header
 
-             remaining_length_buf_.size() +
 
-             remaining_length_;
 
-     }
 
-     /**
 
-      * @brief Get number of element of const_buffer_sequence
 
-      * @return number of element of const_buffer_sequence
 
-      */
 
-     constexpr std::size_t num_of_const_buffer_sequence() const {
 
-         return num_of_const_buffer_sequence_;
 
-     }
 
-     /**
 
-      * @brief Create one continuours buffer.
 
-      *        All sequence of buffers are concatinated.
 
-      *        It is useful to store to file/database.
 
-      * @return continuous buffer
 
-      */
 
-     std::string continuous_buffer() const {
 
-         std::string ret;
 
-         auto sz = size();
 
-         ret.reserve(sz);
 
-         ret.push_back(static_cast<char>(fixed_header_));
 
-         ret.append(remaining_length_buf_.data(), remaining_length_buf_.size());
 
-         // TODO: This is wrong. The reason code MUST be provided
 
-         // if there are properties. Not the other way around.
 
-         // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901154
 
-         // 3.7.2.1 PUBCOMP Reason Code
 
-         // The Reason Code and Property Length can be omitted if
 
-         // the Reason Code is 0x00 (Success) and there are no Properties.
 
-         // In this case the PUBCOMP has a Remaining Length of 2.
 
-         if (reason_code_ != v5::pubcomp_reason_code::success || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-             ret.push_back(static_cast<char>(reason_code_));
 
-             // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901156
 
-             // If the Remaining Length is less than 4 there is no Property Length and the value of 0 is used.
 
-             if (!props_.empty()) {
 
-                 ret.append(property_length_buf_.data(), property_length_buf_.size());
 
-                 auto it = ret.end();
 
-                 ret.resize(sz);
 
-                 auto end = ret.end();
 
-                 for (auto const& p : props_) {
 
-                     v5::fill(p, it, end);
 
-                     it += static_cast<std::string::difference_type>(v5::size(p));
 
-                 }
 
-             }
 
-         }
 
-         return ret;
 
-     }
 
-     std::uint8_t fixed_header_;
 
-     std::size_t remaining_length_;
 
-     boost::container::static_vector<char, 4> remaining_length_buf_;
 
-     boost::container::static_vector<char, PacketIdBytes> packet_id_;
 
-     pubcomp_reason_code reason_code_;
 
-     std::size_t property_length_;
 
-     boost::container::static_vector<char, 4> property_length_buf_;
 
-     properties props_;
 
-     std::size_t num_of_const_buffer_sequence_;
 
- };
 
- using pubcomp_message = basic_pubcomp_message<2>;
 
- template <std::size_t PacketIdBytes>
 
- class basic_subscribe_message {
 
- private:
 
-     struct entry {
 
-         entry(as::const_buffer topic_filter, subscribe_options options)
 
-             : topic_filter_(topic_filter),
 
-               topic_filter_length_buf_ { num_to_2bytes(boost::numeric_cast<std::uint16_t>(topic_filter_.size())) },
 
-               options_(options)
 
-         {}
 
-         as::const_buffer topic_filter_;
 
-         boost::container::static_vector<char, 2> topic_filter_length_buf_;
 
-         subscribe_options options_;
 
-     };
 
- public:
 
-     basic_subscribe_message(
 
-         std::vector<std::tuple<as::const_buffer, subscribe_options>> params,
 
-         typename packet_id_type<PacketIdBytes>::type packet_id,
 
-         properties props
 
-     )
 
-         : fixed_header_(make_fixed_header(control_packet_type::subscribe, 0b0010)),
 
-           remaining_length_(PacketIdBytes),
 
-           property_length_(
 
-               std::accumulate(
 
-                   props.begin(),
 
-                   props.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::size(pv);
 
-                   }
 
-               )
 
-           ),
 
-           props_(force_move(props)),
 
-           num_of_const_buffer_sequence_(
 
-               1 +                   // fixed header
 
-               1 +                   // remaining length
 
-               1 +                   // packet id
 
-               1 +                   // property length
 
-               std::accumulate(
 
-                   props_.begin(),
 
-                   props_.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::num_of_const_buffer_sequence(pv);
 
-                   }
 
-               ) +
 
-               params.size() * 3   // topic filter length, topic filter, qos
 
-           )
 
-     {
 
-         add_packet_id_to_buf<PacketIdBytes>::apply(packet_id_, packet_id);
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         remaining_length_ +=
 
-             property_length_buf_.size() +
 
-             property_length_;
 
-         // Check for errors before allocating.
 
-         for (auto&& e : params) {
 
-             as::const_buffer topic_filter = std::get<0>(e);
 
-             utf8string_check(topic_filter);
 
-         }
 
-         entries_.reserve(params.size());
 
-         for (auto&& e : params) {
 
-             as::const_buffer topic_filter = std::get<0>(e);
 
-             size_t size = topic_filter.size();
 
-             entries_.emplace_back(topic_filter, std::get<1>(e));
 
-             remaining_length_ +=
 
-                 2 +               // topic filter length
 
-                 size +            // topic filter
 
-                 1;                // means QoS
 
-         }
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-     }
 
-     /**
 
-      * @brief Create const buffer sequence
 
-      *        it is for boost asio APIs
 
-      * @return const buffer sequence
 
-      */
 
-     std::vector<as::const_buffer> const_buffer_sequence() const {
 
-         std::vector<as::const_buffer> ret;
 
-         ret.reserve(num_of_const_buffer_sequence());
 
-         ret.emplace_back(as::buffer(&fixed_header_, 1));
 
-         ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
 
-         ret.emplace_back(as::buffer(packet_id_.data(), packet_id_.size()));
 
-         ret.emplace_back(as::buffer(property_length_buf_.data(), property_length_buf_.size()));
 
-         for (auto const& p : props_) {
 
-             v5::add_const_buffer_sequence(ret, p);
 
-         }
 
-         for (auto const& e : entries_) {
 
-             ret.emplace_back(as::buffer(e.topic_filter_length_buf_.data(), e.topic_filter_length_buf_.size()));
 
-             ret.emplace_back(as::buffer(e.topic_filter_));
 
-             ret.emplace_back(as::buffer(&e.options_, 1));
 
-         }
 
-         return ret;
 
-     }
 
-     /**
 
-      * @brief Get whole size of sequence
 
-      * @return whole size
 
-      */
 
-     std::size_t size() const {
 
-         return
 
-             1 +                            // fixed header
 
-             remaining_length_buf_.size() +
 
-             remaining_length_;
 
-     }
 
-     /**
 
-      * @brief Get number of element of const_buffer_sequence
 
-      * @return number of element of const_buffer_sequence
 
-      */
 
-     constexpr std::size_t num_of_const_buffer_sequence() const {
 
-         return num_of_const_buffer_sequence_;
 
-     }
 
-     /**
 
-      * @brief Create one continuours buffer.
 
-      *        All sequence of buffers are concatinated.
 
-      *        It is useful to store to file/database.
 
-      * @return continuous buffer
 
-      */
 
-     std::string continuous_buffer() const {
 
-         std::string ret;
 
-         ret.reserve(size());
 
-         ret.push_back(static_cast<char>(fixed_header_));
 
-         ret.append(remaining_length_buf_.data(), remaining_length_buf_.size());
 
-         ret.append(packet_id_.data(), packet_id_.size());
 
-         ret.append(property_length_buf_.data(), property_length_buf_.size());
 
-         auto it = ret.end();
 
-         ret.resize(ret.size() + property_length_);
 
-         auto end = ret.end();
 
-         for (auto const& p : props_) {
 
-             v5::fill(p, it, end);
 
-             it += static_cast<std::string::difference_type>(v5::size(p));
 
-         }
 
-         for (auto const& e : entries_) {
 
-             ret.append(e.topic_filter_length_buf_.data(), e.topic_filter_length_buf_.size());
 
-             ret.append(get_pointer(e.topic_filter_), get_size(e.topic_filter_));
 
-             ret.push_back(static_cast<char>(e.options_.operator std::uint8_t()));
 
-         }
 
-         return ret;
 
-     }
 
- private:
 
-     std::uint8_t fixed_header_;
 
-     std::vector<entry> entries_;
 
-     boost::container::static_vector<char, PacketIdBytes> packet_id_;
 
-     std::size_t remaining_length_;
 
-     boost::container::static_vector<char, 4> remaining_length_buf_;
 
-     std::size_t property_length_;
 
-     boost::container::static_vector<char, 4> property_length_buf_;
 
-     properties props_;
 
-     std::size_t num_of_const_buffer_sequence_;
 
- };
 
- using subscribe_message = basic_subscribe_message<2>;
 
- template <std::size_t PacketIdBytes>
 
- class basic_suback_message {
 
- public:
 
-     basic_suback_message(
 
-         std::vector<suback_reason_code> reason_codes,
 
-         typename packet_id_type<PacketIdBytes>::type packet_id,
 
-         properties props
 
-     )
 
-         : fixed_header_(make_fixed_header(control_packet_type::suback, 0b0000)),
 
-           remaining_length_(reason_codes.size() + PacketIdBytes),
 
-           property_length_(
 
-               std::accumulate(
 
-                   props.begin(),
 
-                   props.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::size(pv);
 
-                   }
 
-               )
 
-           ),
 
-           props_(force_move(props)),
 
-           num_of_const_buffer_sequence_(
 
-               1 +                   // fixed header
 
-               1 +                   // remaining length
 
-               1 +                   // packet id
 
-               1 +                   // property length
 
-               std::accumulate(
 
-                   props_.begin(),
 
-                   props_.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::num_of_const_buffer_sequence(pv);
 
-                   }
 
-               ) +
 
-               1                     // entries (reason code ...)
 
-           )
 
-    {
 
-         add_packet_id_to_buf<PacketIdBytes>::apply(packet_id_, packet_id);
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         remaining_length_ +=
 
-             property_length_buf_.size() +
 
-             property_length_;
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-         entries_.reserve(reason_codes.size());
 
-         for (auto e : reason_codes) {
 
-             entries_.push_back(static_cast<char>(e));
 
-         }
 
-     }
 
-     /**
 
-      * @brief Create const buffer sequence
 
-      *        it is for boost asio APIs
 
-      * @return const buffer sequence
 
-      */
 
-     std::vector<as::const_buffer> const_buffer_sequence() const {
 
-         std::vector<as::const_buffer> ret;
 
-         ret.reserve(num_of_const_buffer_sequence());
 
-         ret.emplace_back(as::buffer(&fixed_header_, 1));
 
-         ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
 
-         ret.emplace_back(as::buffer(packet_id_.data(), packet_id_.size()));
 
-         ret.emplace_back(as::buffer(property_length_buf_.data(), property_length_buf_.size()));
 
-         for (auto const& p : props_) {
 
-             v5::add_const_buffer_sequence(ret, p);
 
-         }
 
-         ret.emplace_back(as::buffer(entries_));
 
-         return ret;
 
-     }
 
-     /**
 
-      * @brief Get whole size of sequence
 
-      * @return whole size
 
-      */
 
-     std::size_t size() const {
 
-         return
 
-             1 +                            // fixed header
 
-             remaining_length_buf_.size() +
 
-             remaining_length_;
 
-     }
 
-     /**
 
-      * @brief Get number of element of const_buffer_sequence
 
-      * @return number of element of const_buffer_sequence
 
-      */
 
-     constexpr std::size_t num_of_const_buffer_sequence() const {
 
-         return num_of_const_buffer_sequence_;
 
-     }
 
-     /**
 
-      * @brief Create one continuours buffer.
 
-      *        All sequence of buffers are concatinated.
 
-      *        It is useful to store to file/database.
 
-      * @return continuous buffer
 
-      */
 
-     std::string continuous_buffer() const {
 
-         std::string ret;
 
-         ret.reserve(size());
 
-         ret.push_back(static_cast<char>(fixed_header_));
 
-         ret.append(remaining_length_buf_.data(), remaining_length_buf_.size());
 
-         ret.append(packet_id_.data(), packet_id_.size());
 
-         auto it = ret.end();
 
-         ret.resize(ret.size() + property_length_);
 
-         auto end = ret.end();
 
-         for (auto const& p : props_) {
 
-             v5::fill(p, it, end);
 
-             it += static_cast<std::string::difference_type>(v5::size(p));
 
-         }
 
-         ret.append(entries_);
 
-         return ret;
 
-     }
 
- private:
 
-     std::uint8_t fixed_header_;
 
-     std::string entries_;
 
-     boost::container::static_vector<char, PacketIdBytes> packet_id_;
 
-     std::size_t remaining_length_;
 
-     boost::container::static_vector<char, 4> remaining_length_buf_;
 
-     std::size_t property_length_;
 
-     boost::container::static_vector<char, 4> property_length_buf_;
 
-     properties props_;
 
-     std::size_t num_of_const_buffer_sequence_;
 
- };
 
- using suback_message = basic_suback_message<2>;
 
- template <std::size_t PacketIdBytes>
 
- class basic_unsubscribe_message {
 
- private:
 
-     struct entry {
 
-         entry(as::const_buffer topic_filter)
 
-             : topic_filter_(topic_filter),
 
-               topic_filter_length_buf_ { num_to_2bytes(boost::numeric_cast<std::uint16_t>(topic_filter.size())) }
 
-         {}
 
-         as::const_buffer topic_filter_;
 
-         boost::container::static_vector<char, 2> topic_filter_length_buf_;
 
-     };
 
- public:
 
-     basic_unsubscribe_message(
 
-         std::vector<as::const_buffer> params,
 
-         typename packet_id_type<PacketIdBytes>::type packet_id,
 
-         properties props
 
-     )
 
-         : fixed_header_(make_fixed_header(control_packet_type::unsubscribe, 0b0010)),
 
-           remaining_length_(PacketIdBytes),
 
-           property_length_(
 
-               std::accumulate(
 
-                   props.begin(),
 
-                   props.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::size(pv);
 
-                   }
 
-               )
 
-           ),
 
-           props_(force_move(props)),
 
-           num_of_const_buffer_sequence_(
 
-               1 +                   // fixed header
 
-               1 +                   // remaining length
 
-               1 +                   // packet id
 
-               1 +                   // property length
 
-               std::accumulate(
 
-                   props_.begin(),
 
-                   props_.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::num_of_const_buffer_sequence(pv);
 
-                   }
 
-               ) +
 
-               params.size() * 2   // topic filter length, topic filter
 
-           )
 
-     {
 
-         add_packet_id_to_buf<PacketIdBytes>::apply(packet_id_, packet_id);
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         remaining_length_ +=
 
-             property_length_buf_.size() +
 
-             property_length_;
 
-         // Check for errors before allocating.
 
-         for (auto&& e : params) {
 
-             utf8string_check(e);
 
-         }
 
-         entries_.reserve(params.size());
 
-         for (auto&& e : params) {
 
-             auto size = e.size();
 
-             entries_.emplace_back(e);
 
-             remaining_length_ +=
 
-                 2 +          // topic filter length
 
-                 size;        // topic filter
 
-         }
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-     }
 
-     /**
 
-      * @brief Create const buffer sequence
 
-      *        it is for boost asio APIs
 
-      * @return const buffer sequence
 
-      */
 
-     std::vector<as::const_buffer> const_buffer_sequence() const {
 
-         std::vector<as::const_buffer> ret;
 
-         ret.reserve(num_of_const_buffer_sequence());
 
-         ret.emplace_back(as::buffer(&fixed_header_, 1));
 
-         ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
 
-         ret.emplace_back(as::buffer(packet_id_.data(), packet_id_.size()));
 
-         ret.emplace_back(as::buffer(property_length_buf_.data(), property_length_buf_.size()));
 
-         for (auto const& p : props_) {
 
-             v5::add_const_buffer_sequence(ret, p);
 
-         }
 
-         for (auto const& e : entries_) {
 
-             ret.emplace_back(as::buffer(e.topic_filter_length_buf_.data(), e.topic_filter_length_buf_.size()));
 
-             ret.emplace_back(as::buffer(e.topic_filter_));
 
-         }
 
-         return ret;
 
-     }
 
-     /**
 
-      * @brief Get whole size of sequence
 
-      * @return whole size
 
-      */
 
-     std::size_t size() const {
 
-         return
 
-             1 +                            // fixed header
 
-             remaining_length_buf_.size() +
 
-             remaining_length_;
 
-     }
 
-     /**
 
-      * @brief Get number of element of const_buffer_sequence
 
-      * @return number of element of const_buffer_sequence
 
-      */
 
-     constexpr std::size_t num_of_const_buffer_sequence() const {
 
-         return num_of_const_buffer_sequence_;
 
-     }
 
-     /**
 
-      * @brief Create one continuours buffer.
 
-      *        All sequence of buffers are concatinated.
 
-      *        It is useful to store to file/database.
 
-      * @return continuous buffer
 
-      */
 
-     std::string continuous_buffer() const {
 
-         std::string ret;
 
-         ret.reserve(size());
 
-         ret.push_back(static_cast<char>(fixed_header_));
 
-         ret.append(remaining_length_buf_.data(), remaining_length_buf_.size());
 
-         ret.append(packet_id_.data(), packet_id_.size());
 
-         auto it = ret.end();
 
-         ret.resize(ret.size() + property_length_);
 
-         auto end = ret.end();
 
-         for (auto const& p : props_) {
 
-             v5::fill(p, it, end);
 
-             it += static_cast<std::string::difference_type>(v5::size(p));
 
-         }
 
-         for (auto const& e : entries_) {
 
-             ret.append(e.topic_filter_length_buf_.data(), e.topic_filter_length_buf_.size());
 
-             ret.append(get_pointer(e.topic_filter_), get_size(e.topic_filter_));
 
-         }
 
-         return ret;
 
-     }
 
- private:
 
-     std::uint8_t fixed_header_;
 
-     std::vector<entry> entries_;
 
-     boost::container::static_vector<char, PacketIdBytes> packet_id_;
 
-     std::size_t remaining_length_;
 
-     boost::container::static_vector<char, 4> remaining_length_buf_;
 
-     std::size_t property_length_;
 
-     boost::container::static_vector<char, 4> property_length_buf_;
 
-     properties props_;
 
-     std::size_t num_of_const_buffer_sequence_;
 
- };
 
- using unsubscribe_message = basic_unsubscribe_message<2>;
 
- template <std::size_t PacketIdBytes>
 
- class basic_unsuback_message {
 
- public:
 
-     basic_unsuback_message(
 
-         std::vector<v5::unsuback_reason_code> reason_codes,
 
-         typename packet_id_type<PacketIdBytes>::type packet_id,
 
-         properties props
 
-     )
 
-         : fixed_header_(make_fixed_header(control_packet_type::unsuback, 0b0000)),
 
-           reason_codes_(force_move(reason_codes)),
 
-           remaining_length_(reason_codes_.size() + PacketIdBytes),
 
-           property_length_(
 
-               std::accumulate(
 
-                   props.begin(),
 
-                   props.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::size(pv);
 
-                   }
 
-               )
 
-           ),
 
-           props_(force_move(props)),
 
-           num_of_const_buffer_sequence_(
 
-               1 +                   // fixed header
 
-               1 +                   // remaining length
 
-               1 +                   // packet id
 
-               1 +                   // property length
 
-               std::accumulate(
 
-                   props_.begin(),
 
-                   props_.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::num_of_const_buffer_sequence(pv);
 
-                   }
 
-               )
 
-           )
 
-     {
 
-         add_packet_id_to_buf<PacketIdBytes>::apply(packet_id_, packet_id);
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         remaining_length_ +=
 
-             property_length_buf_.size() +
 
-             property_length_;
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-     }
 
-     /**
 
-      * @brief Create const buffer sequence
 
-      *        it is for boost asio APIs
 
-      * @return const buffer sequence
 
-      */
 
-     std::vector<as::const_buffer> const_buffer_sequence() const {
 
-         std::vector<as::const_buffer> ret;
 
-         ret.reserve(num_of_const_buffer_sequence());
 
-         ret.emplace_back(as::buffer(&fixed_header_, 1));
 
-         ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
 
-         ret.emplace_back(as::buffer(packet_id_.data(), packet_id_.size()));
 
-         ret.emplace_back(as::buffer(property_length_buf_.data(), property_length_buf_.size()));
 
-         for (auto const& p : props_) {
 
-             v5::add_const_buffer_sequence(ret, p);
 
-         }
 
-         ret.emplace_back(as::buffer(reinterpret_cast<char const*>(reason_codes_.data()), reason_codes_.size()));
 
-         return ret;
 
-     }
 
-     /**
 
-      * @brief Get whole size of sequence
 
-      * @return whole size
 
-      */
 
-     std::size_t size() const {
 
-         return
 
-             1 +                            // fixed header
 
-             remaining_length_buf_.size() +
 
-             remaining_length_;
 
-     }
 
-     /**
 
-      * @brief Get number of element of const_buffer_sequence
 
-      * @return number of element of const_buffer_sequence
 
-      */
 
-     constexpr std::size_t num_of_const_buffer_sequence() const {
 
-         return num_of_const_buffer_sequence_;
 
-     }
 
-     /**
 
-      * @brief Create one continuours buffer.
 
-      *        All sequence of buffers are concatinated.
 
-      *        It is useful to store to file/database.
 
-      * @return continuous buffer
 
-      */
 
-     std::string continuous_buffer() const {
 
-         std::string ret;
 
-         ret.reserve(size());
 
-         ret.push_back(static_cast<char>(fixed_header_));
 
-         ret.append(remaining_length_buf_.data(), remaining_length_buf_.size());
 
-         ret.append(packet_id_.data(), packet_id_.size());
 
-         auto it = ret.end();
 
-         ret.resize(ret.size() + property_length_);
 
-         auto end = ret.end();
 
-         for (auto const& p : props_) {
 
-             v5::fill(p, it, end);
 
-             it += static_cast<std::string::difference_type>(v5::size(p));
 
-         }
 
-         ret.append(reinterpret_cast<char const*>(reason_codes_.data()), reason_codes_.size());
 
-         return ret;
 
-     }
 
- private:
 
-     std::uint8_t fixed_header_;
 
-     std::vector<v5::unsuback_reason_code> reason_codes_;
 
-     boost::container::static_vector<char, PacketIdBytes> packet_id_;
 
-     std::size_t remaining_length_;
 
-     boost::container::static_vector<char, 4> remaining_length_buf_;
 
-     std::size_t property_length_;
 
-     boost::container::static_vector<char, 4> property_length_buf_;
 
-     properties props_;
 
-     std::size_t num_of_const_buffer_sequence_;
 
- };
 
- using unsuback_message = basic_unsuback_message<2>;
 
- struct pingreq_message : detail::header_only_message {
 
-     pingreq_message()
 
-         : detail::header_only_message(control_packet_type::pingreq, 0b0000)
 
-     {}
 
- };
 
- struct pingresp_message : detail::header_only_message {
 
-     pingresp_message()
 
-         : detail::header_only_message(control_packet_type::pingresp, 0b0000)
 
-     {}
 
- };
 
- struct disconnect_message {
 
-     disconnect_message(
 
-         v5::disconnect_reason_code reason_code,
 
-         properties props
 
-     )
 
-         : fixed_header_(make_fixed_header(control_packet_type::disconnect, 0b0000)),
 
-           remaining_length_(0),
 
-           reason_code_(reason_code),
 
-           property_length_(
 
-               std::accumulate(
 
-                   props.begin(),
 
-                   props.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::size(pv);
 
-                   }
 
-               )
 
-           ),
 
-           props_(force_move(props)),
 
-           num_of_const_buffer_sequence_(
 
-               1 +                   // fixed header
 
-               1 +                   // remaining length
 
-               (
 
-                   // TODO: This is wrong. The reason code MUST be provided
 
-                   // if there are properties. Not the other way around.
 
-                   // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144
 
-                   // 3.14.2.1 Disconnect Reason Code
 
-                   // The Reason Code and Property Length can be omitted if
 
-                   // the Reason Code is 0x00 (Normal disconnecton) and there are no
 
-                   // Properties. In this case the DISCONNECT has a Remaining Length of 0.
 
-                   reason_code_ != v5::disconnect_reason_code::normal_disconnection || MQTT_ALWAYS_SEND_REASON_CODE ? (
 
-                       1 +                   // reason code
 
-                       1 +                   // property length
 
-                       std::accumulate(
 
-                           props_.begin(),
 
-                           props_.end(),
 
-                           std::size_t(0U),
 
-                           [](std::size_t total, property_variant const& pv) {
 
-                               return total + v5::num_of_const_buffer_sequence(pv);
 
-                           }
 
-                       )
 
-                   )
 
-                   : 0
 
-               )
 
-           )
 
-     {
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         // TODO: This is wrong. The reason code MUST be provided
 
-         // if there are properties. Not the other way around.
 
-         // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144
 
-         // 3.14.2.1 Disconnect Reason Code
 
-         // The Reason Code and Property Length can be omitted if
 
-         // the Reason Code is 0x00 (Normal disconnecton) and there are no
 
-         // Properties. In this case the DISCONNECT has a Remaining Length of 0.
 
-         if (reason_code_ != v5::disconnect_reason_code::normal_disconnection || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-             remaining_length_ =
 
-                 1 +                           // reason code
 
-                 property_length_buf_.size() +
 
-                 property_length_;
 
-         }
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-     }
 
-     /**
 
-      * @brief Create const buffer sequence
 
-      *        it is for boost asio APIs
 
-      * @return const buffer sequence
 
-      */
 
-     std::vector<as::const_buffer> const_buffer_sequence() const {
 
-         std::vector<as::const_buffer> ret;
 
-         ret.reserve(num_of_const_buffer_sequence());
 
-         ret.emplace_back(as::buffer(&fixed_header_, 1));
 
-         ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
 
-         // TODO: This is wrong. The reason code MUST be provided
 
-         // if there are properties. Not the other way around.
 
-         // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144
 
-         // 3.14.2.1 Disconnect Reason Code
 
-         // The Reason Code and Property Length can be omitted if
 
-         // the Reason Code is 0x00 (Normal disconnecton) and there are no
 
-         // Properties. In this case the DISCONNECT has a Remaining Length of 0.
 
-         if (reason_code_ != v5::disconnect_reason_code::normal_disconnection || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-             ret.emplace_back(as::buffer(&reason_code_, 1));
 
-             ret.emplace_back(as::buffer(property_length_buf_.data(), property_length_buf_.size()));
 
-             for (auto const& p : props_) {
 
-                 v5::add_const_buffer_sequence(ret, p);
 
-             }
 
-         }
 
-         return ret;
 
-     }
 
-     /**
 
-      * @brief Get whole size of sequence
 
-      * @return whole size
 
-      */
 
-     std::size_t size() const {
 
-         return
 
-             1 +                            // fixed header
 
-             remaining_length_buf_.size() +
 
-             remaining_length_;
 
-     }
 
-     /**
 
-      * @brief Get number of element of const_buffer_sequence
 
-      * @return number of element of const_buffer_sequence
 
-      */
 
-     constexpr std::size_t num_of_const_buffer_sequence() const {
 
-         return num_of_const_buffer_sequence_;
 
-     }
 
-     /**
 
-      * @brief Create one continuours buffer.
 
-      *        All sequence of buffers are concatinated.
 
-      *        It is useful to store to file/database.
 
-      * @return continuous buffer
 
-      */
 
-     std::string continuous_buffer() const {
 
-         std::string ret;
 
-         ret.reserve(size());
 
-         ret.push_back(static_cast<char>(fixed_header_));
 
-         ret.append(remaining_length_buf_.data(), remaining_length_buf_.size());
 
-         // TODO: This is wrong. The reason code MUST be provided
 
-         // if there are properties. Not the other way around.
 
-         // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901144
 
-         // 3.14.2.1 Disconnect Reason Code
 
-         // The Reason Code and Property Length can be omitted if
 
-         // the Reason Code is 0x00 (Normal disconnecton) and there are no
 
-         // Properties. In this case the DISCONNECT has a Remaining Length of 0.
 
-         if (reason_code_ != v5::disconnect_reason_code::normal_disconnection || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-             ret.push_back(static_cast<char>(reason_code_));
 
-             auto it = ret.end();
 
-             ret.resize(ret.size() + property_length_);
 
-             auto end = ret.end();
 
-             for (auto const& p : props_) {
 
-                 v5::fill(p, it, end);
 
-                 it += static_cast<std::string::difference_type>(v5::size(p));
 
-             }
 
-         }
 
-         return ret;
 
-     }
 
- private:
 
-     std::uint8_t fixed_header_;
 
-     std::size_t remaining_length_;
 
-     boost::container::static_vector<char, 4> remaining_length_buf_;
 
-     v5::disconnect_reason_code reason_code_;
 
-     std::size_t property_length_;
 
-     boost::container::static_vector<char, 4> property_length_buf_;
 
-     properties props_;
 
-     std::size_t num_of_const_buffer_sequence_;
 
- };
 
- struct auth_message {
 
-     auth_message(
 
-         v5::auth_reason_code reason_code,
 
-         properties props
 
-     )
 
-         : fixed_header_(make_fixed_header(control_packet_type::auth, 0b0000)),
 
-           remaining_length_(0),
 
-           reason_code_(reason_code),
 
-           property_length_(
 
-               std::accumulate(
 
-                   props.begin(),
 
-                   props.end(),
 
-                   std::size_t(0U),
 
-                   [](std::size_t total, property_variant const& pv) {
 
-                       return total + v5::size(pv);
 
-                   }
 
-               )
 
-           ),
 
-           props_(force_move(props)),
 
-           num_of_const_buffer_sequence_(
 
-               1 +                   // fixed header
 
-               1 +                   // remaining length
 
-               (
 
-                   // TODO: This is wrong. The reason code MUST be provided
 
-                   // if there are properties. Not the other way around.
 
-                   // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901220
 
-                   // 3.15.2.1 Authenticate Reason Code
 
-                   // The Reason Code and Property Length can be omitted if
 
-                   // the Reason Code is 0x00 (Success) and there are no
 
-                   // Properties. In this case the AUTH has a Remaining Length of 0.
 
-                   reason_code_ != v5::auth_reason_code::success || MQTT_ALWAYS_SEND_REASON_CODE ?
 
-                   (
 
-                       1 +                   // reason code
 
-                       1 +                   // property length
 
-                       std::accumulate(
 
-                           props_.begin(),
 
-                           props_.end(),
 
-                           std::size_t(0U),
 
-                           [](std::size_t total, property_variant const& pv) {
 
-                               return total + v5::num_of_const_buffer_sequence(pv);
 
-                           }
 
-                       )
 
-                   )
 
-                   : 0
 
-               )
 
-           )
 
-     {
 
-         auto pb = variable_bytes(property_length_);
 
-         for (auto e : pb) {
 
-             property_length_buf_.push_back(e);
 
-         }
 
-         // TODO: This is wrong. The reason code MUST be provided
 
-         // if there are properties. Not the other way around.
 
-         // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901220
 
-         // 3.15.2.1 Authenticate Reason Code
 
-         // The Reason Code and Property Length can be omitted if
 
-         // the Reason Code is 0x00 (Success) and there are no
 
-         // Properties. In this case the AUTH has a Remaining Length of 0.
 
-         if (reason_code_ != v5::auth_reason_code::success || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-             remaining_length_ =
 
-                 1 +                           // reason code
 
-                 property_length_buf_.size() +
 
-                 property_length_;
 
-         }
 
-         auto rb = remaining_bytes(remaining_length_);
 
-         for (auto e : rb) {
 
-             remaining_length_buf_.push_back(e);
 
-         }
 
-     }
 
-     /**
 
-      * @brief Create const buffer sequence
 
-      *        it is for boost asio APIs
 
-      * @return const buffer sequence
 
-      */
 
-     std::vector<as::const_buffer> const_buffer_sequence() const {
 
-         std::vector<as::const_buffer> ret;
 
-         ret.reserve(num_of_const_buffer_sequence());
 
-         ret.emplace_back(as::buffer(&fixed_header_, 1));
 
-         ret.emplace_back(as::buffer(remaining_length_buf_.data(), remaining_length_buf_.size()));
 
-         // TODO: This is wrong. The reason code MUST be provided
 
-         // if there are properties. Not the other way around.
 
-         // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901220
 
-         // 3.15.2.1 Authenticate Reason Code
 
-         // The Reason Code and Property Length can be omitted if
 
-         // the Reason Code is 0x00 (Success) and there are no
 
-         // Properties. In this case the AUTH has a Remaining Length of 0.
 
-         if (reason_code_ != v5::auth_reason_code::success || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-             ret.emplace_back(as::buffer(&reason_code_, 1));
 
-             ret.emplace_back(as::buffer(property_length_buf_.data(), property_length_buf_.size()));
 
-             for (auto const& p : props_) {
 
-                 v5::add_const_buffer_sequence(ret, p);
 
-             }
 
-         }
 
-         return ret;
 
-     }
 
-     /**
 
-      * @brief Get whole size of sequence
 
-      * @return whole size
 
-      */
 
-     std::size_t size() const {
 
-         return
 
-             1 +                            // fixed header
 
-             remaining_length_buf_.size() +
 
-             remaining_length_;
 
-     }
 
-     /**
 
-      * @brief Get number of element of const_buffer_sequence
 
-      * @return number of element of const_buffer_sequence
 
-      */
 
-     constexpr std::size_t num_of_const_buffer_sequence() const {
 
-         return num_of_const_buffer_sequence_;
 
-     }
 
-    /**
 
-      * @brief Create one continuours buffer.
 
-      *        All sequence of buffers are concatinated.
 
-      *        It is useful to store to file/database.
 
-      * @return continuous buffer
 
-      */
 
-     std::string continuous_buffer() const {
 
-         std::string ret;
 
-         ret.reserve(size());
 
-         ret.push_back(static_cast<char>(fixed_header_));
 
-         ret.append(remaining_length_buf_.data(), remaining_length_buf_.size());
 
-         // TODO: This is wrong. The reason code MUST be provided
 
-         // if there are properties. Not the other way around.
 
-         // https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901220
 
-         // 3.15.2.1 Authenticate Reason Code
 
-         // The Reason Code and Property Length can be omitted if
 
-         // the Reason Code is 0x00 (Success) and there are no
 
-         // Properties. In this case the AUTH has a Remaining Length of 0.
 
-         if (reason_code_ != v5::auth_reason_code::success || MQTT_ALWAYS_SEND_REASON_CODE) {
 
-             ret.push_back(static_cast<char>(reason_code_));
 
-             auto it = ret.end();
 
-             ret.resize(ret.size() + property_length_);
 
-             auto end = ret.end();
 
-             for (auto const& p : props_) {
 
-                 v5::fill(p, it, end);
 
-                 it += static_cast<std::string::difference_type>(v5::size(p));
 
-             }
 
-         }
 
-         return ret;
 
-     }
 
- private:
 
-     std::uint8_t fixed_header_;
 
-     std::size_t remaining_length_;
 
-     boost::container::static_vector<char, 4> remaining_length_buf_;
 
-     v5::auth_reason_code reason_code_;
 
-     std::size_t property_length_;
 
-     boost::container::static_vector<char, 4> property_length_buf_;
 
-     properties props_;
 
-     std::size_t num_of_const_buffer_sequence_;
 
- };
 
- } // namespace v5
 
- } // namespace MQTT_NS
 
- #endif // MQTT_V5_MESSAGE_HPP
 
 
  |