property_parse.hpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. // Copyright Takatoshi Kondo 2018
  2. //
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #if !defined(MQTT_PROPERTY_PARSE_HPP)
  7. #define MQTT_PROPERTY_PARSE_HPP
  8. #include <vector>
  9. #include <mqtt/namespace.hpp>
  10. #include <mqtt/optional.hpp>
  11. #include <mqtt/property_variant.hpp>
  12. #include <mqtt/variable_length.hpp>
  13. #include <mqtt/move.hpp>
  14. namespace MQTT_NS {
  15. namespace v5 {
  16. namespace property {
  17. inline
  18. optional<property_variant> parse_one(buffer& buf) {
  19. if (buf.empty()) return nullopt;
  20. try {
  21. auto id = static_cast<property::id>(buf.front());
  22. buf.remove_prefix(1);
  23. switch (id) {
  24. case id::payload_format_indicator: {
  25. if (buf.size() < 1) return nullopt;
  26. auto p = payload_format_indicator(buf.begin(), std::next(buf.begin(), 1));
  27. buf.remove_prefix(1);
  28. return property_variant(p);
  29. } break;
  30. case id::message_expiry_interval: {
  31. if (buf.size() < 4) return nullopt;
  32. auto p = message_expiry_interval(buf.begin(), std::next(buf.begin(), 4));
  33. buf.remove_prefix(4);
  34. return property_variant(p);
  35. } break;
  36. case id::content_type: {
  37. if (buf.size() < 2) return nullopt;
  38. auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
  39. if (buf.size() < 2U + len) return nullopt;
  40. auto p = content_type(buf.substr(2, len));
  41. buf.remove_prefix(2 + len);
  42. return property_variant(p);
  43. } break;
  44. case id::response_topic: {
  45. if (buf.size() < 2) return nullopt;
  46. auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
  47. if (buf.size() < 2U + len) return nullopt;
  48. auto p = response_topic(buf.substr(2, len));
  49. buf.remove_prefix(2 + len);
  50. return property_variant(p);
  51. } break;
  52. case id::correlation_data: {
  53. if (buf.size() < 2) return nullopt;
  54. auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
  55. if (buf.size() < 2U + len) return nullopt;
  56. auto p = correlation_data(buf.substr(2, len));
  57. buf.remove_prefix(2 + len);
  58. return property_variant(p);
  59. } break;
  60. case id::subscription_identifier: {
  61. auto val_consumed = variable_length(buf.begin(), buf.end());
  62. auto val = std::get<0>(val_consumed);
  63. auto consumed = std::get<1>(val_consumed);
  64. if (consumed == 0) return nullopt;
  65. auto p = subscription_identifier(val);
  66. buf.remove_prefix(consumed);
  67. return property_variant(p);
  68. } break;
  69. case id::session_expiry_interval: {
  70. if (buf.size() < 4) return nullopt;
  71. auto p = session_expiry_interval(buf.begin(), std::next(buf.begin(), 4));
  72. buf.remove_prefix(4);
  73. return property_variant(p);
  74. } break;
  75. case id::assigned_client_identifier: {
  76. if (buf.size() < 2) return nullopt;
  77. auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
  78. if (buf.size() < 2U + len) return nullopt;
  79. auto p = assigned_client_identifier(buf.substr(2, len));
  80. buf.remove_prefix(2 + len);
  81. return property_variant(p);
  82. } break;
  83. case id::server_keep_alive: {
  84. if (buf.size() < 2) return nullopt;
  85. auto p = server_keep_alive(buf.begin(), std::next(buf.begin(), 2));
  86. buf.remove_prefix(2);
  87. return property_variant(p);
  88. } break;
  89. case id::authentication_method: {
  90. if (buf.size() < 2) return nullopt;
  91. auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
  92. if (buf.size() < 2U + len) return nullopt;
  93. auto p = authentication_method(buf.substr(2, len));
  94. buf.remove_prefix(2 + len);
  95. return property_variant(p);
  96. } break;
  97. case id::authentication_data: {
  98. if (buf.size() < 2) return nullopt;
  99. auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
  100. if (buf.size() < 2U + len) return nullopt;
  101. auto p = authentication_data(buf.substr(2, len));
  102. buf.remove_prefix(2 + len);
  103. return property_variant(p);
  104. } break;
  105. case id::request_problem_information: {
  106. if (buf.size() < 1) return nullopt;
  107. auto p = request_problem_information(buf.begin(), std::next(buf.begin(), 1));
  108. buf.remove_prefix(1);
  109. return property_variant(p);
  110. } break;
  111. case id::will_delay_interval: {
  112. if (buf.size() < 4) return nullopt;
  113. auto p = will_delay_interval(buf.begin(), std::next(buf.begin(), 4));
  114. buf.remove_prefix(4);
  115. return property_variant(p);
  116. } break;
  117. case id::request_response_information: {
  118. if (buf.size() < 1) return nullopt;
  119. auto p = request_response_information(buf.begin(), std::next(buf.begin(), 1));
  120. buf.remove_prefix(1);
  121. return property_variant(p);
  122. } break;
  123. case id::response_information: {
  124. if (buf.size() < 2) return nullopt;
  125. auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
  126. if (buf.size() < 2U + len) return nullopt;
  127. auto p = response_information(buf.substr(2, len));
  128. buf.remove_prefix(2 + len);
  129. return property_variant(p);
  130. } break;
  131. case id::server_reference: {
  132. if (buf.size() < 2) return nullopt;
  133. auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
  134. if (buf.size() < 2U + len) return nullopt;
  135. auto p = server_reference(buf.substr(2, len));
  136. buf.remove_prefix(2 + len);
  137. return property_variant(p);
  138. } break;
  139. case id::reason_string: {
  140. if (buf.size() < 2) return nullopt;
  141. auto len = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
  142. if (buf.size() < 2U + len) return nullopt;
  143. auto p = reason_string(buf.substr(2, len));
  144. buf.remove_prefix(2 + len);
  145. return property_variant(p);
  146. } break;
  147. case id::receive_maximum: {
  148. if (buf.size() < 2) return nullopt;
  149. auto p = receive_maximum(buf.begin(), std::next(buf.begin(), 2));
  150. buf.remove_prefix(2);
  151. return property_variant(p);
  152. } break;
  153. case id::topic_alias_maximum: {
  154. if (buf.size() < 2) return nullopt;
  155. auto p = topic_alias_maximum(buf.begin(), std::next(buf.begin(), 2));
  156. buf.remove_prefix(2);
  157. return property_variant(p);
  158. } break;
  159. case id::topic_alias: {
  160. if (buf.size() < 2) return nullopt;
  161. auto p = topic_alias(buf.begin(), std::next(buf.begin(), 2));
  162. buf.remove_prefix(2);
  163. return property_variant(p);
  164. } break;
  165. case id::maximum_qos: {
  166. if (buf.size() < 1) return nullopt;
  167. auto p = maximum_qos(buf.begin(), std::next(buf.begin(), 1));
  168. buf.remove_prefix(1);
  169. return property_variant(p);
  170. } break;
  171. case id::retain_available: {
  172. if (buf.size() < 1) return nullopt;
  173. auto p = retain_available(buf.begin(), std::next(buf.begin(), 1));
  174. buf.remove_prefix(1);
  175. return property_variant(p);
  176. } break;
  177. case id::user_property: {
  178. if (buf.size() < 2) return nullopt;
  179. auto keylen = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
  180. if (buf.size() < 2U + keylen) return nullopt;
  181. auto key = buf.substr(2, keylen);
  182. buf.remove_prefix(2 + keylen);
  183. if (buf.size() < 2) return nullopt;
  184. auto vallen = make_uint16_t(buf.begin(), std::next(buf.begin(), 2));
  185. if (buf.size() < 2U + vallen) return nullopt;
  186. auto val = buf.substr(2, vallen);
  187. auto p = user_property(force_move(key), force_move(val));
  188. buf.remove_prefix(2 + vallen);
  189. return property_variant(p);
  190. } break;
  191. case id::maximum_packet_size: {
  192. if (buf.size() < 4) return nullopt;
  193. auto p = maximum_packet_size(buf.begin(), std::next(buf.begin(), 4));
  194. buf.remove_prefix(4);
  195. return property_variant(p);
  196. } break;
  197. case id::wildcard_subscription_available: {
  198. if (buf.size() < 1) return nullopt;
  199. auto p = wildcard_subscription_available(buf.begin(), std::next(buf.begin(), 1));
  200. buf.remove_prefix(1);
  201. return property_variant(p);
  202. } break;
  203. case id::subscription_identifier_available: {
  204. if (buf.size() < 1) return nullopt;
  205. auto p = subscription_identifier_available(buf.begin(), std::next(buf.begin(), 1));
  206. buf.remove_prefix(1);
  207. return property_variant(p);
  208. } break;
  209. case id::shared_subscription_available: {
  210. if (buf.size() < 1) return nullopt;
  211. auto p = shared_subscription_available(buf.begin(), std::next(buf.begin(), 1));
  212. buf.remove_prefix(1);
  213. return property_variant(p);
  214. } break;
  215. }
  216. }
  217. catch (property_parse_error const&) {
  218. return nullopt;
  219. }
  220. return nullopt;
  221. }
  222. inline
  223. std::vector<property_variant> parse(buffer buf) {
  224. std::vector<property_variant> props;
  225. while (true) {
  226. if (auto ret = parse_one(buf)) {
  227. props.push_back(force_move(ret.value()));
  228. }
  229. else {
  230. break;
  231. }
  232. }
  233. return props;
  234. }
  235. } // namespace property
  236. } // namespace v5
  237. } // namespace MQTT_NS
  238. #endif // MQTT_PROPERTY_PARSE_HPP