mirror of
https://github.com/boostorg/mqtt5.git
synced 2025-09-25 08:20:56 +02:00
Drop Spirit dependency
Summary: Ref #36 Reviewers: ivica Reviewed By: ivica Subscribers: miljen Differential Revision: https://repo.mireo.local/D37107
This commit is contained in:
@@ -49,12 +49,9 @@ else()
|
|||||||
Boost::container
|
Boost::container
|
||||||
Boost::core
|
Boost::core
|
||||||
Boost::endian
|
Boost::endian
|
||||||
Boost::fusion
|
|
||||||
Boost::optional
|
|
||||||
Boost::random
|
Boost::random
|
||||||
Boost::range
|
Boost::range
|
||||||
Boost::smart_ptr
|
Boost::smart_ptr
|
||||||
Boost::spirit
|
|
||||||
Boost::system
|
Boost::system
|
||||||
Boost::type_traits
|
Boost::type_traits
|
||||||
Threads::Threads
|
Threads::Threads
|
||||||
|
@@ -13,12 +13,9 @@ constant boost_dependencies :
|
|||||||
/boost/container//boost_container
|
/boost/container//boost_container
|
||||||
/boost/core//boost_core
|
/boost/core//boost_core
|
||||||
/boost/endian//boost_endian
|
/boost/endian//boost_endian
|
||||||
/boost/fusion//boost_fusion
|
|
||||||
/boost/optional//boost_optional
|
|
||||||
/boost/random//boost_random
|
/boost/random//boost_random
|
||||||
/boost/range//boost_range
|
/boost/range//boost_range
|
||||||
/boost/smart_ptr//boost_smart_ptr
|
/boost/smart_ptr//boost_smart_ptr
|
||||||
/boost/spirit//boost_spirit
|
|
||||||
/boost/system//boost_system
|
/boost/system//boost_system
|
||||||
/boost/type_traits//boost_type_traits
|
/boost/type_traits//boost_type_traits
|
||||||
;
|
;
|
||||||
|
@@ -12,11 +12,7 @@
|
|||||||
|
|
||||||
#include <boost/mqtt5/detail/traits.hpp>
|
#include <boost/mqtt5/detail/traits.hpp>
|
||||||
|
|
||||||
#include <boost/fusion/adapted/std_tuple.hpp>
|
#include <boost/endian/conversion.hpp>
|
||||||
#include <boost/fusion/container/deque.hpp>
|
|
||||||
#include <boost/optional/optional.hpp>
|
|
||||||
#include <boost/spirit/home/x3.hpp>
|
|
||||||
#include <boost/spirit/home/x3/binary/binary.hpp>
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -24,217 +20,49 @@
|
|||||||
|
|
||||||
namespace boost::mqtt5::decoders {
|
namespace boost::mqtt5::decoders {
|
||||||
|
|
||||||
namespace x3 = boost::spirit::x3;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct convert { using type = T; };
|
|
||||||
|
|
||||||
template <typename ...Args>
|
|
||||||
struct convert<boost::fusion::deque<Args...>> {
|
|
||||||
using type = std::tuple<typename convert<Args>::type...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct convert<boost::optional<T>> {
|
|
||||||
using type = std::optional<T>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct convert<std::vector<T>> {
|
|
||||||
using type = std::vector<typename convert<T>::type>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename Parser>
|
|
||||||
constexpr auto as(Parser&& p) {
|
|
||||||
return x3::rule<struct _, T>{} = std::forward<Parser>(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename It, typename Parser>
|
template <typename It, typename Parser>
|
||||||
auto type_parse(It& first, const It last, const Parser& p) {
|
auto type_parse(It& first, const It last, const Parser& p) {
|
||||||
using ctx_type = decltype(x3::make_context<struct _>(std::declval<Parser&>()));
|
using rv_type = typename Parser::attribute_type;
|
||||||
using attr_type = typename x3::traits::attribute_of<Parser, ctx_type>::type;
|
|
||||||
|
|
||||||
using rv_type = typename convert<attr_type>::type;
|
|
||||||
|
|
||||||
std::optional<rv_type> rv;
|
std::optional<rv_type> rv;
|
||||||
rv_type value {};
|
rv_type value {};
|
||||||
if (x3::phrase_parse(first, last, as<rv_type>(p), x3::eps(false), value))
|
if (p.parse(first, last, value))
|
||||||
rv = std::move(value);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename AttributeType, typename It, typename Parser>
|
|
||||||
auto type_parse(It& first, const It last, const Parser& p) {
|
|
||||||
std::optional<AttributeType> rv;
|
|
||||||
AttributeType value {};
|
|
||||||
if (x3::phrase_parse(first, last, as<AttributeType>(p), x3::eps(false), value))
|
|
||||||
rv = std::move(value);
|
rv = std::move(value);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace basic {
|
namespace basic {
|
||||||
|
|
||||||
template <typename T>
|
template <typename Attr>
|
||||||
constexpr auto to(T& arg) {
|
struct int_parser {
|
||||||
return [&](auto& ctx) {
|
using attribute_type = Attr;
|
||||||
using ctx_type = decltype(ctx);
|
|
||||||
using attr_type = decltype(x3::_attr(std::declval<const ctx_type&>()));
|
|
||||||
if constexpr (detail::is_boost_iterator<attr_type>)
|
|
||||||
arg = T { x3::_attr(ctx).begin(), x3::_attr(ctx).end() };
|
|
||||||
else
|
|
||||||
arg = x3::_attr(ctx);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename LenParser, typename Subject, typename Enable = void>
|
template <typename It>
|
||||||
class scope_limit {};
|
bool parse(It& first, const It last, Attr& attr) const {
|
||||||
|
constexpr size_t byte_size = sizeof(Attr);
|
||||||
template <typename LenParser, typename Subject>
|
if (std::distance(first, last) < static_cast<ptrdiff_t>(byte_size))
|
||||||
class scope_limit<
|
|
||||||
LenParser, Subject,
|
|
||||||
std::enable_if_t<x3::traits::is_parser<LenParser>::value>
|
|
||||||
> :
|
|
||||||
public x3::unary_parser<Subject, scope_limit<LenParser, Subject>>
|
|
||||||
{
|
|
||||||
using base_type = x3::unary_parser<Subject, scope_limit<LenParser, Subject>>;
|
|
||||||
LenParser _lp;
|
|
||||||
public:
|
|
||||||
using ctx_type =
|
|
||||||
decltype(x3::make_context<struct _>(std::declval<Subject&>()));
|
|
||||||
using attribute_type =
|
|
||||||
typename x3::traits::attribute_of<Subject, ctx_type>::type;
|
|
||||||
|
|
||||||
static bool const has_attribute = true;
|
|
||||||
|
|
||||||
scope_limit(const LenParser& lp, const Subject& subject) :
|
|
||||||
base_type(subject), _lp(lp)
|
|
||||||
{}
|
|
||||||
|
|
||||||
template <typename It, typename Ctx, typename RCtx, typename Attr>
|
|
||||||
bool parse(
|
|
||||||
It& first, const It last,
|
|
||||||
const Ctx& ctx, RCtx& rctx, Attr& attr
|
|
||||||
) const {
|
|
||||||
|
|
||||||
It iter = first;
|
|
||||||
typename x3::traits::attribute_of<LenParser, Ctx>::type len;
|
|
||||||
if (!_lp.parse(iter, last, ctx, rctx, len))
|
|
||||||
return false;
|
|
||||||
if (iter + len > last)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!base_type::subject.parse(iter, iter + len, ctx, rctx, attr))
|
using namespace boost::endian;
|
||||||
return false;
|
attr = endian_load<Attr, sizeof(Attr), order::big>(
|
||||||
|
reinterpret_cast<const uint8_t*>(static_cast<const char*>(&*first))
|
||||||
|
);
|
||||||
|
first += sizeof(Attr);
|
||||||
|
|
||||||
first = iter;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Size, typename Subject>
|
inline constexpr int_parser<uint8_t> byte_;
|
||||||
class scope_limit<
|
inline constexpr int_parser<uint16_t> word_;
|
||||||
Size, Subject,
|
inline constexpr int_parser<uint32_t> dword_;
|
||||||
std::enable_if_t<std::is_arithmetic_v<Size>>
|
|
||||||
> :
|
|
||||||
public x3::unary_parser<Subject, scope_limit<Size, Subject>>
|
|
||||||
{
|
|
||||||
using base_type = x3::unary_parser<Subject, scope_limit<Size, Subject>>;
|
|
||||||
size_t _limit;
|
|
||||||
public:
|
|
||||||
using ctx_type =
|
|
||||||
decltype(x3::make_context<struct _>(std::declval<Subject&>()));
|
|
||||||
using attribute_type =
|
|
||||||
typename x3::traits::attribute_of<Subject, ctx_type>::type;
|
|
||||||
|
|
||||||
static bool const has_attribute = true;
|
struct varint_parser {
|
||||||
|
|
||||||
scope_limit(Size limit, const Subject& subject) :
|
|
||||||
base_type(subject), _limit(limit)
|
|
||||||
{}
|
|
||||||
|
|
||||||
template <typename It, typename Ctx, typename RCtx, typename Attr>
|
|
||||||
bool parse(
|
|
||||||
It& first, const It last,
|
|
||||||
const Ctx& ctx, RCtx& rctx, Attr& attr
|
|
||||||
) const {
|
|
||||||
|
|
||||||
It iter = first;
|
|
||||||
if (iter + _limit > last)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!base_type::subject.parse(iter, iter + _limit, ctx, rctx, attr))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
first = iter;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename LenParser, typename Enable = void>
|
|
||||||
struct scope_limit_gen {
|
|
||||||
template <typename Subject>
|
|
||||||
auto operator[](const Subject& p) const {
|
|
||||||
return scope_limit<LenParser, Subject> { _lp, x3::as_parser(p) };
|
|
||||||
}
|
|
||||||
LenParser _lp;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Size>
|
|
||||||
struct scope_limit_gen<
|
|
||||||
Size,
|
|
||||||
std::enable_if_t<std::is_arithmetic_v<Size>>
|
|
||||||
> {
|
|
||||||
template <typename Subject>
|
|
||||||
auto operator[](const Subject& p) const {
|
|
||||||
return scope_limit<Size, Subject> { limit, x3::as_parser(p) };
|
|
||||||
}
|
|
||||||
Size limit;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <
|
|
||||||
typename Parser,
|
|
||||||
std::enable_if_t<x3::traits::is_parser<Parser>::value, bool> = true
|
|
||||||
>
|
|
||||||
scope_limit_gen<Parser> scope_limit_(const Parser& p) {
|
|
||||||
return { p };
|
|
||||||
}
|
|
||||||
|
|
||||||
template <
|
|
||||||
typename Size,
|
|
||||||
std::enable_if_t<std::is_arithmetic_v<Size>, bool> = true
|
|
||||||
>
|
|
||||||
scope_limit_gen<Size> scope_limit_(Size limit) {
|
|
||||||
return { limit };
|
|
||||||
}
|
|
||||||
|
|
||||||
struct verbatim_parser : x3::parser<verbatim_parser> {
|
|
||||||
using attribute_type = std::string;
|
|
||||||
static bool const has_attribute = true;
|
|
||||||
|
|
||||||
template <typename It, typename Ctx, typename RCtx, typename Attr>
|
|
||||||
bool parse(It& first, const It last, const Ctx&, RCtx&, Attr& attr) const {
|
|
||||||
attr = std::string { first, last };
|
|
||||||
first = last;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr auto verbatim_ = verbatim_parser{};
|
|
||||||
|
|
||||||
struct varint_parser : x3::parser<varint_parser> {
|
|
||||||
using attribute_type = int32_t;
|
using attribute_type = int32_t;
|
||||||
static bool const has_attribute = true;
|
|
||||||
|
|
||||||
template <typename It, typename Ctx, typename RCtx, typename Attr>
|
template <typename It>
|
||||||
bool parse(
|
bool parse(It& first, const It last, int32_t& attr) const {
|
||||||
It& first, const It last,
|
auto iter = first;
|
||||||
const Ctx& ctx, RCtx&, Attr& attr
|
|
||||||
) const {
|
|
||||||
|
|
||||||
It iter = first;
|
|
||||||
x3::skip_over(iter, last, ctx);
|
|
||||||
|
|
||||||
if (iter == last)
|
if (iter == last)
|
||||||
return false;
|
return false;
|
||||||
@@ -262,22 +90,17 @@ struct varint_parser : x3::parser<varint_parser> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr varint_parser varint_{};
|
inline constexpr varint_parser varint_;
|
||||||
|
|
||||||
struct len_prefix_parser : x3::parser<len_prefix_parser> {
|
struct len_prefix_parser {
|
||||||
using attribute_type = std::string;
|
using attribute_type = std::string;
|
||||||
static bool const has_attribute = true;
|
|
||||||
|
|
||||||
template <typename It, typename Ctx, typename RCtx, typename Attr>
|
template <typename It>
|
||||||
bool parse(
|
bool parse(It& first, const It last, std::string& attr) const {
|
||||||
It& first, const It last,
|
auto iter = first;
|
||||||
const Ctx& ctx, RCtx& rctx, Attr& attr
|
|
||||||
) const {
|
|
||||||
It iter = first;
|
|
||||||
x3::skip_over(iter, last, ctx);
|
|
||||||
|
|
||||||
typename x3::traits::attribute_of<decltype(x3::big_word), Ctx>::type len;
|
typename decltype(word_)::attribute_type len;
|
||||||
if (x3::big_word.parse(iter, last, ctx, rctx, len)) {
|
if (word_.parse(iter, last, len)) {
|
||||||
if (std::distance(iter, last) < len)
|
if (std::distance(iter, last) < len)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -290,44 +113,25 @@ struct len_prefix_parser : x3::parser<len_prefix_parser> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr len_prefix_parser utf8_ {};
|
inline constexpr len_prefix_parser utf8_ {};
|
||||||
constexpr len_prefix_parser binary_ {};
|
inline constexpr len_prefix_parser binary_ {};
|
||||||
|
|
||||||
/*
|
|
||||||
Boost Spirit incorrectly deduces atribute type for a parser of the form
|
|
||||||
(eps(a) | parser1) >> (eps(b) | parser)
|
|
||||||
and we had to create if_ parser to remedy the issue
|
|
||||||
*/
|
|
||||||
|
|
||||||
template <typename Subject>
|
template <typename Subject>
|
||||||
class conditional_parser :
|
struct conditional_parser {
|
||||||
public x3::unary_parser<Subject, conditional_parser<Subject>> {
|
using subject_attr_type = typename Subject::attribute_type;
|
||||||
|
using attribute_type = std::optional<subject_attr_type>;
|
||||||
|
|
||||||
using base_type = x3::unary_parser<Subject, conditional_parser<Subject>>;
|
Subject p;
|
||||||
bool _condition;
|
bool condition;
|
||||||
public:
|
|
||||||
using ctx_type =
|
|
||||||
decltype(x3::make_context<struct _>(std::declval<Subject&>()));
|
|
||||||
using subject_attr_type =
|
|
||||||
typename x3::traits::attribute_of<Subject, ctx_type>::type;
|
|
||||||
|
|
||||||
using attribute_type = boost::optional<subject_attr_type>;
|
template <typename It>
|
||||||
static bool const has_attribute = true;
|
bool parse(It& first, const It last, attribute_type& attr) const {
|
||||||
|
if (!condition)
|
||||||
conditional_parser(const Subject& s, bool condition) :
|
|
||||||
base_type(s), _condition(condition) {}
|
|
||||||
|
|
||||||
template <typename It, typename Ctx, typename RCtx, typename Attr>
|
|
||||||
bool parse(
|
|
||||||
It& first, const It last,
|
|
||||||
const Ctx& ctx, RCtx& rctx, Attr& attr
|
|
||||||
) const {
|
|
||||||
if (!_condition)
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
It iter = first;
|
auto iter = first;
|
||||||
subject_attr_type sattr {};
|
subject_attr_type sattr {};
|
||||||
if (!base_type::subject.parse(iter, last, ctx, rctx, sattr))
|
if (!p.parse(iter, last, sattr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
attr.emplace(std::move(sattr));
|
attr.emplace(std::move(sattr));
|
||||||
@@ -340,59 +144,155 @@ struct conditional_gen {
|
|||||||
bool _condition;
|
bool _condition;
|
||||||
|
|
||||||
template <typename Subject>
|
template <typename Subject>
|
||||||
auto operator[](const Subject& p) const {
|
conditional_parser<Subject> operator[](const Subject& p) const {
|
||||||
return conditional_parser<Subject> { p, _condition };
|
return { p, _condition };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline conditional_gen if_(bool condition) {
|
constexpr conditional_gen if_(bool condition) {
|
||||||
return { condition };
|
return { condition };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct verbatim_parser {
|
||||||
|
using attribute_type = std::string;
|
||||||
|
|
||||||
|
template <typename It>
|
||||||
|
bool parse(It& first, const It last, std::string& attr) const {
|
||||||
|
attr = std::string { first, last };
|
||||||
|
first = last;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr auto verbatim_ = verbatim_parser{};
|
||||||
|
|
||||||
|
template <typename... Ps>
|
||||||
|
struct seq_parser {
|
||||||
|
using attribute_type = std::tuple<typename Ps::attribute_type...>;
|
||||||
|
|
||||||
|
std::tuple<Ps...> parsers;
|
||||||
|
|
||||||
|
template <typename It>
|
||||||
|
bool parse(It& first, const It last, attribute_type& attr) const {
|
||||||
|
return parse_impl(
|
||||||
|
first, last, attr, std::make_index_sequence<sizeof...(Ps)>{}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename It, size_t... Is>
|
||||||
|
bool parse_impl(
|
||||||
|
It& first, const It last, attribute_type& attr,
|
||||||
|
std::index_sequence<Is...>
|
||||||
|
) const {
|
||||||
|
auto iter = first;
|
||||||
|
bool rv = (
|
||||||
|
std::get<Is>(parsers).parse(iter, last, std::get<Is>(attr))
|
||||||
|
&& ...
|
||||||
|
);
|
||||||
|
if (rv)
|
||||||
|
first = iter;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... Ps, typename P2>
|
||||||
|
constexpr seq_parser<Ps..., P2> operator>>(
|
||||||
|
const seq_parser<Ps...>& p1, const P2& p2
|
||||||
|
) {
|
||||||
|
return { std::tuple_cat(p1.parsers, std::make_tuple(p2)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename P1, typename P2>
|
||||||
|
constexpr seq_parser<P1, P2> operator>>(const P1& p1, const P2& p2) {
|
||||||
|
return { std::make_tuple(p1, p2) };
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Attr>
|
||||||
|
struct attr_parser {
|
||||||
|
using attribute_type = Attr;
|
||||||
|
|
||||||
|
Attr attr;
|
||||||
|
|
||||||
|
template <typename It>
|
||||||
|
bool parse(It&, const It, Attr& attr) const {
|
||||||
|
attr = this->attr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Attr>
|
||||||
|
constexpr attr_parser<Attr> attr(const Attr& val) {
|
||||||
|
return { val };
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Subject>
|
||||||
|
struct plus_parser {
|
||||||
|
using subject_attr_type = typename Subject::attribute_type;
|
||||||
|
using attribute_type = std::vector<subject_attr_type>;
|
||||||
|
|
||||||
|
Subject p;
|
||||||
|
|
||||||
|
template <typename It, typename Attr>
|
||||||
|
bool parse(It& first, const It last, Attr& attr) const {
|
||||||
|
bool success = false;
|
||||||
|
while (first < last) {
|
||||||
|
subject_attr_type sattr {};
|
||||||
|
auto iter = first;
|
||||||
|
if (!p.parse(iter, last, sattr)) break;
|
||||||
|
|
||||||
|
success = true;
|
||||||
|
first = iter;
|
||||||
|
attr.push_back(std::move(sattr));
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename P>
|
||||||
|
constexpr plus_parser<P> operator+(const P& p) {
|
||||||
|
return { p };
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace basic
|
} // end namespace basic
|
||||||
|
|
||||||
|
|
||||||
namespace prop {
|
namespace prop {
|
||||||
|
|
||||||
namespace basic = boost::mqtt5::decoders::basic;
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <typename It, typename Ctx, typename RCtx, typename Prop>
|
template <typename It, typename Prop>
|
||||||
bool parse_to_prop(
|
bool parse_to_prop(It& iter, const It last, Prop& prop) {
|
||||||
It& iter, const It last,
|
|
||||||
const Ctx& ctx, RCtx& rctx, Prop& prop
|
|
||||||
) {
|
|
||||||
using namespace boost::mqtt5::detail;
|
using namespace boost::mqtt5::detail;
|
||||||
using prop_type = std::remove_reference_t<decltype(prop)>;
|
using prop_type = std::remove_reference_t<decltype(prop)>;
|
||||||
|
|
||||||
bool rv = false;
|
bool rv = false;
|
||||||
|
|
||||||
if constexpr (std::is_same_v<prop_type, uint8_t>)
|
if constexpr (std::is_same_v<prop_type, uint8_t>)
|
||||||
rv = x3::byte_.parse(iter, last, ctx, rctx, prop);
|
rv = basic::byte_.parse(iter, last, prop);
|
||||||
else if constexpr (std::is_same_v<prop_type, uint16_t>)
|
else if constexpr (std::is_same_v<prop_type, uint16_t>)
|
||||||
rv = x3::big_word.parse(iter, last, ctx, rctx, prop);
|
rv = basic::word_.parse(iter, last, prop);
|
||||||
else if constexpr (std::is_same_v<prop_type, int32_t>)
|
else if constexpr (std::is_same_v<prop_type, int32_t>)
|
||||||
rv = basic::varint_.parse(iter, last, ctx, rctx, prop);
|
rv = basic::varint_.parse(iter, last, prop);
|
||||||
else if constexpr (std::is_same_v<prop_type, uint32_t>)
|
else if constexpr (std::is_same_v<prop_type, uint32_t>)
|
||||||
rv = x3::big_dword.parse(iter, last, ctx, rctx, prop);
|
rv = basic::dword_.parse(iter, last, prop);
|
||||||
else if constexpr (std::is_same_v<prop_type, std::string>)
|
else if constexpr (std::is_same_v<prop_type, std::string>)
|
||||||
rv = basic::utf8_.parse(iter, last, ctx, rctx, prop);
|
rv = basic::utf8_.parse(iter, last, prop);
|
||||||
|
|
||||||
else if constexpr (is_optional<prop_type>) {
|
else if constexpr (is_optional<prop_type>) {
|
||||||
typename prop_type::value_type val;
|
typename prop_type::value_type val;
|
||||||
rv = parse_to_prop(iter, last, ctx, rctx, val);
|
rv = parse_to_prop(iter, last, val);
|
||||||
if (rv) prop.emplace(std::move(val));
|
if (rv) prop.emplace(std::move(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (is_pair<prop_type>) {
|
else if constexpr (is_pair<prop_type>) {
|
||||||
rv = parse_to_prop(iter, last, ctx, rctx, prop.first);
|
rv = parse_to_prop(iter, last, prop.first);
|
||||||
rv = parse_to_prop(iter, last, ctx, rctx, prop.second);
|
rv = parse_to_prop(iter, last, prop.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if constexpr (is_vector<prop_type> || is_small_vector<prop_type>) {
|
else if constexpr (is_vector<prop_type> || is_small_vector<prop_type>) {
|
||||||
typename std::remove_reference_t<prop_type>::value_type value;
|
typename std::remove_reference_t<prop_type>::value_type value;
|
||||||
rv = parse_to_prop(iter, last, ctx, rctx, value);
|
rv = parse_to_prop(iter, last, value);
|
||||||
if (rv) prop.push_back(std::move(value));
|
if (rv) prop.push_back(std::move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,28 +302,21 @@ bool parse_to_prop(
|
|||||||
} // end namespace detail
|
} // end namespace detail
|
||||||
|
|
||||||
template <typename Props>
|
template <typename Props>
|
||||||
class prop_parser : public x3::parser<prop_parser<Props>> {
|
struct prop_parser {
|
||||||
public:
|
|
||||||
using attribute_type = Props;
|
using attribute_type = Props;
|
||||||
static bool const has_attribute = true;
|
|
||||||
|
|
||||||
template <typename It, typename Ctx, typename RCtx, typename Attr>
|
template <typename It>
|
||||||
bool parse(
|
bool parse(It& first, const It last, Props& attr) const {
|
||||||
It& first, const It last,
|
auto iter = first;
|
||||||
const Ctx& ctx, RCtx& rctx, Attr& attr
|
|
||||||
) const {
|
|
||||||
|
|
||||||
It iter = first;
|
|
||||||
x3::skip_over(iter, last, ctx);
|
|
||||||
|
|
||||||
if (iter == last)
|
if (iter == last)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
int32_t props_length;
|
int32_t props_length;
|
||||||
if (!basic::varint_.parse(iter, last, ctx, rctx, props_length))
|
if (!basic::varint_.parse(iter, last, props_length))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const It scoped_last = iter + props_length;
|
const auto scoped_last = iter + props_length;
|
||||||
// attr = Props{};
|
// attr = Props{};
|
||||||
|
|
||||||
while (iter < scoped_last) {
|
while (iter < scoped_last) {
|
||||||
@@ -433,10 +326,8 @@ public:
|
|||||||
|
|
||||||
attr.apply_on(
|
attr.apply_on(
|
||||||
prop_id,
|
prop_id,
|
||||||
[&rv, &iter, scoped_last, &ctx, &rctx](auto& prop) {
|
[&rv, &iter, scoped_last](auto& prop) {
|
||||||
rv = detail::parse_to_prop(
|
rv = detail::parse_to_prop(iter, scoped_last, prop);
|
||||||
iter, scoped_last, ctx, rctx, prop
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -450,13 +341,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename Props>
|
template <typename Props>
|
||||||
constexpr auto props_ = prop_parser<Props> {};
|
constexpr auto props_ = prop_parser<Props> {};
|
||||||
|
|
||||||
} // end namespace prop
|
} // end namespace prop
|
||||||
|
|
||||||
|
|
||||||
} // end namespace boost::mqtt5::decoders
|
} // end namespace boost::mqtt5::decoders
|
||||||
|
|
||||||
#endif // !BOOST_MQTT5_BASE_DECODERS_HPP
|
#endif // !BOOST_MQTT5_BASE_DECODERS_HPP
|
||||||
|
@@ -32,7 +32,7 @@ using fixed_header = std::tuple<
|
|||||||
inline std::optional<fixed_header> decode_fixed_header(
|
inline std::optional<fixed_header> decode_fixed_header(
|
||||||
byte_citer& it, const byte_citer last
|
byte_citer& it, const byte_citer last
|
||||||
) {
|
) {
|
||||||
auto fixed_header_ = x3::byte_ >> basic::varint_;
|
constexpr auto fixed_header_ = basic::byte_ >> basic::varint_;
|
||||||
return type_parse(it, last, fixed_header_);
|
return type_parse(it, last, fixed_header_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ using packet_id = uint16_t;
|
|||||||
inline std::optional<packet_id> decode_packet_id(
|
inline std::optional<packet_id> decode_packet_id(
|
||||||
byte_citer& it
|
byte_citer& it
|
||||||
) {
|
) {
|
||||||
auto packet_id_ = x3::big_word;
|
constexpr auto packet_id_ = basic::word_;
|
||||||
return type_parse(it, it + sizeof(uint16_t), packet_id_);
|
return type_parse(it, it + sizeof(uint16_t), packet_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,11 +58,11 @@ using connect_message = std::tuple<
|
|||||||
inline std::optional<connect_message> decode_connect(
|
inline std::optional<connect_message> decode_connect(
|
||||||
uint32_t remain_length, byte_citer& it
|
uint32_t remain_length, byte_citer& it
|
||||||
) {
|
) {
|
||||||
auto var_header_ =
|
constexpr auto var_header_ =
|
||||||
basic::utf8_ >> // MQTT
|
basic::utf8_ >> // MQTT
|
||||||
x3::byte_ >> // (num 5)
|
basic::byte_ >> // (num 5)
|
||||||
x3::byte_ >> // conn_flags_
|
basic::byte_ >> // conn_flags_
|
||||||
x3::big_word >> // keep_alive
|
basic::word_ >> // keep_alive
|
||||||
prop::props_<connect_props>;
|
prop::props_<connect_props>;
|
||||||
|
|
||||||
const byte_citer end = it + remain_length;
|
const byte_citer end = it + remain_length;
|
||||||
@@ -124,9 +124,7 @@ using connack_message = std::tuple<
|
|||||||
inline std::optional<connack_message> decode_connack(
|
inline std::optional<connack_message> decode_connack(
|
||||||
uint32_t remain_length, byte_citer& it
|
uint32_t remain_length, byte_citer& it
|
||||||
) {
|
) {
|
||||||
auto connack_ = basic::scope_limit_(remain_length)[
|
constexpr auto connack_ = basic::byte_ >> basic::byte_ >> prop::props_<connack_props>;
|
||||||
x3::byte_ >> x3::byte_ >> prop::props_<connack_props>
|
|
||||||
];
|
|
||||||
return type_parse(it, it + remain_length, connack_);
|
return type_parse(it, it + remain_length, connack_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,10 +142,10 @@ inline std::optional<publish_message> decode_publish(
|
|||||||
uint8_t flags = control_byte & 0b1111;
|
uint8_t flags = control_byte & 0b1111;
|
||||||
auto qos = qos_e((flags >> 1) & 0b11);
|
auto qos = qos_e((flags >> 1) & 0b11);
|
||||||
|
|
||||||
auto publish_ = basic::scope_limit_(remain_length)[
|
auto publish_ =
|
||||||
basic::utf8_ >> basic::if_(qos != qos_e::at_most_once)[x3::big_word] >>
|
basic::utf8_ >> basic::if_(qos != qos_e::at_most_once)[basic::word_] >>
|
||||||
x3::attr(flags) >> prop::props_<publish_props> >> basic::verbatim_
|
basic::attr(flags) >> prop::props_<publish_props> >>
|
||||||
];
|
basic::verbatim_;
|
||||||
return type_parse(it, it + remain_length, publish_);
|
return type_parse(it, it + remain_length, publish_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,9 +159,7 @@ inline std::optional<puback_message> decode_puback(
|
|||||||
) {
|
) {
|
||||||
if (remain_length == 0)
|
if (remain_length == 0)
|
||||||
return puback_message {};
|
return puback_message {};
|
||||||
auto puback_ = basic::scope_limit_(remain_length)[
|
constexpr auto puback_ = basic::byte_ >> prop::props_<puback_props>;
|
||||||
x3::byte_ >> prop::props_<puback_props>
|
|
||||||
];
|
|
||||||
return type_parse(it, it + remain_length, puback_);
|
return type_parse(it, it + remain_length, puback_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,9 +173,7 @@ inline std::optional<pubrec_message> decode_pubrec(
|
|||||||
) {
|
) {
|
||||||
if (remain_length == 0)
|
if (remain_length == 0)
|
||||||
return pubrec_message {};
|
return pubrec_message {};
|
||||||
auto pubrec_ = basic::scope_limit_(remain_length)[
|
constexpr auto pubrec_ = basic::byte_ >> prop::props_<pubrec_props>;
|
||||||
x3::byte_ >> prop::props_<pubrec_props>
|
|
||||||
];
|
|
||||||
return type_parse(it, it + remain_length, pubrec_);
|
return type_parse(it, it + remain_length, pubrec_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,9 +187,7 @@ inline std::optional<pubrel_message> decode_pubrel(
|
|||||||
) {
|
) {
|
||||||
if (remain_length == 0)
|
if (remain_length == 0)
|
||||||
return pubrel_message {};
|
return pubrel_message {};
|
||||||
auto pubrel_ = basic::scope_limit_(remain_length)[
|
constexpr auto pubrel_ = basic::byte_ >> prop::props_<pubrel_props>;
|
||||||
x3::byte_ >> prop::props_<pubrel_props>
|
|
||||||
];
|
|
||||||
return type_parse(it, it + remain_length, pubrel_);
|
return type_parse(it, it + remain_length, pubrel_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,9 +201,7 @@ inline std::optional<pubcomp_message> decode_pubcomp(
|
|||||||
) {
|
) {
|
||||||
if (remain_length == 0)
|
if (remain_length == 0)
|
||||||
return pubcomp_message {};
|
return pubcomp_message {};
|
||||||
auto pubcomp_ = basic::scope_limit_(remain_length)[
|
constexpr auto pubcomp_ = basic::byte_ >> prop::props_<pubcomp_props>;
|
||||||
x3::byte_ >> prop::props_<pubcomp_props>
|
|
||||||
];
|
|
||||||
return type_parse(it, it + remain_length, pubcomp_);
|
return type_parse(it, it + remain_length, pubcomp_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,9 +213,7 @@ using subscribe_message = std::tuple<
|
|||||||
inline std::optional<subscribe_message> decode_subscribe(
|
inline std::optional<subscribe_message> decode_subscribe(
|
||||||
uint32_t remain_length, byte_citer& it
|
uint32_t remain_length, byte_citer& it
|
||||||
) {
|
) {
|
||||||
auto subscribe_ = basic::scope_limit_(remain_length)[
|
constexpr auto subscribe_ = prop::props_<subscribe_props> >> +(basic::utf8_ >> basic::byte_);
|
||||||
prop::props_<subscribe_props> >> +(basic::utf8_ >> x3::byte_)
|
|
||||||
];
|
|
||||||
return type_parse(it, it + remain_length, subscribe_);
|
return type_parse(it, it + remain_length, subscribe_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,9 +225,7 @@ using suback_message = std::tuple<
|
|||||||
inline std::optional<suback_message> decode_suback(
|
inline std::optional<suback_message> decode_suback(
|
||||||
uint32_t remain_length, byte_citer& it
|
uint32_t remain_length, byte_citer& it
|
||||||
) {
|
) {
|
||||||
auto suback_ = basic::scope_limit_(remain_length)[
|
constexpr auto suback_ = prop::props_<suback_props> >> +basic::byte_;
|
||||||
prop::props_<suback_props> >> +x3::byte_
|
|
||||||
];
|
|
||||||
return type_parse(it, it + remain_length, suback_);
|
return type_parse(it, it + remain_length, suback_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,9 +237,7 @@ using unsubscribe_message = std::tuple<
|
|||||||
inline std::optional<unsubscribe_message> decode_unsubscribe(
|
inline std::optional<unsubscribe_message> decode_unsubscribe(
|
||||||
uint32_t remain_length, byte_citer& it
|
uint32_t remain_length, byte_citer& it
|
||||||
) {
|
) {
|
||||||
auto unsubscribe_ = basic::scope_limit_(remain_length)[
|
constexpr auto unsubscribe_ = prop::props_<unsubscribe_props> >> +basic::utf8_;
|
||||||
prop::props_<unsubscribe_props> >> +basic::utf8_
|
|
||||||
];
|
|
||||||
return type_parse(it, it + remain_length, unsubscribe_);
|
return type_parse(it, it + remain_length, unsubscribe_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,9 +249,7 @@ using unsuback_message = std::tuple<
|
|||||||
inline std::optional<unsuback_message> decode_unsuback(
|
inline std::optional<unsuback_message> decode_unsuback(
|
||||||
uint32_t remain_length, byte_citer& it
|
uint32_t remain_length, byte_citer& it
|
||||||
) {
|
) {
|
||||||
auto unsuback_ = basic::scope_limit_(remain_length)[
|
constexpr auto unsuback_ = prop::props_<unsuback_props> >> +basic::byte_;
|
||||||
prop::props_<unsuback_props> >> +x3::byte_
|
|
||||||
];
|
|
||||||
return type_parse(it, it + remain_length, unsuback_);
|
return type_parse(it, it + remain_length, unsuback_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,9 +263,7 @@ inline std::optional<disconnect_message> decode_disconnect(
|
|||||||
) {
|
) {
|
||||||
if (remain_length == 0)
|
if (remain_length == 0)
|
||||||
return disconnect_message {};
|
return disconnect_message {};
|
||||||
auto disconnect_ = basic::scope_limit_(remain_length)[
|
constexpr auto disconnect_ = basic::byte_ >> prop::props_<disconnect_props>;
|
||||||
x3::byte_ >> prop::props_<disconnect_props>
|
|
||||||
];
|
|
||||||
return type_parse(it, it + remain_length, disconnect_);
|
return type_parse(it, it + remain_length, disconnect_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,9 +277,7 @@ inline std::optional<auth_message> decode_auth(
|
|||||||
) {
|
) {
|
||||||
if (remain_length == 0)
|
if (remain_length == 0)
|
||||||
return auth_message {};
|
return auth_message {};
|
||||||
auto auth_ = basic::scope_limit_(remain_length)[
|
constexpr auto auth_ = basic::byte_ >> prop::props_<auth_props>;
|
||||||
x3::byte_ >> prop::props_<auth_props>
|
|
||||||
];
|
|
||||||
return type_parse(it, it + remain_length, auth_);
|
return type_parse(it, it + remain_length, auth_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,9 +8,8 @@
|
|||||||
#ifndef BOOST_MQTT5_ENDPOINTS_HPP
|
#ifndef BOOST_MQTT5_ENDPOINTS_HPP
|
||||||
#define BOOST_MQTT5_ENDPOINTS_HPP
|
#define BOOST_MQTT5_ENDPOINTS_HPP
|
||||||
|
|
||||||
#include <boost/mqtt5/types.hpp>
|
|
||||||
|
|
||||||
#include <boost/mqtt5/detail/log_invoke.hpp>
|
#include <boost/mqtt5/detail/log_invoke.hpp>
|
||||||
|
#include <boost/mqtt5/detail/internal_types.hpp>
|
||||||
|
|
||||||
#include <boost/asio/append.hpp>
|
#include <boost/asio/append.hpp>
|
||||||
#include <boost/asio/associated_allocator.hpp>
|
#include <boost/asio/associated_allocator.hpp>
|
||||||
@@ -23,7 +22,6 @@
|
|||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/post.hpp>
|
#include <boost/asio/post.hpp>
|
||||||
#include <boost/asio/prepend.hpp>
|
#include <boost/asio/prepend.hpp>
|
||||||
#include <boost/spirit/home/x3.hpp>
|
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
@@ -155,16 +153,6 @@ class endpoints {
|
|||||||
template <typename Owner, typename Handler>
|
template <typename Owner, typename Handler>
|
||||||
friend class resolve_op;
|
friend class resolve_op;
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static constexpr auto to_(T& arg) {
|
|
||||||
return [&](auto& ctx) { arg = boost::spirit::x3::_attr(ctx); };
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename Parser>
|
|
||||||
static constexpr auto as_(Parser&& p){
|
|
||||||
return boost::spirit::x3::rule<struct _, T>{} = std::forward<Parser>(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename Executor>
|
template <typename Executor>
|
||||||
endpoints(
|
endpoints(
|
||||||
@@ -202,26 +190,25 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void brokers(std::string hosts, uint16_t default_port) {
|
void brokers(std::string hosts, uint16_t default_port) {
|
||||||
namespace x3 = boost::spirit::x3;
|
|
||||||
|
|
||||||
_servers.clear();
|
_servers.clear();
|
||||||
|
|
||||||
std::string host, port, path;
|
|
||||||
|
|
||||||
// loosely based on RFC 3986
|
// loosely based on RFC 3986
|
||||||
auto unreserved_ = x3::char_("-a-zA-Z_0-9._~");
|
for (auto it = hosts.cbegin(), end = hosts.cend(); it != end;) {
|
||||||
auto digit_ = x3::char_("0-9");
|
skip_spaces(it, end);
|
||||||
auto separator_ = x3::char_(',');
|
|
||||||
|
|
||||||
auto host_ = as_<std::string>(+unreserved_)[to_(host)];
|
auto host = std::string(match_while("A-Za-z0-9._~-", it, end));
|
||||||
auto port_ = as_<std::string>(':' >> +digit_)[to_(port)];
|
if (host.empty()) break;
|
||||||
auto path_ = as_<std::string>(+(x3::char_('/') >> *unreserved_))[to_(path)];
|
|
||||||
auto uri_ = *x3::omit[x3::space] >> (host_ >> -port_ >> -path_) >>
|
std::string port;
|
||||||
(*x3::omit[x3::space] >> x3::omit[separator_ | x3::eoi]);
|
if (it < end && *it == ':') {
|
||||||
|
port = std::string(match_while("0-9", ++it, end));
|
||||||
|
if (port.empty()) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string path;
|
||||||
|
if (it < end && *it == '/')
|
||||||
|
path = std::string(match_while("/A-Za-z0-9._~-", it, end));
|
||||||
|
|
||||||
for (auto b = hosts.begin(); b != hosts.end(); ) {
|
|
||||||
host.clear(); port.clear(); path.clear();
|
|
||||||
if (phrase_parse(b, hosts.end(), uri_, x3::eps(false))) {
|
|
||||||
_servers.push_back({
|
_servers.push_back({
|
||||||
std::move(host),
|
std::move(host),
|
||||||
port.empty()
|
port.empty()
|
||||||
@@ -229,11 +216,46 @@ public:
|
|||||||
: std::move(port),
|
: std::move(port),
|
||||||
std::move(path)
|
std::move(path)
|
||||||
});
|
});
|
||||||
}
|
|
||||||
else b = hosts.end();
|
skip_spaces(it, end);
|
||||||
|
if (it == end || *it++ != ',') break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr void skip_spaces(
|
||||||
|
byte_citer& it, const byte_citer& end
|
||||||
|
) {
|
||||||
|
match_while(" \t\r\n\f\v", it, end);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static constexpr std::string_view match_while(
|
||||||
|
const char* chs, byte_citer& it, const byte_citer& end
|
||||||
|
) {
|
||||||
|
if (it == end)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto beg = it;
|
||||||
|
while (it < end && is_any_of(chs, *it)) ++it;
|
||||||
|
|
||||||
|
return { &*beg, static_cast<size_t>(it - beg) };
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr bool is_any_of(const char* chs, char c) {
|
||||||
|
while (*chs)
|
||||||
|
if (*(chs + 1) == '-' && *(chs + 2)) {
|
||||||
|
if (c >= *chs && c <= *(chs + 2))
|
||||||
|
return true;
|
||||||
|
chs += 3;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (c == *chs)
|
||||||
|
return true;
|
||||||
|
++chs;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -21,12 +21,9 @@ set(deps
|
|||||||
container
|
container
|
||||||
core
|
core
|
||||||
endian
|
endian
|
||||||
fusion
|
|
||||||
optional
|
|
||||||
random
|
random
|
||||||
range
|
range
|
||||||
smart_ptr
|
smart_ptr
|
||||||
spirit
|
|
||||||
system
|
system
|
||||||
type_traits
|
type_traits
|
||||||
|
|
||||||
@@ -42,10 +39,11 @@ set(deps
|
|||||||
intrusive
|
intrusive
|
||||||
# logic # Beast dependency
|
# logic # Beast dependency
|
||||||
mp11
|
mp11
|
||||||
|
optional
|
||||||
preprocessor
|
preprocessor
|
||||||
static_assert
|
static_assert
|
||||||
# static_string # Beast dependency
|
# static_string # Beast dependency
|
||||||
type_index
|
# type_index # Beast dependency
|
||||||
winapi
|
winapi
|
||||||
move
|
move
|
||||||
function_types
|
function_types
|
||||||
@@ -64,12 +62,8 @@ set(deps
|
|||||||
iterator
|
iterator
|
||||||
regex
|
regex
|
||||||
"function"
|
"function"
|
||||||
phoenix
|
|
||||||
pool
|
pool
|
||||||
proto
|
|
||||||
thread
|
|
||||||
unordered
|
unordered
|
||||||
variant
|
|
||||||
variant2
|
variant2
|
||||||
describe
|
describe
|
||||||
predef
|
predef
|
||||||
@@ -77,10 +71,8 @@ set(deps
|
|||||||
lexical_cast
|
lexical_cast
|
||||||
numeric/conversion
|
numeric/conversion
|
||||||
tokenizer
|
tokenizer
|
||||||
atomic
|
fusion
|
||||||
chrono
|
|
||||||
exception
|
exception
|
||||||
ratio
|
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach(dep IN LISTS deps)
|
foreach(dep IN LISTS deps)
|
||||||
|
@@ -74,7 +74,7 @@ BOOST_FIXTURE_TEST_CASE(single_host, shared_test_data) {
|
|||||||
BOOST_FIXTURE_TEST_CASE(multiple_hosts, shared_test_data) {
|
BOOST_FIXTURE_TEST_CASE(multiple_hosts, shared_test_data) {
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
// "example.invalid" will not be resolved
|
// "example.invalid" will not be resolved
|
||||||
ep.brokers("127.0.0.1:1001,127.0.0.1/path1, example.invalid, localhost:1002/path1/path-2/path.3_", 1000);
|
ep.brokers("127.0.0.1:1001,127.0.0.1/~path1, example.invalid, localhost:1002/path1/path-2/path.3_", 1000);
|
||||||
|
|
||||||
asio::co_spawn(ioc, [&]() -> asio::awaitable<void> {
|
asio::co_spawn(ioc, [&]() -> asio::awaitable<void> {
|
||||||
for (size_t i = 0; i < 3; ++i) {
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
@@ -90,7 +90,7 @@ BOOST_FIXTURE_TEST_CASE(multiple_hosts, shared_test_data) {
|
|||||||
BOOST_TEST(!eps.empty());
|
BOOST_TEST(!eps.empty());
|
||||||
BOOST_TEST(ap.host == "127.0.0.1");
|
BOOST_TEST(ap.host == "127.0.0.1");
|
||||||
BOOST_TEST(ap.port == "1000");
|
BOOST_TEST(ap.port == "1000");
|
||||||
BOOST_TEST(ap.path == "/path1");
|
BOOST_TEST(ap.path == "/~path1");
|
||||||
|
|
||||||
std::tie(ec, eps, ap) = co_await ep.async_next_endpoint(use_nothrow_awaitable);
|
std::tie(ec, eps, ap) = co_await ep.async_next_endpoint(use_nothrow_awaitable);
|
||||||
BOOST_TEST(ec == success);
|
BOOST_TEST(ec == success);
|
||||||
|
@@ -3,8 +3,7 @@
|
|||||||
"version-semver": "0.0.1",
|
"version-semver": "0.0.1",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"boost-asio",
|
"boost-asio",
|
||||||
"boost-beast",
|
"boost-beast"
|
||||||
"boost-spirit"
|
|
||||||
],
|
],
|
||||||
"default-features": [],
|
"default-features": [],
|
||||||
"features": {
|
"features": {
|
||||||
|
Reference in New Issue
Block a user