...
This commit is contained in:
@@ -35,6 +35,7 @@ protected:
|
||||
|
||||
public:
|
||||
using typename base_t::config_t;
|
||||
using result_t = std::expected<keyval_netmsg_t, typename base_t::error_t>;
|
||||
|
||||
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 <char_range_c R>
|
||||
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<CharRangeT, std::remove_cvref_t<R>>) {
|
||||
std::ranges::copy(std::forward<R>(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>(r), std::move(config));
|
||||
return msg.fromCharRange(std::forward<R>(r), std::move(config));
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
// to satisfy net_message_c-concept
|
||||
static keyval_netmsg_t fromBytes(std::span<const char> 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<const char> 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));
|
||||
}
|
||||
|
||||
@@ -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 <typename IR>
|
||||
auto fromBytes(IR&& bytes)
|
||||
requires input_char_range_c<std::remove_cvref_t<IR>>
|
||||
{
|
||||
using or_t = std::conditional_t<std::ranges::contiguous_range<IR>, std::span<const char>,
|
||||
std::ranges::subrange<std::ranges::iterator_t<IR>>>;
|
||||
using or_t =
|
||||
std::conditional_t<std::ranges::contiguous_range<IR>, std::span<const char>,
|
||||
std::ranges::subrange<std::ranges::iterator_t<IR>, std::ranges::sentinel_t<IR>>>;
|
||||
|
||||
return fromBytes<or_t>(std::forward<IR>(bytes));
|
||||
}
|
||||
|
||||
// to satisfy 'net_proto_c' concept
|
||||
template <typename CharT = char>
|
||||
requires(std::same_as<CharT, char> || std::same_as<CharT, const char>)
|
||||
std::expected<std::span<CharT>, std::error_code> fromBytes(std::span<CharT> bytes)
|
||||
{
|
||||
return fromBytes<std::span<CharT>>(bytes);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static_assert(net_proto_c<netproto_stopseq_t<>>, "!!!");
|
||||
|
||||
|
||||
/* BINARY BLOB PROTOCOL */
|
||||
|
||||
/*
|
||||
* a sequence of bytes in format:
|
||||
* <blob size field><bynary blob bytes>
|
||||
* <blob size field><binary blob bytes>
|
||||
*
|
||||
blob size field: a symbolic representation of a HEXIMAL UNSIGNED INTEGER (e.g. "000000FA", MUST BE IN
|
||||
UPPER-CASE!!!)
|
||||
|
||||
@@ -29,15 +29,23 @@ concept net_proto_c = requires(T t) {
|
||||
// from session-level representation to transport-level one
|
||||
{ t.toBytes(std::declval<CharRangeT>()) } -> char_range_or_range_of_char_ranges_c;
|
||||
|
||||
// from transport-level representation to session-level one
|
||||
requires(
|
||||
requires {
|
||||
{ t.fromBytes(std::declval<std::span<const char>>()) } -> char_range_c;
|
||||
// { t.fromBytes(std::declval<std::span<const char>>()) } -> char_range_c;
|
||||
{ t.fromBytes(std::declval<std::span<const char>>()) } -> ret_expected_c;
|
||||
requires char_range_c<std::remove_cvref_t<
|
||||
decltype(std::declval<T>().fromBytes(std::declval<std::span<const char>>()).value())>>;
|
||||
} ||
|
||||
requires {
|
||||
{ t.fromBytes(std::declval<std::span<char>>()) } -> char_range_c;
|
||||
// { t.fromBytes(std::declval<std::span<char>>()) } -> char_range_c;
|
||||
{ t.fromBytes(std::declval<std::span<char>>()) } -> ret_expected_c;
|
||||
requires char_range_c<
|
||||
std::remove_cvref_t<decltype(std::declval<T>().fromBytes(std::declval<std::span<char>>()).value())>>;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
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::span<const char>>()) } -> std::same_as<T>;
|
||||
// { T::fromBytes(std::declval<std::span<const char>>()) } -> std::same_as<T>;
|
||||
{ T::fromBytes(std::declval<std::span<const char>>()) } -> ret_expected_type_c<T>;
|
||||
} ||
|
||||
requires {
|
||||
{ T::fromBytes(std::declval<std::span<char>>()) } -> std::same_as<T>;
|
||||
// { T::fromBytes(std::declval<std::span<char>>()) } -> std::same_as<T>;
|
||||
{ T::fromBytes(std::declval<std::span<char>>()) } -> ret_expected_type_c<T>;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -101,9 +111,9 @@ concept net_listener_c = requires(T t, const T t_const) {
|
||||
|
||||
{ t.accept() } -> async_retval_c<typename T::connection_t>;
|
||||
|
||||
{ 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 <typename T>
|
||||
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<decltype(T::ROLE)>;
|
||||
// to be sure 'ROLE' is compile-time constant
|
||||
[]() { [[maybe_unused]] static constexpr auto val = T::ROLE; }();
|
||||
|
||||
net_connection_c<typename T::connection_t>;
|
||||
@@ -139,9 +151,9 @@ concept net_initiator_c =
|
||||
// server-role
|
||||
{ t.accept() } -> async_retval_c<typename T::connection_t>;
|
||||
|
||||
{ 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<typename T::connection_t>;
|
||||
|
||||
Reference in New Issue
Block a user