...
This commit is contained in:
@@ -35,6 +35,7 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
using typename base_t::config_t;
|
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,
|
keyval_netmsg_t(base_t::config_t config = {.keyval_delim = SNPLIB_DEFAULT_NETMSG_KEYVALUE_DELIM,
|
||||||
.valseq_delim = SNPLIB_DEFAULT_NETMSG_VALUEVALUE_DELIM})
|
.valseq_delim = SNPLIB_DEFAULT_NETMSG_VALUEVALUE_DELIM})
|
||||||
@@ -52,7 +53,7 @@ public:
|
|||||||
~keyval_netmsg_t() = default;
|
~keyval_netmsg_t() = default;
|
||||||
|
|
||||||
template <char_range_c R>
|
template <char_range_c R>
|
||||||
static keyval_netmsg_t fromBytes(R&& r,
|
static result_t fromBytes(R&& r,
|
||||||
base_t::config_t config = {.keyval_delim = SNPLIB_DEFAULT_NETMSG_KEYVALUE_DELIM,
|
base_t::config_t config = {.keyval_delim = SNPLIB_DEFAULT_NETMSG_KEYVALUE_DELIM,
|
||||||
.valseq_delim = SNPLIB_DEFAULT_NETMSG_VALUEVALUE_DELIM})
|
.valseq_delim = SNPLIB_DEFAULT_NETMSG_VALUEVALUE_DELIM})
|
||||||
{
|
{
|
||||||
@@ -61,16 +62,14 @@ public:
|
|||||||
// deep copy
|
// deep copy
|
||||||
if constexpr (std::same_as<CharRangeT, std::remove_cvref_t<R>>) {
|
if constexpr (std::same_as<CharRangeT, std::remove_cvref_t<R>>) {
|
||||||
std::ranges::copy(std::forward<R>(r), std::back_inserter(msg._ownByteSeq));
|
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 {
|
} 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
|
// to satisfy net_message_c-concept
|
||||||
static keyval_netmsg_t fromBytes(std::span<const char> r,
|
static result_t fromBytes(std::span<const char> r,
|
||||||
base_t::config_t config = {.keyval_delim = SNPLIB_DEFAULT_NETMSG_KEYVALUE_DELIM,
|
base_t::config_t config = {.keyval_delim = SNPLIB_DEFAULT_NETMSG_KEYVALUE_DELIM,
|
||||||
.valseq_delim = SNPLIB_DEFAULT_NETMSG_VALUEVALUE_DELIM})
|
.valseq_delim = SNPLIB_DEFAULT_NETMSG_VALUEVALUE_DELIM})
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "../concepts/snplib_concepts.h"
|
#include "../concepts/snplib_concepts.h"
|
||||||
#include "../utils/snplib_string.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>
|
template <typename IR>
|
||||||
auto fromBytes(IR&& bytes)
|
auto fromBytes(IR&& bytes)
|
||||||
requires input_char_range_c<std::remove_cvref_t<IR>>
|
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>,
|
using or_t =
|
||||||
std::ranges::subrange<std::ranges::iterator_t<IR>>>;
|
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));
|
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 */
|
/* BINARY BLOB PROTOCOL */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* a sequence of bytes in format:
|
* 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
|
blob size field: a symbolic representation of a HEXIMAL UNSIGNED INTEGER (e.g. "000000FA", MUST BE IN
|
||||||
UPPER-CASE!!!)
|
UPPER-CASE!!!)
|
||||||
|
|||||||
@@ -29,15 +29,23 @@ concept net_proto_c = requires(T t) {
|
|||||||
// from session-level representation to transport-level one
|
// from session-level representation to transport-level one
|
||||||
{ t.toBytes(std::declval<CharRangeT>()) } -> char_range_or_range_of_char_ranges_c;
|
{ t.toBytes(std::declval<CharRangeT>()) } -> char_range_or_range_of_char_ranges_c;
|
||||||
|
|
||||||
|
// from transport-level representation to session-level one
|
||||||
requires(
|
requires(
|
||||||
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 {
|
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>
|
template <typename T>
|
||||||
concept net_message_c = requires(const T t_const) {
|
concept net_message_c = requires(const T t_const) {
|
||||||
// { t.toBytes() } -> char_range_or_range_of_char_ranges_c;
|
// { 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
|
// can be constructed from contiguous byte range
|
||||||
requires(
|
requires(
|
||||||
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 {
|
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.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;
|
{ 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)
|
[[maybe_unused]] static constexpr std::array arr{// server role (listener of connections)
|
||||||
T::ROLE_SERVER,
|
T::ROLE_SERVER,
|
||||||
// cleant role (opener of connections)
|
// client role (opener of connections)
|
||||||
T::ROLE_CLIENT};
|
T::ROLE_CLIENT};
|
||||||
}();
|
}();
|
||||||
};
|
};
|
||||||
@@ -128,8 +138,10 @@ enum class net_initiator_role_e : int { ROLE_SERVER, ROLE_CLIENT };
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
concept net_initiator_c =
|
concept net_initiator_c =
|
||||||
requires(T t, const T t_const) {
|
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)>;
|
requires net_initiator_role_c<decltype(T::ROLE)>;
|
||||||
|
// to be sure 'ROLE' is compile-time constant
|
||||||
[]() { [[maybe_unused]] static constexpr auto val = T::ROLE; }();
|
[]() { [[maybe_unused]] static constexpr auto val = T::ROLE; }();
|
||||||
|
|
||||||
net_connection_c<typename T::connection_t>;
|
net_connection_c<typename T::connection_t>;
|
||||||
@@ -139,9 +151,9 @@ concept net_initiator_c =
|
|||||||
// server-role
|
// server-role
|
||||||
{ t.accept() } -> async_retval_c<typename T::connection_t>;
|
{ 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!!!
|
}) && ((T::ROLE != decltype(T::ROLE)::ROLE_CLIENT) || requires(T t) { // use of short-circuiting logic!!!
|
||||||
// client-role
|
// client-role
|
||||||
{ t.open() } -> async_retval_c<typename T::connection_t>;
|
{ t.open() } -> async_retval_c<typename T::connection_t>;
|
||||||
|
|||||||
Reference in New Issue
Block a user