LCOV - code coverage report
Current view: top level - include/hpactor/types - types.hpp (source / functions) Coverage Total Hit
Test: HPActor Coverage Lines: 89.4 % 141 126
Test Date: 2026-05-20 02:24:49 Functions: 94.1 % 118 111
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : // Copyright 2026 HPActor Contributors
       2                 :             : //
       3                 :             : // Licensed under the Apache License, Version 2.0 (the "License");
       4                 :             : // you may not use this file except in compliance with the License.
       5                 :             : // You may obtain a copy of the License at
       6                 :             : //
       7                 :             : //     http://www.apache.org/licenses/LICENSE-2.0
       8                 :             : //
       9                 :             : // Unless required by applicable law or agreed to in writing, software
      10                 :             : // distributed under the License is distributed on an "AS IS" BASIS,
      11                 :             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12                 :             : // See the License for the specific language governing permissions and
      13                 :             : // limitations under the License.
      14                 :             : 
      15                 :             : #pragma once
      16                 :             : 
      17                 :             : #include <arpa/inet.h>
      18                 :             : #include <array>
      19                 :             : #include <atomic>
      20                 :             : #include <chrono>
      21                 :             : #include <cstdint>
      22                 :             : #include <cstring>
      23                 :             : #include <netinet/in.h>
      24                 :             : #include <string>
      25                 :             : #include <string_view>
      26                 :             : #include <variant>
      27                 :             : #include <vector>
      28                 :             : 
      29                 :             : #include <hpactor/adt/id.hpp>
      30                 :             : #include <hpactor/adt/stream_buffer.hpp>
      31                 :             : #include <hpactor/adt/tags.hpp>
      32                 :             : #include <vector>
      33                 :             : 
      34                 :             : namespace hpactor {
      35                 :             : 
      36                 :             : // constexpr network-to-host byte-order conversion (ntohs is not constexpr)
      37                 :         183 : inline constexpr uint16_t net_to_host_u16(uint16_t net_val) noexcept {
      38                 :             : #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
      39                 :         183 :     return __builtin_bswap16(net_val);
      40                 :             : #else
      41                 :             :     return net_val;
      42                 :             : #endif
      43                 :             : }
      44                 :             : 
      45                 :             : // -----------------------------------------------------------------------------
      46                 :             : // ActorId - unique identifier for an actor instance
      47                 :             : // -----------------------------------------------------------------------------
      48                 :             : using ActorId = Id<ActorTag>;
      49                 :             : 
      50                 :             : // -----------------------------------------------------------------------------
      51                 :             : // Protocol - network protocol family
      52                 :             : // -----------------------------------------------------------------------------
      53                 :             : enum class Protocol { IPv4, IPv6 };
      54                 :             : 
      55                 :             : // -----------------------------------------------------------------------------
      56                 :             : // DispatchPolicy — how an actor is dispatched to a scheduler worker
      57                 :             : // -----------------------------------------------------------------------------
      58                 :             : enum class DispatchPolicy : uint8_t {
      59                 :             :     Cooperative = 0,
      60                 :             :     DedicatedThread,
      61                 :             :     DedicatedPool,
      62                 :             : };
      63                 :             : 
      64                 :             : // -----------------------------------------------------------------------------
      65                 :             : // Ipv4Endpoint - IPv4 address and port (network byte order)
      66                 :             : // -----------------------------------------------------------------------------
      67                 :             : struct Ipv4Endpoint {
      68                 :             :     uint32_t addr;    // Network byte order (big-endian)
      69                 :             :     uint16_t port_nw; // Network byte order
      70                 :             : 
      71                 :         130 :     constexpr Ipv4Endpoint() noexcept : addr(0), port_nw(0) {}
      72                 :     1243724 :     constexpr Ipv4Endpoint(uint32_t a, uint16_t p) noexcept
      73                 :     1243724 :         : addr(a), port_nw(p) {}
      74                 :             : 
      75                 :         179 :     [[nodiscard]] constexpr uint16_t port() const noexcept {
      76                 :         179 :         return net_to_host_u16(port_nw);
      77                 :             :     }
      78                 :           1 :     [[nodiscard]] constexpr bool is_ipv4() const noexcept {
      79                 :           1 :         return true;
      80                 :             :     }
      81                 :           1 :     [[nodiscard]] constexpr bool is_ipv6() const noexcept {
      82                 :           1 :         return false;
      83                 :             :     }
      84                 :             :     [[nodiscard]] constexpr bool is_loopback() const noexcept;
      85                 :             :     [[nodiscard]] constexpr bool is_private_network() const noexcept;
      86                 :             :     [[nodiscard]] constexpr bool is_unspecified() const noexcept;
      87                 :             : 
      88                 :             :     // For socket operations
      89                 :             :     constexpr socklen_t sockaddr_length() const noexcept {
      90                 :             :         return sizeof(sockaddr_in);
      91                 :             :     }
      92                 :             :     void to_sockaddr(sockaddr_in* out) const noexcept;
      93                 :             : 
      94                 :         132 :     constexpr bool operator==(const Ipv4Endpoint& other) const noexcept {
      95                 :         132 :         return addr == other.addr && port_nw == other.port_nw;
      96                 :             :     }
      97                 :           1 :     constexpr bool operator!=(const Ipv4Endpoint& other) const noexcept {
      98                 :           1 :         return !(*this == other);
      99                 :             :     }
     100                 :             : };
     101                 :             : 
     102                 :          39 : [[nodiscard]] constexpr bool Ipv4Endpoint::is_loopback() const noexcept {
     103                 :             :     // Network byte order: 127.0.0.1 = 0x7F000001
     104                 :             :     // MSB (byte 0 in network order) = 0x7F
     105                 :             :     // On little-endian, addr value is still 0x7F000001, so MSB = (addr >> 24)
     106                 :             :     // On big-endian, MSB = (addr >> 24) = 0x7F
     107                 :             :     // Both give same result
     108                 :          39 :     return (addr >> 24) == 0x7F;
     109                 :             : }
     110                 :             : 
     111                 :           4 : [[nodiscard]] constexpr bool Ipv4Endpoint::is_private_network() const noexcept {
     112                 :           4 :     auto b1 = static_cast<uint8_t>((addr >> 24) & 0xFF);
     113                 :           4 :     uint32_t rest = addr & 0xFFFF0000;
     114                 :           5 :     return b1 == 10 || (b1 == 172 && ((addr >> 16) & 0xFF & 0xF0) == 0x10) ||
     115                 :           5 :            (b1 == 192 && rest == 0xC0A80000);
     116                 :             : }
     117                 :             : 
     118                 :           0 : [[nodiscard]] constexpr bool Ipv4Endpoint::is_unspecified() const noexcept {
     119                 :           0 :     return addr == 0;
     120                 :             : }
     121                 :             : 
     122                 :           1 : inline void Ipv4Endpoint::to_sockaddr(sockaddr_in* out) const noexcept {
     123                 :           1 :     out->sin_family = AF_INET;
     124                 :           1 :     out->sin_port = port_nw;
     125                 :           1 :     out->sin_addr.s_addr = addr;
     126                 :           1 :     std::memset(out->sin_zero, 0, sizeof(out->sin_zero));
     127                 :           1 : }
     128                 :             : 
     129                 :             : // -----------------------------------------------------------------------------
     130                 :             : // Ipv6Endpoint - IPv6 address and port (network byte order)
     131                 :             : // -----------------------------------------------------------------------------
     132                 :             : struct Ipv6Endpoint {
     133                 :             :     std::array<uint8_t, 16> addr; // Network byte order
     134                 :             :     uint16_t port_nw;             // Network byte order
     135                 :             : 
     136                 :             :     constexpr Ipv6Endpoint() noexcept : addr{}, port_nw(0) {}
     137                 :           5 :     constexpr Ipv6Endpoint(std::array<uint8_t, 16> a, uint16_t p) noexcept
     138                 :           5 :         : addr(a), port_nw(p) {}
     139                 :             : 
     140                 :           4 :     [[nodiscard]] constexpr uint16_t port() const noexcept {
     141                 :           4 :         return net_to_host_u16(port_nw);
     142                 :             :     }
     143                 :           1 :     [[nodiscard]] constexpr bool is_ipv4() const noexcept {
     144                 :           1 :         return false;
     145                 :             :     }
     146                 :           1 :     [[nodiscard]] constexpr bool is_ipv6() const noexcept {
     147                 :           1 :         return true;
     148                 :             :     }
     149                 :             :     [[nodiscard]] bool is_loopback() const noexcept;
     150                 :             :     [[nodiscard]] bool is_private_network() const noexcept;
     151                 :             :     [[nodiscard]] bool is_unspecified() const noexcept;
     152                 :             : 
     153                 :             :     // For socket operations
     154                 :             :     constexpr socklen_t sockaddr_length() const noexcept {
     155                 :             :         return sizeof(sockaddr_in6);
     156                 :             :     }
     157                 :             :     void to_sockaddr(sockaddr_in6* out) const noexcept;
     158                 :             : 
     159                 :           0 :     bool operator==(const Ipv6Endpoint& other) const noexcept {
     160                 :           0 :         return addr == other.addr && port_nw == other.port_nw;
     161                 :             :     }
     162                 :           0 :     bool operator!=(const Ipv6Endpoint& other) const noexcept {
     163                 :           0 :         return !(*this == other);
     164                 :             :     }
     165                 :             : };
     166                 :             : 
     167                 :           3 : inline bool Ipv6Endpoint::is_loopback() const noexcept {
     168                 :          48 :     for (std::size_t i = 0; i < 15; ++i)
     169                 :          45 :         if (addr[i] != 0)
     170                 :           0 :             return false;
     171                 :           3 :     return addr[15] == 1;
     172                 :             : }
     173                 :             : 
     174                 :             : inline bool Ipv6Endpoint::is_private_network() const noexcept {
     175                 :             :     return (addr[0] & 0xFE) == 0xFC;
     176                 :             : }
     177                 :             : 
     178                 :             : inline bool Ipv6Endpoint::is_unspecified() const noexcept {
     179                 :             :     for (std::size_t i = 0; i < 16; ++i)
     180                 :             :         if (addr[i] != 0)
     181                 :             :             return false;
     182                 :             :     return true;
     183                 :             : }
     184                 :             : 
     185                 :           1 : inline void Ipv6Endpoint::to_sockaddr(sockaddr_in6* out) const noexcept {
     186                 :           1 :     out->sin6_family = AF_INET6;
     187                 :           1 :     out->sin6_port = port_nw;
     188                 :           1 :     std::memcpy(out->sin6_addr.s6_addr, addr.data(), 16);
     189                 :           1 :     out->sin6_flowinfo = 0;
     190                 :           1 :     out->sin6_scope_id = 0;
     191                 :           1 : }
     192                 :             : 
     193                 :             : // -----------------------------------------------------------------------------
     194                 :             : // EndPoint - variant over IPv4/IPv6
     195                 :             : // -----------------------------------------------------------------------------
     196                 :             : using EndPoint = std::variant<Ipv4Endpoint, Ipv6Endpoint>;
     197                 :             : 
     198                 :             : // -----------------------------------------------------------------------------
     199                 :             : // LocalEndpoint - loopback endpoint for local actor communication
     200                 :             : // -----------------------------------------------------------------------------
     201                 :             : inline constexpr Ipv4Endpoint LocalEndpoint{0x7F000001, 0}; // 127.0.0.1:0 in
     202                 :             :                                                             // network byte
     203                 :             :                                                             // order
     204                 :             : 
     205                 :             : // to_sockaddr free function for variant
     206                 :             : inline void to_sockaddr(const EndPoint& ep, sockaddr* out, socklen_t* len) {
     207                 :             :     if (auto* ipv4 = std::get_if<Ipv4Endpoint>(&ep)) {
     208                 :             :         if (*len >= sizeof(sockaddr_in)) {
     209                 :             :             ipv4->to_sockaddr(reinterpret_cast<sockaddr_in*>(out));
     210                 :             :             *len = sizeof(sockaddr_in);
     211                 :             :         }
     212                 :             :     } else if (auto* ipv6 = std::get_if<Ipv6Endpoint>(&ep)) {
     213                 :             :         if (*len >= sizeof(sockaddr_in6)) {
     214                 :             :             ipv6->to_sockaddr(reinterpret_cast<sockaddr_in6*>(out));
     215                 :             :             *len = sizeof(sockaddr_in6);
     216                 :             :         }
     217                 :             :     }
     218                 :             : }
     219                 :             : 
     220                 :             : // -----------------------------------------------------------------------------
     221                 :             : // EndPoint operations (implemented in cpp)
     222                 :             : // -----------------------------------------------------------------------------
     223                 :             : namespace endpoint_ops {
     224                 :             : [[nodiscard]] Protocol protocol(const EndPoint& ep);
     225                 :             : [[nodiscard]] int address_family(const EndPoint& ep);
     226                 :             : [[nodiscard]] std::string to_string(const EndPoint& ep);
     227                 :             : [[nodiscard]] EndPoint parse_endpoint(std::string_view node_id);
     228                 :             : } // namespace endpoint_ops
     229                 :             : 
     230                 :             : // -----------------------------------------------------------------------------
     231                 :             : // ActorType - type identifier for an actor
     232                 :             : // -----------------------------------------------------------------------------
     233                 :             : using ActorType = uint32_t;
     234                 :             : constexpr ActorType InvalidActorType = 0;
     235                 :             : 
     236                 :             : // -----------------------------------------------------------------------------
     237                 :             : // incarnation_type - version counter for actor lifecycle
     238                 :             : // -----------------------------------------------------------------------------
     239                 :             : using incarnation_type = uint64_t;
     240                 :             : 
     241                 :             : // -----------------------------------------------------------------------------
     242                 :             : // MessageId - unique identifier for a message
     243                 :             : // -----------------------------------------------------------------------------
     244                 :             : using MessageId = Id<MessageTag>;
     245                 :             : 
     246                 :          17 : inline MessageId generate_message_id() {
     247                 :             :     static std::atomic<uint64_t> next_id_{1};
     248                 :          17 :     return MessageId(next_id_.fetch_add(1));
     249                 :             : }
     250                 :             : 
     251                 :             : // -----------------------------------------------------------------------------
     252                 :             : // error - error code wrapper (no exceptions in hot path)
     253                 :             : // -----------------------------------------------------------------------------
     254                 :             : class error {
     255                 :             :   public:
     256                 :        1077 :     error() = default;
     257                 :             : 
     258                 :          62 :     explicit error(uint32_t code, std::string msg = {})
     259                 :          62 :         : code_(code), message_(std::move(msg)) {}
     260                 :             : 
     261                 :           9 :     uint32_t code() const {
     262                 :           9 :         return code_;
     263                 :             :     }
     264                 :           2 :     const std::string& message() const {
     265                 :           2 :         return message_;
     266                 :             :     }
     267                 :             : 
     268                 :           4 :     bool ok() const {
     269                 :           4 :         return code_ == 0;
     270                 :             :     }
     271                 :           2 :     explicit operator bool() const {
     272                 :           2 :         return !ok();
     273                 :             :     }
     274                 :             : 
     275                 :             :   private:
     276                 :             :     uint32_t code_ = 0;
     277                 :             :     std::string message_;
     278                 :             : };
     279                 :             : 
     280                 :             : // -----------------------------------------------------------------------------
     281                 :             : // errors namespace - canonical error codes
     282                 :             : // -----------------------------------------------------------------------------
     283                 :             : namespace errors {
     284                 :             : constexpr uint32_t unknown = 1;
     285                 :             : constexpr uint32_t actor_down = 2;
     286                 :             : constexpr uint32_t actor_not_found = 3;
     287                 :             : constexpr uint32_t mailbox_full = 4;
     288                 :             : constexpr uint32_t timeout = 5;
     289                 :             : constexpr uint32_t invalid_argument = 6;
     290                 :             : 
     291                 :             : // HTTP protocol errors
     292                 :             : constexpr uint32_t http_parse_error = 2001;
     293                 :             : constexpr uint32_t http_connect_failed = 2002;
     294                 :             : constexpr uint32_t http_timeout = 2003;
     295                 :             : 
     296                 :             : constexpr uint32_t user = 1000;
     297                 :             : } // namespace errors
     298                 :             : 
     299                 :             : // -----------------------------------------------------------------------------
     300                 :             : // result<T> - return type for message handlers
     301                 :             : // -----------------------------------------------------------------------------
     302                 :             : template <typename T> class result {
     303                 :             :   public:
     304                 :         167 :     static result<T> make(T&& value) {
     305                 :         167 :         return result<T>(std::move(value));
     306                 :             :     }
     307                 :          18 :     static result<T> make(class error err) {
     308                 :          18 :         return result<T>(std::move(err));
     309                 :             :     }
     310                 :             : 
     311                 :         165 :     bool has_value() const {
     312                 :         165 :         return has_value_;
     313                 :             :     }
     314                 :         168 :     T& value() {
     315                 :         168 :         return std::get<0>(value_);
     316                 :             :     }
     317                 :           8 :     const class error& error() const {
     318                 :           8 :         return std::get<1>(value_);
     319                 :             :     }
     320                 :             : 
     321                 :             :   private:
     322                 :         167 :     result(T&& val) : has_value_(true), value_(std::move(val)) {}
     323                 :          18 :     result(class error err) : has_value_(false), value_(err) {}
     324                 :             : 
     325                 :             :     bool has_value_;
     326                 :             :     std::variant<T, class error> value_;
     327                 :             : };
     328                 :             : 
     329                 :             : template <> class result<void> {
     330                 :             :   public:
     331                 :        1069 :     static result<void> make() {
     332                 :        1069 :         return result<void>();
     333                 :             :     }
     334                 :           3 :     static result<void> make(class error err) {
     335                 :           3 :         return result<void>(std::move(err));
     336                 :             :     }
     337                 :             : 
     338                 :         957 :     bool has_value() const {
     339                 :         957 :         return has_value_;
     340                 :             :     }
     341                 :             :     void value() const {} // No-op for void
     342                 :           2 :     const class error& error() const {
     343                 :           2 :         return error_;
     344                 :             :     }
     345                 :             : 
     346                 :             :   private:
     347                 :        1069 :     result() : has_value_(true) {}
     348                 :           3 :     result(class error err) : has_value_(false), error_(std::move(err)) {}
     349                 :             : 
     350                 :             :     bool has_value_;
     351                 :             :     class error error_;
     352                 :             : };
     353                 :             : 
     354                 :             : // -----------------------------------------------------------------------------
     355                 :             : // Clock - for time-based operations
     356                 :             : // -----------------------------------------------------------------------------
     357                 :             : class Clock {
     358                 :             :   public:
     359                 :             :     using time_point = std::chrono::steady_clock::time_point;
     360                 :             :     using duration = std::chrono::milliseconds;
     361                 :          33 :     time_point now() const {
     362                 :          33 :         return std::chrono::steady_clock::now();
     363                 :             :     }
     364                 :             : };
     365                 :             : 
     366                 :             : // -----------------------------------------------------------------------------
     367                 :             : // AlarmHandle - opaque handle for alarms
     368                 :             : // -----------------------------------------------------------------------------
     369                 :             : using AlarmHandle = Id<AlarmTag>;
     370                 :             : 
     371                 :             : // -----------------------------------------------------------------------------
     372                 :             : // Trace identifiers - W3C/OpenTelemetry-compatible distributed tracing IDs
     373                 :             : // -----------------------------------------------------------------------------
     374                 :             : struct TraceId {
     375                 :             :     std::array<uint8_t, 16> bytes{};
     376                 :             : 
     377                 :          24 :     bool valid() const noexcept {
     378                 :         164 :         for (uint8_t b : bytes) {
     379                 :         159 :             if (b != 0) {
     380                 :          19 :                 return true;
     381                 :             :             }
     382                 :             :         }
     383                 :           5 :         return false;
     384                 :             :     }
     385                 :             : 
     386                 :           5 :     bool operator==(const TraceId& other) const noexcept {
     387                 :           5 :         return bytes == other.bytes;
     388                 :             :     }
     389                 :             : };
     390                 :             : 
     391                 :             : struct SpanId {
     392                 :             :     std::array<uint8_t, 8> bytes{};
     393                 :             : 
     394                 :          21 :     bool valid() const noexcept {
     395                 :          69 :         for (uint8_t b : bytes) {
     396                 :          67 :             if (b != 0) {
     397                 :          19 :                 return true;
     398                 :             :             }
     399                 :             :         }
     400                 :           2 :         return false;
     401                 :             :     }
     402                 :             : 
     403                 :           3 :     bool operator==(const SpanId& other) const noexcept {
     404                 :           3 :         return bytes == other.bytes;
     405                 :             :     }
     406                 :             : };
     407                 :             : 
     408                 :             : struct TraceFlags {
     409                 :             :     static constexpr uint8_t kSampled = 0x01;
     410                 :             : 
     411                 :             :     uint8_t value = 0;
     412                 :             : 
     413                 :          10 :     bool sampled() const noexcept {
     414                 :          10 :         return (value & kSampled) != 0;
     415                 :             :     }
     416                 :             : 
     417                 :           8 :     void set_sampled(bool enabled) noexcept {
     418                 :           8 :         if (enabled) {
     419                 :           7 :             value = static_cast<uint8_t>(value | kSampled);
     420                 :             :         } else {
     421                 :           1 :             value = static_cast<uint8_t>(value & ~kSampled);
     422                 :             :         }
     423                 :           8 :     }
     424                 :             : };
     425                 :             : 
     426                 :             : struct TraceContext {
     427                 :             :     TraceId trace_id;
     428                 :             :     SpanId span_id;
     429                 :             :     TraceFlags flags;
     430                 :             :     uint8_t version = 0;
     431                 :             :     uint16_t tracestate_len = 0;
     432                 :             :     std::array<char, 256> tracestate{};
     433                 :             : 
     434                 :          13 :     bool valid() const noexcept {
     435                 :          13 :         return trace_id.valid() && span_id.valid();
     436                 :             :     }
     437                 :             : 
     438                 :          10 :     bool sampled() const noexcept {
     439                 :          10 :         return flags.sampled();
     440                 :             :     }
     441                 :             : 
     442                 :           2 :     std::string_view tracestate_view() const noexcept {
     443                 :           2 :         return {tracestate.data(), tracestate_len};
     444                 :             :     }
     445                 :             : 
     446                 :           4 :     void clear() noexcept {
     447                 :           4 :         trace_id = TraceId{};
     448                 :           4 :         span_id = SpanId{};
     449                 :           4 :         flags = TraceFlags{};
     450                 :           4 :         version = 0;
     451                 :           4 :         tracestate_len = 0;
     452                 :           4 :         tracestate.fill('\0');
     453                 :           4 :     }
     454                 :             : };
     455                 :             : 
     456                 :             : // -----------------------------------------------------------------------------
     457                 :             : // StreamBuffer - byte buffer type
     458                 :             : // -----------------------------------------------------------------------------
     459                 :             : using adt::StreamBuffer;
     460                 :             : 
     461                 :             : // -----------------------------------------------------------------------------
     462                 :             : // TypeTag - type identifier for serialization (replaces RTTI)
     463                 :             : //
     464                 :             : // Range layout:
     465                 :             : //   0x00000000 – 0x000000FF   System messages (256 slots)
     466                 :             : //   0x00000100 – 0x00000FFF   Reserved for future system expansion
     467                 :             : //   0x00001000 – 0x00FFFFFF   Application-defined messages (~16M slots)
     468                 :             : //
     469                 :             : // System sub-ranges:
     470                 :             : //   0x00 – 0x0F   Core system (lifecycle: Down, Exit, Link, Unlink, Monitor,
     471                 :             : //   Demonitor) 0x10 – 0x1F   Spawn protocol (SpawnRequest, SpawnResponse,
     472                 :             : //   Error) 0x20 – 0x2F   HTTP protocol (HttpRequest, HttpResponse) 0x30 – 0x3F
     473                 :             : //   TOML bootstrap (SystemInit) 0x40 – 0x4F   Metrics (MetricsRequest,
     474                 :             : //   MetricsResponse) 0x50 – 0x5F   CLI interactive (Inspect, Kill, List, Stats)
     475                 :             : //   0x60 – 0x6F   Async I/O (IoCompletion)
     476                 :             : //   0x70 – 0xFF   Reserved for future system use
     477                 :             : //
     478                 :             : // Application sub-ranges (examples):
     479                 :             : //   0x00001000 – 0x00001FFF   Auth subsystem
     480                 :             : //   0x00002000 – 0x00002FFF   Chat subsystem
     481                 :             : //   0x00003000 – 0x00003FFF   Database subsystem
     482                 :             : //   ...
     483                 :             : // -----------------------------------------------------------------------------
     484                 :             : enum class TypeTag : uint32_t {
     485                 :             :     // ---- System message range
     486                 :             :     // ------------------------------------------------
     487                 :             :     Invalid = 0x00000000,
     488                 :             : 
     489                 :             :     // Core system (0x00 – 0x0F)
     490                 :             :     DownMsg = 0x01,
     491                 :             :     ExitMsg = 0x02,
     492                 :             :     LinkMsg = 0x03,
     493                 :             :     UnlinkMsg = 0x04,
     494                 :             :     MonitorMsg = 0x0A,
     495                 :             :     DemonitorMsg = 0x0B,
     496                 :             : 
     497                 :             :     // Spawn protocol (0x10 – 0x1F)
     498                 :             :     SpawnRequestTag = 0x10,
     499                 :             :     SpawnResponseTag = 0x11,
     500                 :             :     ErrorMsg = 0x12,
     501                 :             : 
     502                 :             :     // HTTP protocol (0x20 – 0x2F)
     503                 :             :     HttpRequestTag = 0x20,
     504                 :             :     HttpResponseTag = 0x21,
     505                 :             : 
     506                 :             :     // TOML config bootstrapping (0x30 – 0x3F)
     507                 :             :     SystemInitTag = 0x30,
     508                 :             : 
     509                 :             :     // Metrics subsystem (0x40 – 0x4F)
     510                 :             :     MetricsRequestTag = 0x40,
     511                 :             :     MetricsResponseTag = 0x41,
     512                 :             : 
     513                 :             :     // CLI interactive subsystem (0x50 – 0x5F)
     514                 :             :     InspectStateRequestTag = 0x50,
     515                 :             :     InspectStateResponseTag = 0x51,
     516                 :             :     KillRequestTag = 0x52,
     517                 :             :     KillResponseTag = 0x53,
     518                 :             :     ListActorsRequestTag = 0x54,
     519                 :             :     ListActorsResponseTag = 0x55,
     520                 :             :     SystemStatsRequestTag = 0x56,
     521                 :             :     SystemStatsResponseTag = 0x57,
     522                 :             :     MemoryStatsRequestTag = 0x58,
     523                 :             :     MemoryStatsResponseTag = 0x59,
     524                 :             :     TopologyShowRequestTag = 0x5A,
     525                 :             :     TopologyShowResponseTag = 0x5B,
     526                 :             :     TopologyRestartRequestTag = 0x5C,
     527                 :             :     TopologyRestartResponseTag = 0x5D,
     528                 :             : 
     529                 :             :     // Async I/O (0x60 – 0x6F)
     530                 :             :     IoCompletionTag = 0x60,
     531                 :             : 
     532                 :             :     // Backpressure control (0x70 – 0x7F)
     533                 :             :     BackpressureSignalTag = 0x70,
     534                 :             : 
     535                 :             :     // ---- Application range
     536                 :             :     // ---------------------------------------------------
     537                 :             :     User = 0x00001000,
     538                 :             : };
     539                 :             : 
     540                 :             : } // namespace hpactor
     541                 :             : 
     542                 :             : // -----------------------------------------------------------------------------
     543                 :             : // std::hash specializations (must be in namespace std)
     544                 :             : // -----------------------------------------------------------------------------
     545                 :             : template <> struct std::hash<hpactor::Ipv4Endpoint> {
     546                 :         112 :     std::size_t operator()(const hpactor::Ipv4Endpoint& ep) const noexcept {
     547                 :         112 :         std::size_t h = std::hash<uint32_t>{}(ep.addr);
     548                 :         112 :         h ^= std::hash<uint16_t>{}(ep.port()) + 0x9e3779b9 + (h << 6) + (h >> 2);
     549                 :         112 :         return h;
     550                 :             :     }
     551                 :             : };
     552                 :             : 
     553                 :             : template <> struct std::hash<hpactor::Ipv6Endpoint> {
     554                 :           0 :     std::size_t operator()(const hpactor::Ipv6Endpoint& ep) const noexcept {
     555                 :           0 :         std::size_t h = 0;
     556                 :           0 :         for (uint8_t b : ep.addr) {
     557                 :           0 :             h ^= std::hash<uint8_t>{}(b) + 0x9e3779b9 + (h << 6) + (h >> 2);
     558                 :             :         }
     559                 :           0 :         h ^= std::hash<uint16_t>{}(ep.port()) + 0x9e3779b9 + (h << 6) + (h >> 2);
     560                 :           0 :         return h;
     561                 :             :     }
     562                 :             : };
     563                 :             : 
     564                 :             : template <> struct std::hash<hpactor::EndPoint> {
     565                 :         110 :     std::size_t operator()(const hpactor::EndPoint& ep) const noexcept {
     566                 :         110 :         if (auto* ipv4 = std::get_if<hpactor::Ipv4Endpoint>(&ep)) {
     567                 :         110 :             return std::hash<hpactor::Ipv4Endpoint>{}(*ipv4);
     568                 :             :         }
     569                 :           0 :         return std::hash<hpactor::Ipv6Endpoint>{}(
     570                 :           0 :             std::get<hpactor::Ipv6Endpoint>(ep));
     571                 :             :     }
     572                 :             : };
        

Generated by: LCOV version 2.0-1