This commit is contained in:
2026-09-29 17:58:14 +03:00
parent f7d57f3997
commit 47c6d39569
3 changed files with 48 additions and 23 deletions

View File

@@ -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));
}

View File

@@ -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!!!)

View File

@@ -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>;