More session id work

This commit is contained in:
Kurt Sassenrath 2023-11-06 16:16:04 -08:00
parent 1ceccd0720
commit 578065be47
6 changed files with 141 additions and 4 deletions

View File

@ -27,20 +27,42 @@ namespace parselink {
namespace proto {
struct session_id {
std::array<std::byte, 32> bytes;
public:
session_id() noexcept;
// Not the intended way to build a session id. Ideally, they'll be randomly
// generated.
explicit constexpr session_id(std::array<std::byte, 32> const& v) noexcept {
std::copy(v.begin(), v.end(), bytes_.begin());
}
[[nodiscard]] constexpr auto operator<=>(
session_id const& other) const noexcept {
return bytes <=> other.bytes;
return bytes_ <=> other.bytes_;
}
[[nodiscard]] constexpr auto operator==(
session_id const& other) const noexcept {
return bytes_ == other.bytes_;
}
[[nodiscard]] constexpr auto operator<=>(
std::span<std::byte const> other) const noexcept {
return std::lexicographical_compare_three_way(bytes.begin(),
bytes.end(), other.begin(), other.end(),
return std::lexicographical_compare_three_way(bytes_.begin(),
bytes_.end(), other.begin(), other.end(),
std::compare_three_way());
}
[[nodiscard]] constexpr auto operator==(
std::span<std::byte const> other) const noexcept {
return std::equal(bytes_.begin(), bytes_.end(), other.begin(), other.end());
}
constexpr std::span<std::byte const> raw() const noexcept {
return bytes_;
}
private:
std::array<std::byte, 32> bytes_;
};
} // namespace proto

View File

@ -4,6 +4,7 @@ cc_library(
name = "proto",
srcs = [
"session.cpp",
"session_id.cpp",
],
deps = [
"//include/parselink:proto",

View File

@ -0,0 +1,38 @@
//-----------------------------------------------------------------------------
// ___ __ _ _
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
// / ___/ (_| | | \__ \ __/ /__| | | | | <
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
//
//-----------------------------------------------------------------------------
// Author: Kurt Sassenrath
// Module: proto
//
// Session ID implementation
//
// Copyright (c) 2023 Kurt Sassenrath.
//
// License TBD.
//-----------------------------------------------------------------------------
#include "parselink/proto/session_id.h"
#include "hydrogen.h"
namespace {
void ensure_initialized() {
static auto init_crng [[maybe_unused]] = [] { return hydro_init(); }();
}
template <std::size_t N>
auto get_random_bytes() {
ensure_initialized();
std::array<std::byte, N> out;
hydro_random_buf(out.data(), N);
return out;
}
}
using namespace parselink::proto;
session_id::session_id() noexcept : bytes_(get_random_bytes<32>()) {}

22
tests/proto/BUILD Normal file
View File

@ -0,0 +1,22 @@
cc_library(
name = "test_deps",
srcs = [
"test_main.cpp",
],
deps = [
"//source/proto",
"@expected",
"@fmt",
"@magic_enum",
"@ut",
],
)
cc_test(
name = "session_id",
srcs = [
"test_session_id.cpp",
],
deps = ["test_deps"],
)

View File

@ -0,0 +1,2 @@
int main(int, char**) {}

View File

@ -0,0 +1,52 @@
#include <boost/ut.hpp>
#include <parselink/proto/session_id.h>
#include <set>
namespace {
using namespace boost::ut;
using namespace parselink::proto;
template <typename... Bytes>
constexpr std::array<std::byte, sizeof...(Bytes)> make_bytes(Bytes&&... bytes) {
return {std::byte(std::forward<Bytes>(bytes))...};
}
constexpr std::array<std::byte, 32> null_id_bytes = {};
}
suite session_id_tests = [] {
"test explicitly generated session ids"_test = [] {
constexpr session_id sid1(null_id_bytes);
constexpr session_id sid2(null_id_bytes);
expect(sid1 == sid2);
expect(sid1 == null_id_bytes);
constexpr auto basic_id = make_bytes(
0x0, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f);
constexpr session_id sid3(basic_id);
constexpr session_id sid4(basic_id);
expect(sid3 == sid4);
expect(sid3 == basic_id);
};
"test random generated"_test = [] {
session_id sid1;
session_id sid2;
expect(sid1 != null_id_bytes);
expect(sid2 != null_id_bytes);
expect(sid1 != sid2);
};
"test random generated entropy"_test = [] {
constexpr static std::size_t iter_count = 100000;
std::set<session_id> sessions;
while (sessions.size() < iter_count) {
session_id s;
expect(!sessions.contains(s));
sessions.insert(std::move(s));
}
};
};