FastMM documentation
FastMM C++ API 0.6.0
Public headers, tier 1 and tier 2
Loading...
Searching...
No Matches
strong_id.hpp
Go to the documentation of this file.
1#pragma once
2// Strongly typed identifiers. Mixing an InstrumentId with a VenueId is a compile error.
3#include "fastmm/core/config_macros.hpp"
4#include "fastmm/core/fixed_string.hpp"
5#include "fastmm/core/hex.hpp"
6
7#include <compare>
8#include <cstddef>
9#include <cstdint>
10#include <cstring>
11#include <functional>
12#include <limits>
13#include <optional>
14#include <string_view>
15#include <type_traits>
16
17namespace fastmm {
18
19template <class Tag, class Rep, Rep kInvalid = std::numeric_limits<Rep>::max()>
20struct StrongId {
21 static_assert(std::is_integral_v<Rep>);
22 using rep_type = Rep;
23
24 Rep value = kInvalid;
25
26 constexpr StrongId() noexcept = default;
27 constexpr explicit StrongId(Rep v) noexcept : value(v) {}
28 [[nodiscard]] static constexpr StrongId invalid() noexcept { return StrongId{}; }
29 [[nodiscard]] constexpr bool valid() const noexcept { return value != kInvalid; }
30 [[nodiscard]] constexpr Rep get() const noexcept { return value; }
31 constexpr auto operator<=>(const StrongId&) const noexcept = default;
32};
34// Dense index into the engine's instrument table. All per-instrument state is an array
35// indexed by this.
38// 48-bit: session_epoch(16) << 32 | seq(32). 0 is never issued.
40using VenueOrderId = FixedString<40>;
42using ExecId = FixedString<40>;
44static_assert(std::is_trivially_copyable_v<InstrumentId>);
45static_assert(sizeof(InstrumentId) == 4 && sizeof(VenueId) == 1 && sizeof(ClientOrderId) == 8);
46
47// 32-bit pool index handle. Cheaper than a pointer, stable across relocation of the pool
48// (journals/snapshots), and lets a slot be recycled with a generation check by the owner.
49inline constexpr std::uint32_t kNullHandle = std::numeric_limits<std::uint32_t>::max();
50
51template <class T>
52struct Handle {
53 std::uint32_t idx = kNullHandle;
54 constexpr Handle() noexcept = default;
55 constexpr explicit Handle(std::uint32_t i) noexcept : idx(i) {}
56 [[nodiscard]] constexpr bool valid() const noexcept { return idx != kNullHandle; }
57 constexpr auto operator<=>(const Handle&) const noexcept = default;
58};
60// --- ClientOrderId wire form -------------------------------------------------------------
61// "fm" + 12 lowercase hex digits (48 bits) = 14 chars. Fits Binance (36) and Bybit (36).
62inline constexpr std::size_t kClOrdIdChars = 14;
64// Writes the kClOrdIdChars characters of the wire form to dst (no terminator) with two
65// 8-byte stores.
66FASTMM_FORCE_INLINE void write_cl_ord_id(char* dst, ClientOrderId id) noexcept {
67 const std::uint64_t hi = hex8(static_cast<std::uint32_t>((id.value >> 32) & 0xFFFF));
68 const std::uint64_t lo = hex8(static_cast<std::uint32_t>(id.value));
69 // "fm" + the last 4 characters of hi (its upper 4 bytes); bytes 6 and 7 are then
70 // overwritten by lo.
71 const std::uint64_t head = std::uint64_t{'f'} | (std::uint64_t{'m'} << 8) | ((hi >> 32) << 16);
72 std::memcpy(dst, &head, 8);
73 std::memcpy(dst + 6, &lo, 8);
74}
75
76[[nodiscard]] inline FixedString<16> encode_cl_ord_id(ClientOrderId id) noexcept {
77 FixedString<16> out;
78 write_cl_ord_id(out.data(), id);
79 out.set_size(kClOrdIdChars);
80 return out;
81}
82
83[[nodiscard]] inline std::optional<ClientOrderId> decode_cl_ord_id(std::string_view s) noexcept {
84 if (s.size() != kClOrdIdChars || s[0] != 'f' || s[1] != 'm') return std::nullopt;
85 std::uint64_t v = 0;
86 for (std::size_t i = 2; i < kClOrdIdChars; ++i) {
87 const char c = s[i];
88 unsigned d = 0;
89 if (c >= '0' && c <= '9') {
90 d = static_cast<unsigned>(c - '0');
91 } else if (c >= 'a' && c <= 'f') {
92 d = static_cast<unsigned>(c - 'a') + 10U;
93 } else {
94 return std::nullopt;
95 }
96 v = (v << 4) | d;
97 }
98 if (v == 0) return std::nullopt;
99 return ClientOrderId{v};
100}
101
102[[nodiscard]] constexpr ClientOrderId make_cl_ord_id(std::uint16_t epoch,
103 std::uint32_t seq) noexcept {
104 return ClientOrderId{(static_cast<std::uint64_t>(epoch) << 32) | seq};
105}
106[[nodiscard]] constexpr std::uint16_t cl_ord_id_epoch(ClientOrderId id) noexcept {
107 return static_cast<std::uint16_t>((id.value >> 32) & 0xFFFF);
108}
109[[nodiscard]] constexpr std::uint32_t cl_ord_id_seq(ClientOrderId id) noexcept {
110 return static_cast<std::uint32_t>(id.value & 0xFFFF'FFFFULL);
111}
112
113} // namespace fastmm
114
115template <class Tag, class Rep, Rep I>
116struct std::hash<fastmm::StrongId<Tag, Rep, I>> {
117 std::size_t operator()(const fastmm::StrongId<Tag, Rep, I>& id) const noexcept {
118 return std::hash<Rep>{}(id.value);
119 }
120};
Definition strategy.hpp:16
StrongId< struct ClientOrderTag, std::uint64_t, 0 > ClientOrderId
48-bit: session_epoch(16) << 32 | seq(32). 0 is never issued.
Definition strong_id.hpp:41
constexpr std::uint32_t kNullHandle
32-bit pool index handle.
Definition strong_id.hpp:51
constexpr ClientOrderId make_cl_ord_id(std::uint16_t epoch, std::uint32_t seq) noexcept
Definition strong_id.hpp:103
FixedString< 40 > VenueOrderId
Definition strong_id.hpp:42
constexpr std::size_t kClOrdIdChars
"fm" + 12 lowercase hex digits (48 bits) = 14 chars. Fits Binance (36) and Bybit (36).
Definition strong_id.hpp:63
constexpr std::uint32_t cl_ord_id_seq(ClientOrderId id) noexcept
Definition strong_id.hpp:110
std::optional< ClientOrderId > decode_cl_ord_id(std::string_view s) noexcept
Definition strong_id.hpp:84
StrongId< struct InstrumentTag, std::uint32_t > InstrumentId
Dense index into the engine's instrument table.
Definition strong_id.hpp:38
FASTMM_FORCE_INLINE void write_cl_ord_id(char *dst, ClientOrderId id) noexcept
Writes the kClOrdIdChars characters of the wire form to dst (no terminator) with two 8-byte stores.
Definition strong_id.hpp:67
FixedString< 16 > encode_cl_ord_id(ClientOrderId id) noexcept
Definition strong_id.hpp:77
FixedString< 40 > ExecId
Definition strong_id.hpp:44
constexpr std::uint16_t cl_ord_id_epoch(ClientOrderId id) noexcept
Definition strong_id.hpp:107
Definition strong_id.hpp:54
constexpr bool valid() const noexcept
Definition strong_id.hpp:58
std::uint32_t idx
Definition strong_id.hpp:55
constexpr auto operator<=>(const Handle &) const noexcept=default
constexpr Handle() noexcept=default
Definition strong_id.hpp:22
Rep rep_type
Definition strong_id.hpp:24