123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- // 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_PROPERTY_PARSE_HPP)
- #define MQTT_PROPERTY_PARSE_HPP
- #include <vector>
- #include <mqtt/namespace.hpp>
- #include <mqtt/optional.hpp>
- #include <mqtt/property_variant.hpp>
- #include <mqtt/variable_length.hpp>
- #include <mqtt/move.hpp>
- namespace MQTT_NS {
- namespace v5 {
- namespace property {
- inline
- optional<property_variant> parse_one(buffer& buf) {
- if (buf.empty()) return nullopt;
- try {
- auto id = static_cast<property::id>(buf.front());
- buf.remove_prefix(1);
- switch (id) {
- case id::payload_format_indicator: {
- if (buf.size() < 1) return nullopt;
- auto p = payload_format_indicator(buf.begin(), std::next(buf.begin(), 1));
- buf.remove_prefix(1);
- return property_variant(p);
- } break;
- case id::message_expiry_interval: {
- if (buf.size() < 4) return nullopt;
- auto p = message_expiry_interval(buf.begin(), std::next(buf.begin(), 4));
- buf.remove_prefix(4);
- return property_variant(p);
- } break;
- case id::content_type: {
- if (buf.size() < 2) return nullopt;
- auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
- if (buf.size() < 2U + len) return nullopt;
- auto p = content_type(buf.substr(2, len));
- buf.remove_prefix(2 + len);
- return property_variant(p);
- } break;
- case id::response_topic: {
- if (buf.size() < 2) return nullopt;
- auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
- if (buf.size() < 2U + len) return nullopt;
- auto p = response_topic(buf.substr(2, len));
- buf.remove_prefix(2 + len);
- return property_variant(p);
- } break;
- case id::correlation_data: {
- if (buf.size() < 2) return nullopt;
- auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
- if (buf.size() < 2U + len) return nullopt;
- auto p = correlation_data(buf.substr(2, len));
- buf.remove_prefix(2 + len);
- return property_variant(p);
- } break;
- case id::subscription_identifier: {
- auto val_consumed = variable_length(buf.begin(), buf.end());
- auto val = std::get<0>(val_consumed);
- auto consumed = std::get<1>(val_consumed);
- if (consumed == 0) return nullopt;
- auto p = subscription_identifier(val);
- buf.remove_prefix(consumed);
- return property_variant(p);
- } break;
- case id::session_expiry_interval: {
- if (buf.size() < 4) return nullopt;
- auto p = session_expiry_interval(buf.begin(), std::next(buf.begin(), 4));
- buf.remove_prefix(4);
- return property_variant(p);
- } break;
- case id::assigned_client_identifier: {
- if (buf.size() < 2) return nullopt;
- auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
- if (buf.size() < 2U + len) return nullopt;
- auto p = assigned_client_identifier(buf.substr(2, len));
- buf.remove_prefix(2 + len);
- return property_variant(p);
- } break;
- case id::server_keep_alive: {
- if (buf.size() < 2) return nullopt;
- auto p = server_keep_alive(buf.begin(), std::next(buf.begin(), 2));
- buf.remove_prefix(2);
- return property_variant(p);
- } break;
- case id::authentication_method: {
- if (buf.size() < 2) return nullopt;
- auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
- if (buf.size() < 2U + len) return nullopt;
- auto p = authentication_method(buf.substr(2, len));
- buf.remove_prefix(2 + len);
- return property_variant(p);
- } break;
- case id::authentication_data: {
- if (buf.size() < 2) return nullopt;
- auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
- if (buf.size() < 2U + len) return nullopt;
- auto p = authentication_data(buf.substr(2, len));
- buf.remove_prefix(2 + len);
- return property_variant(p);
- } break;
- case id::request_problem_information: {
- if (buf.size() < 1) return nullopt;
- auto p = request_problem_information(buf.begin(), std::next(buf.begin(), 1));
- buf.remove_prefix(1);
- return property_variant(p);
- } break;
- case id::will_delay_interval: {
- if (buf.size() < 4) return nullopt;
- auto p = will_delay_interval(buf.begin(), std::next(buf.begin(), 4));
- buf.remove_prefix(4);
- return property_variant(p);
- } break;
- case id::request_response_information: {
- if (buf.size() < 1) return nullopt;
- auto p = request_response_information(buf.begin(), std::next(buf.begin(), 1));
- buf.remove_prefix(1);
- return property_variant(p);
- } break;
- case id::response_information: {
- if (buf.size() < 2) return nullopt;
- auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
- if (buf.size() < 2U + len) return nullopt;
- auto p = response_information(buf.substr(2, len));
- buf.remove_prefix(2 + len);
- return property_variant(p);
- } break;
- case id::server_reference: {
- if (buf.size() < 2) return nullopt;
- auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
- if (buf.size() < 2U + len) return nullopt;
- auto p = server_reference(buf.substr(2, len));
- buf.remove_prefix(2 + len);
- return property_variant(p);
- } break;
- case id::reason_string: {
- if (buf.size() < 2) return nullopt;
- auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
- if (buf.size() < 2U + len) return nullopt;
- auto p = reason_string(buf.substr(2, len));
- buf.remove_prefix(2 + len);
- return property_variant(p);
- } break;
- case id::receive_maximum: {
- if (buf.size() < 2) return nullopt;
- auto p = receive_maximum(buf.begin(), std::next(buf.begin(), 2));
- buf.remove_prefix(2);
- return property_variant(p);
- } break;
- case id::topic_alias_maximum: {
- if (buf.size() < 2) return nullopt;
- auto p = topic_alias_maximum(buf.begin(), std::next(buf.begin(), 2));
- buf.remove_prefix(2);
- return property_variant(p);
- } break;
- case id::topic_alias: {
- if (buf.size() < 2) return nullopt;
- auto p = topic_alias(buf.begin(), std::next(buf.begin(), 2));
- buf.remove_prefix(2);
- return property_variant(p);
- } break;
- case id::maximum_qos: {
- if (buf.size() < 1) return nullopt;
- auto p = maximum_qos(buf.begin(), std::next(buf.begin(), 1));
- buf.remove_prefix(1);
- return property_variant(p);
- } break;
- case id::retain_available: {
- if (buf.size() < 1) return nullopt;
- auto p = retain_available(buf.begin(), std::next(buf.begin(), 1));
- buf.remove_prefix(1);
- return property_variant(p);
- } break;
- case id::user_property: {
- if (buf.size() < 2) return nullopt;
- auto keylen = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
- if (buf.size() < 2U + keylen) return nullopt;
- auto key = buf.substr(2, keylen);
- buf.remove_prefix(2 + keylen);
- if (buf.size() < 2) return nullopt;
- auto vallen = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
- if (buf.size() < 2U + vallen) return nullopt;
- auto val = buf.substr(2, vallen);
- auto p = user_property(force_move(key), force_move(val));
- buf.remove_prefix(2 + vallen);
- return property_variant(p);
- } break;
- case id::maximum_packet_size: {
- if (buf.size() < 4) return nullopt;
- auto p = maximum_packet_size(buf.begin(), std::next(buf.begin(), 4));
- buf.remove_prefix(4);
- return property_variant(p);
- } break;
- case id::wildcard_subscription_available: {
- if (buf.size() < 1) return nullopt;
- auto p = wildcard_subscription_available(buf.begin(), std::next(buf.begin(), 1));
- buf.remove_prefix(1);
- return property_variant(p);
- } break;
- case id::subscription_identifier_available: {
- if (buf.size() < 1) return nullopt;
- auto p = subscription_identifier_available(buf.begin(), std::next(buf.begin(), 1));
- buf.remove_prefix(1);
- return property_variant(p);
- } break;
- case id::shared_subscription_available: {
- if (buf.size() < 1) return nullopt;
- auto p = shared_subscription_available(buf.begin(), std::next(buf.begin(), 1));
- buf.remove_prefix(1);
- return property_variant(p);
- } break;
- }
- }
- catch (property_parse_error const&) {
- return nullopt;
- }
- return nullopt;
- }
- inline
- std::vector<property_variant> parse(buffer buf) {
- std::vector<property_variant> props;
- while (true) {
- if (auto ret = parse_one(buf)) {
- props.push_back(force_move(ret.value()));
- }
- else {
- break;
- }
- }
- return props;
- }
- } // namespace property
- } // namespace v5
- } // namespace MQTT_NS
- #endif // MQTT_PROPERTY_PARSE_HPP
|