diff --git a/include/snipplib/network/snplib_netmsg.h b/include/snipplib/network/snplib_netmsg.h index a5c4cb9..51094c3 100644 --- a/include/snipplib/network/snplib_netmsg.h +++ b/include/snipplib/network/snplib_netmsg.h @@ -35,6 +35,7 @@ protected: public: using typename base_t::config_t; + using result_t = std::expected; keyval_netmsg_t(base_t::config_t config = {.keyval_delim = SNPLIB_DEFAULT_NETMSG_KEYVALUE_DELIM, .valseq_delim = SNPLIB_DEFAULT_NETMSG_VALUEVALUE_DELIM}) @@ -52,27 +53,25 @@ public: ~keyval_netmsg_t() = default; template - static keyval_netmsg_t fromBytes(R&& r, - base_t::config_t config = {.keyval_delim = SNPLIB_DEFAULT_NETMSG_KEYVALUE_DELIM, - .valseq_delim = SNPLIB_DEFAULT_NETMSG_VALUEVALUE_DELIM}) + static result_t fromBytes(R&& r, + base_t::config_t config = {.keyval_delim = SNPLIB_DEFAULT_NETMSG_KEYVALUE_DELIM, + .valseq_delim = SNPLIB_DEFAULT_NETMSG_VALUEVALUE_DELIM}) { keyval_netmsg_t msg; // deep copy if constexpr (std::same_as>) { std::ranges::copy(std::forward(r), std::back_inserter(msg._ownByteSeq)); - msg.fromCharRange(msg._ownByteSeq, std::move(config)); + return msg.fromCharRange(msg._ownByteSeq, std::move(config)); } else { - msg.fromCharRange(std::forward(r), std::move(config)); + return msg.fromCharRange(std::forward(r), std::move(config)); } - - return msg; } // to satisfy net_message_c-concept - static keyval_netmsg_t fromBytes(std::span r, - base_t::config_t config = {.keyval_delim = SNPLIB_DEFAULT_NETMSG_KEYVALUE_DELIM, - .valseq_delim = SNPLIB_DEFAULT_NETMSG_VALUEVALUE_DELIM}) + static result_t fromBytes(std::span r, + base_t::config_t config = {.keyval_delim = SNPLIB_DEFAULT_NETMSG_KEYVALUE_DELIM, + .valseq_delim = SNPLIB_DEFAULT_NETMSG_VALUEVALUE_DELIM}) { return keyval_netmsg_t::fromBytes(r, std::move(config)); } diff --git a/include/snipplib/network/snplib_netproto.h b/include/snipplib/network/snplib_netproto.h index 5ccbf6b..d215669 100644 --- a/include/snipplib/network/snplib_netproto.h +++ b/include/snipplib/network/snplib_netproto.h @@ -2,6 +2,7 @@ #include "../concepts/snplib_concepts.h" #include "../utils/snplib_string.h" +#include "snipplib/network/snplib_network.h" /* @@ -119,23 +120,36 @@ struct netproto_stopseq_t { } } + // deduces a view-type from the input range-type template auto fromBytes(IR&& bytes) requires input_char_range_c> { - using or_t = std::conditional_t, std::span, - std::ranges::subrange>>; + using or_t = + std::conditional_t, std::span, + std::ranges::subrange, std::ranges::sentinel_t>>; return fromBytes(std::forward(bytes)); } + + // to satisfy 'net_proto_c' concept + template + requires(std::same_as || std::same_as) + std::expected, std::error_code> fromBytes(std::span bytes) + { + return fromBytes>(bytes); + } }; +static_assert(net_proto_c>, "!!!"); + + /* BINARY BLOB PROTOCOL */ /* * a sequence of bytes in format: - * + * * blob size field: a symbolic representation of a HEXIMAL UNSIGNED INTEGER (e.g. "000000FA", MUST BE IN UPPER-CASE!!!) diff --git a/include/snipplib/network/snplib_network.h b/include/snipplib/network/snplib_network.h index 0ad517a..72bd567 100644 --- a/include/snipplib/network/snplib_network.h +++ b/include/snipplib/network/snplib_network.h @@ -29,15 +29,23 @@ concept net_proto_c = requires(T t) { // from session-level representation to transport-level one { t.toBytes(std::declval()) } -> char_range_or_range_of_char_ranges_c; + // from transport-level representation to session-level one requires( requires { - { t.fromBytes(std::declval>()) } -> char_range_c; + // { t.fromBytes(std::declval>()) } -> char_range_c; + { t.fromBytes(std::declval>()) } -> ret_expected_c; + requires char_range_c().fromBytes(std::declval>()).value())>>; } || requires { - { t.fromBytes(std::declval>()) } -> char_range_c; + // { t.fromBytes(std::declval>()) } -> char_range_c; + { t.fromBytes(std::declval>()) } -> ret_expected_c; + requires char_range_c< + std::remove_cvref_t().fromBytes(std::declval>()).value())>>; }); }; + template concept net_message_c = requires(const T t_const) { // { t.toBytes() } -> char_range_or_range_of_char_ranges_c; @@ -46,10 +54,12 @@ concept net_message_c = requires(const T t_const) { // can be constructed from contiguous byte range requires( requires { - { T::fromBytes(std::declval>()) } -> std::same_as; + // { T::fromBytes(std::declval>()) } -> std::same_as; + { T::fromBytes(std::declval>()) } -> ret_expected_type_c; } || requires { - { T::fromBytes(std::declval>()) } -> std::same_as; + // { T::fromBytes(std::declval>()) } -> std::same_as; + { T::fromBytes(std::declval>()) } -> ret_expected_type_c; }); }; @@ -101,9 +111,9 @@ concept net_listener_c = requires(T t, const T t_const) { { t.accept() } -> async_retval_c; - { t.startListen() } -> ret_error_c; + { t.startListening() } -> ret_error_c; - t.stopListen(); + t.stopListening(); { t_const.endpoint() } -> net_endpoint_c; }; @@ -116,7 +126,7 @@ concept net_initiator_role_c = requires { []() { [[maybe_unused]] static constexpr std::array arr{// server role (listener of connections) T::ROLE_SERVER, - // cleant role (opener of connections) + // client role (opener of connections) T::ROLE_CLIENT}; }(); }; @@ -128,8 +138,10 @@ enum class net_initiator_role_e : int { ROLE_SERVER, ROLE_CLIENT }; template concept net_initiator_c = requires(T t, const T t_const) { - // common part + // common part: + // must contain a static compile-time constant 'ROLE' of type satisfied to 'net_initiator_role_c' concept requires net_initiator_role_c; + // to be sure 'ROLE' is compile-time constant []() { [[maybe_unused]] static constexpr auto val = T::ROLE; }(); net_connection_c; @@ -139,9 +151,9 @@ concept net_initiator_c = // server-role { t.accept() } -> async_retval_c; - { t.startListen() } -> ret_error_c; + { t.startListening() } -> ret_error_c; - t.stopListen(); + t.stopListening(); }) && ((T::ROLE != decltype(T::ROLE)::ROLE_CLIENT) || requires(T t) { // use of short-circuiting logic!!! // client-role { t.open() } -> async_retval_c;