| 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 {inlineoptional<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;}inlinestd::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
 |