2#include "gaia/config/config.h"
10#include "gaia/core/span.h"
11#include "gaia/core/utility.h"
12#include "gaia/ecs/chunk_allocator.h"
13#include "gaia/ecs/component.h"
14#include "gaia/mem/data_layout_policy.h"
15#include "gaia/mem/mem_utils.h"
16#include "gaia/meta/reflection.h"
17#include "gaia/meta/type_info.h"
18#include "gaia/ser/ser_rt.h"
19#include "gaia/util/str.h"
24 enum class RuntimeTypeKind : uint8_t {
46 enum class RuntimeJsonEncoding : uint8_t {
55 inline constexpr uint32_t RuntimeDescriptionMaxLength = 1024;
58 using RuntimeFieldFlagsType = uint16_t;
60 enum RuntimeFieldFlags : RuntimeFieldFlagsType {
62 RuntimeFieldFlag_None = 0,
64 RuntimeFieldFlag_ReadOnly = 1u << 0,
66 RuntimeFieldFlag_Hidden = 1u << 1,
68 RuntimeFieldFlag_Multiline = 1u << 2,
70 RuntimeFieldFlag_HasMinimum = 1u << 3,
72 RuntimeFieldFlag_HasMaximum = 1u << 4,
74 RuntimeFieldFlag_HasStep = 1u << 5
84 GAIA_NODISCARD
constexpr bool valid() const noexcept {
85 return value != UINT32_MAX;
91 return value == other.value;
97 return value != other.value;
103 template <
typename StringType>
119 RuntimeJsonEncoding jsonEncoding = RuntimeJsonEncoding::Default;
122 RuntimeFieldFlagsType
flags = RuntimeFieldFlag_None;
138 using RuntimeFieldInit = RuntimeFieldMeta<util::str_view>;
140 using RuntimeFieldDesc = RuntimeFieldMeta<SymbolId>;
144 template <
typename StringType>
156 using RuntimeConstantInit = RuntimeConstantMeta<util::str_view>;
158 using RuntimeConstantDesc = RuntimeConstantMeta<SymbolId>;
242 RuntimeTypeKind
typeKind = RuntimeTypeKind::Struct;
247 RuntimeJsonEncoding jsonEncoding = RuntimeJsonEncoding::Default;
283 using FuncFrom = void(
void*,
void*, uint32_t, uint32_t, uint32_t, uint32_t);
285 using FuncCopy = void(
void*,
const void*, uint32_t, uint32_t, uint32_t, uint32_t);
287 using FuncMove = void(
void*,
void*, uint32_t, uint32_t, uint32_t, uint32_t);
289 using FuncSwap = void(
void*,
void*, uint32_t, uint32_t, uint32_t, uint32_t);
291 using FuncCmp = bool(
const void*,
const void*);
339 template <
typename T>
342 using CT = component_type_t<T>;
344 using U =
typename component_type_t<T>::Type;
346 using DescU =
typename CT::TypeFull;
360 return meta::type_info::name<DescU>();
365 static constexpr uint32_t
size() {
366 if constexpr (std::is_empty_v<U>)
369 return (uint32_t)
sizeof(
U);
376 static constexpr uint32_t
alig() {
381 "Table component alignment can't exceed MemoryBlockAlignment");
383 storage_type() != DataStorageType::Sparse ||
alig <=
alignof(std::max_align_t),
384 "Sparse component alignment can't exceed alignof(std::max_align_t)");
391 static uint32_t
soa(std::span<uint8_t, meta::StructToTupleMaxTypes> soaSizes) {
392 if constexpr (mem::is_soa_layout_v<U>) {
394 using TTuple =
decltype(meta::struct_to_tuple(std::declval<U>()));
396 constexpr auto TTupleSize = std::tuple_size_v<TTuple>;
397 static_assert(TTupleSize > 0);
398 static_assert(TTupleSize <= meta::StructToTupleMaxTypes);
399 core::each_tuple<TTuple>([&](
auto&& item) {
400 static_assert(
sizeof(item) <= 255,
"Each member of a SoA component can be at most 255 B long!");
401 soaSizes[i] = (uint8_t)
sizeof(item);
404 GAIA_ASSERT(i <= meta::StructToTupleMaxTypes);
415 constexpr auto storageType = auto_storage_policy_v<U>;
416 if constexpr (storageType == DataStorageType::DontFragment) {
418 !mem::is_soa_layout_v<U>,
"GAIA_STORAGE(DontFragment) is not compatible with SoA layouts");
419 if constexpr (std::is_empty_v<U>)
420 return DataStorageType::Table;
422 return DataStorageType::Sparse;
425 storageType == DataStorageType::Table || storageType == DataStorageType::Sparse,
426 "Unsupported component storage type");
428 storageType != DataStorageType::Sparse || !std::is_empty_v<U>,
429 "GAIA_STORAGE(Sparse) requires a non-empty component payload");
431 storageType != DataStorageType::Sparse || !mem::is_soa_layout_v<U>,
432 "GAIA_STORAGE(Sparse) is not compatible with SoA layouts");
440 if constexpr (!mem::is_soa_layout_v<U> && !std::is_trivially_constructible_v<U>) {
441 return [](
void* ptr, uint32_t cnt) {
442 core::call_ctor_n((
U*)ptr, cnt);
452 if constexpr (!mem::is_soa_layout_v<U> && !std::is_trivially_destructible_v<U>) {
453 return [](
void* ptr, uint32_t cnt) {
454 core::call_dtor_n((
U*)ptr, cnt);
464 return [](
void* GAIA_RESTRICT dst,
const void* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
465 uint32_t sizeDst, uint32_t sizeSrc) {
466 mem::copy_ctor_element<U>((uint8_t*)dst, (
const uint8_t*)src, idxDst, idxSrc, sizeDst, sizeSrc);
473 return [](
void* GAIA_RESTRICT dst,
void* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
474 uint32_t sizeDst, uint32_t sizeSrc) {
475 mem::move_ctor_element<U>((uint8_t*)dst, (uint8_t*)src, idxDst, idxSrc, sizeDst, sizeSrc);
482 return [](
void* GAIA_RESTRICT dst,
const void* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
483 uint32_t sizeDst, uint32_t sizeSrc) {
484 mem::copy_element<U>((uint8_t*)dst, (
const uint8_t*)src, idxDst, idxSrc, sizeDst, sizeSrc);
491 return [](
void* GAIA_RESTRICT dst,
void* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
492 uint32_t sizeDst, uint32_t sizeSrc) {
493 mem::move_element<U>((uint8_t*)dst, (uint8_t*)src, idxDst, idxSrc, sizeDst, sizeSrc);
500 return [](
void* GAIA_RESTRICT left,
void* GAIA_RESTRICT right, uint32_t idxLeft, uint32_t idxRight,
501 uint32_t sizeLeft, uint32_t sizeRight) {
502 mem::swap_elements<U>((uint8_t*)left, (uint8_t*)right, idxLeft, idxRight, sizeLeft, sizeRight);
509 if constexpr (mem::is_soa_layout_v<U>) {
510 return []([[maybe_unused]]
const void* left, [[maybe_unused]]
const void* right) {
511 GAIA_ASSERT(
false &&
"func_cmp for SoA not implemented yet");
517 if constexpr (hasGlobalCmp || hasMemberCmp) {
518 return [](
const void* left,
const void* right) {
519 const auto* l = (
const U*)left;
520 const auto* r = (
const U*)right;
525 return [](
const void* left,
const void* right) {
526 const auto* l = (
const U*)left;
527 const auto* r = (
const U*)right;
528 return memcmp(l, r,
sizeof(
U)) == 0;
537 return [](
ser::serializer& s,
const void* pSrc, uint32_t from, uint32_t to, uint32_t cap) {
538 const auto* pComponent = (
const U*)pSrc;
540#if GAIA_ASSERT_ENABLED
542 s.check(*pComponent);
545 if constexpr (mem::is_soa_layout_v<U>) {
547 GAIA_FOR2(from, to) {
553 GAIA_FOR2(from, to) {
564 return [](
ser::serializer& s,
void* pDst, uint32_t from, uint32_t to, uint32_t cap) {
565 if constexpr (mem::is_soa_layout_v<U>) {
567 GAIA_FOR2(from, to) {
573 auto* pComponent = (
U*)pDst + from;
574 GAIA_FOR2(from, to) {
582#if GAIA_ECS_AUTO_COMPONENT_FIELDS
587 template <
typename Field>
588 static Entity auto_field_type() noexcept {
589 using FU = core::raw_t<Field>;
590 if constexpr (std::is_same_v<FU, bool>)
592 else if constexpr (std::is_same_v<FU, char>)
594 else if constexpr (std::is_arithmetic_v<FU>)
595 return runtime_primitive_type_entity(ser::type_id<FU>());
603 static uint32_t auto_fields(std::span<RuntimeFieldInit, meta::StructToTupleMaxTypes> fields) {
604 using Raw = core::raw_t<T>;
605 if constexpr (std::is_empty_v<Raw> || mem::is_soa_layout_v<Raw>) {
607 }
else if constexpr (!std::is_class_v<Raw>) {
608 const auto fieldType = auto_field_type<Raw>();
609 if (fieldType == EntityBad)
613 }
else if constexpr (!std::is_aggregate_v<Raw>) {
617 const auto* pBase =
reinterpret_cast<const uint8_t*
>(&tmp);
618 static constexpr const char* FieldNames[meta::StructToTupleMaxTypes] = {
619 "f0",
"f1",
"f2",
"f3",
"f4",
"f5",
"f6",
"f7",
"f8",
"f9",
"f10",
"f11",
"f12",
"f13",
"f14"};
620 uint32_t fieldCount = 0;
621 meta::each_member(tmp, [&](
auto&... members) {
622 auto add_field = [&](
auto& member) {
623 using Field = core::raw_t<
decltype(member)>;
624 const auto fieldType = auto_field_type<Field>();
625 if (fieldType == EntityBad)
627 GAIA_ASSERT(fieldCount < meta::StructToTupleMaxTypes);
628 const auto* pField =
reinterpret_cast<const uint8_t*
>(&member);
629 const auto offset = (uint32_t)(pField - pBase);
630 const auto* fieldName = FieldNames[fieldCount];
631 const auto fieldNameLen = (uint32_t)GAIA_STRLEN(fieldName, 4);
632 fields[fieldCount] = {util::str_view(fieldName, fieldNameLen), fieldType, offset, 0};
635 (add_field(members), ...);
648 static ecs::ComponentDesc
651 desc.
name = descName;
655 desc.soa =
soa(soaSizes);
656 desc.pSoaSizes = soaSizes.data();
Detects whether T supports a free operator==.
Definition utility.h:775
Detects whether T defines operator== as a member function.
Definition utility.h:767
Plain component registration descriptor shared by typed and runtime component paths....
Definition component_desc.h:277
void(void *, uint32_t) FuncDtor
Component destructor callback for a contiguous range of payload slots.
Definition component_desc.h:281
FuncCopy * funcCopyCtor
Optional copy-constructor callback. Runtime byte-only components leave this null.
Definition component_desc.h:319
FuncSwap * funcSwap
Optional swap callback. Runtime byte-only components leave this null.
Definition component_desc.h:327
FuncCopy * funcCopy
Optional copy-assignment callback. Runtime byte-only components leave this null.
Definition component_desc.h:323
FuncCtor * funcCtor
Optional constructor callback. Runtime byte-only components leave this null.
Definition component_desc.h:315
const uint8_t * pSoaSizes
Per-element SoA sizes when soa is non-zero. The array must contain soa non-zero entries and their sum...
Definition component_desc.h:309
bool(const void *, const void *) FuncCmp
Component equality callback for comparing two payload values.
Definition component_desc.h:291
FuncSave * funcSave
Optional typed serialization save callback. Semantic runtime JSON uses field metadata instead.
Definition component_desc.h:331
FuncMove * funcMove
Optional move-assignment callback. Runtime byte-only components leave this null.
Definition component_desc.h:325
void(ser::serializer &, const void *, uint32_t, uint32_t, uint32_t) FuncSave
Component serializer callback for typed component save operations.
Definition component_desc.h:293
uint32_t soa
Number of SoA elements, 0 means AoS.
Definition component_desc.h:306
DataStorageType storageType
Component storage mode.
Definition component_desc.h:304
RuntimeTypeDesc runtimeType
Runtime reflection metadata copied during registration.
Definition component_desc.h:313
void(void *, const void *, uint32_t, uint32_t, uint32_t, uint32_t) FuncCopy
Component copy callback used by typed registration and storage moves.
Definition component_desc.h:285
void(void *, void *, uint32_t, uint32_t, uint32_t, uint32_t) FuncSwap
Component swap callback used by storage operations that exchange payload ranges.
Definition component_desc.h:289
void(ser::serializer &, void *, uint32_t, uint32_t, uint32_t) FuncLoad
Component serializer callback for typed component load operations.
Definition component_desc.h:295
uint32_t alig
Component payload alignment in bytes.
Definition component_desc.h:302
void(void *, uint32_t) FuncCtor
Component constructor callback for a contiguous range of payload slots.
Definition component_desc.h:279
void(void *, void *, uint32_t, uint32_t, uint32_t, uint32_t) FuncFrom
Component migration callback used when copying or moving from one layout stride to another.
Definition component_desc.h:283
uint32_t size
Component payload size in bytes.
Definition component_desc.h:300
FuncCmp * funcCmp
Optional equality callback. Runtime byte-only components leave this null.
Definition component_desc.h:329
ComponentLookupHash hashLookup
Optional explicit lookup hash. When empty, the symbol hash is used.
Definition component_desc.h:311
void(void *, void *, uint32_t, uint32_t, uint32_t, uint32_t) FuncMove
Component move callback used by typed registration and storage moves.
Definition component_desc.h:287
FuncMove * funcMoveCtor
Optional move-constructor callback. Runtime byte-only components leave this null.
Definition component_desc.h:317
FuncLoad * funcLoad
Optional typed serialization load callback. Semantic runtime JSON uses field metadata instead.
Definition component_desc.h:333
FuncDtor * funcDtor
Optional destructor callback. Runtime byte-only components leave this null.
Definition component_desc.h:321
util::str_view name
Registered component symbol.
Definition component_desc.h:298
static constexpr uint32_t MaxAlignment
Largest component alignment storable.
Definition id.h:55
Identifier of an entity or component instance in the world. Packs the entity index,...
Definition id.h:231
Callback table for opaque runtime values with adapter-owned physical storage.
Definition component_desc.h:228
void * ctx
User context passed to all callbacks.
Definition component_desc.h:230
bool(* project)(void *, const RuntimeOpaqueScope &, RuntimeOpaqueValue &)
Projects an opaque value to its semantic runtime type. Required for traversal.
Definition component_desc.h:232
bool(* commit)(void *, RuntimeOpaqueScope &, RuntimeOpaqueValue &)
Commits a projected semantic value after cursor writes. Optional for direct projections....
Definition component_desc.h:235
Runtime opaque adapter input scope. The physical byte layout is owned by the adapter.
Definition component_desc.h:202
const void * data
Read-only opaque payload or handle bytes.
Definition component_desc.h:206
Entity type
Opaque runtime type entity for the selected value.
Definition component_desc.h:204
void * mutData
Mutable opaque payload or handle bytes. Null for read-only traversal.
Definition component_desc.h:208
uint32_t size
Size of the opaque payload or handle bytes.
Definition component_desc.h:210
Semantic value projected from opaque runtime storage.
Definition component_desc.h:214
void * token
Adapter-owned projection token.
Definition component_desc.h:224
uint32_t size
Size of projected semantic bytes.
Definition component_desc.h:222
void * mutData
Mutable projected semantic bytes. Null for read-only traversal.
Definition component_desc.h:220
Entity type
Semantic runtime type entity for projected bytes. EntityBad uses opaqueAsType.
Definition component_desc.h:216
const void * data
Read-only projected semantic bytes.
Definition component_desc.h:218
Callback table for adapter-owned dynamic sequence values.
Definition component_desc.h:187
bool(* count)(void *, const RuntimeSequenceScope &, uint32_t &)
Reads the dynamic element count. Required for traversal.
Definition component_desc.h:191
bool(* commitElement)(void *, RuntimeSequenceScope &, RuntimeSequenceElement &)
Commits a projected element after cursor writes. Optional for direct element pointers....
Definition component_desc.h:198
bool(* element)(void *, const RuntimeSequenceScope &, uint32_t, RuntimeSequenceElement &)
Selects one element by index. Required for traversal.
Definition component_desc.h:193
bool(* resize)(void *, RuntimeSequenceScope &, uint32_t)
Resizes the sequence. Optional. Required for JSON load into dynamic sequences.
Definition component_desc.h:195
void * ctx
User context passed to all callbacks.
Definition component_desc.h:189
Runtime sequence element returned by an adapter.
Definition component_desc.h:173
Entity type
Runtime type entity for the selected element value.
Definition component_desc.h:175
uint32_t size
Size of the selected element bytes.
Definition component_desc.h:181
void * token
Adapter-owned token for projected elements.
Definition component_desc.h:183
void * mutData
Mutable element bytes. Null for read-only traversal.
Definition component_desc.h:179
const void * data
Read-only element bytes.
Definition component_desc.h:177
Runtime sequence adapter input scope. The byte layout is owned by the adapter.
Definition component_desc.h:161
void * mutData
Mutable sequence payload or handle bytes. Null for read-only traversal.
Definition component_desc.h:167
const void * data
Read-only sequence payload or handle bytes.
Definition component_desc.h:165
uint32_t size
Size of the selected sequence payload or handle bytes.
Definition component_desc.h:169
Entity type
Runtime type entity for the selected sequence value.
Definition component_desc.h:163
Runtime reflection metadata embedded in a component descriptor or supplied to typed registration....
Definition component_desc.h:240
Entity underlyingType
Primitive storage type for enum/bitmask metadata. EntityBad otherwise.
Definition component_desc.h:250
Entity semantic
Optional named entity identifying the authored semantic.
Definition component_desc.h:244
const RuntimeOpaqueAdapter * opaqueAdapter
Optional adapter for opaque semantic projections. The callback table must outlive the registration.
Definition component_desc.h:268
const RuntimeConstantInit * constants
Runtime constant initializers copied during registration.
Definition component_desc.h:256
const RuntimeFieldInit * fields
Runtime field initializers copied during registration.
Definition component_desc.h:252
uint32_t fieldCount
Number of field initializers.
Definition component_desc.h:254
uint32_t constantCount
Number of constant initializers.
Definition component_desc.h:258
Entity elementType
Element type for fixed array or dynamic vector metadata.
Definition component_desc.h:260
const RuntimeSequenceAdapter * sequenceAdapter
Optional adapter for dynamic sequence metadata. The callback table must outlive the registration.
Definition component_desc.h:266
RuntimeTypeKind typeKind
Runtime reflection type kind.
Definition component_desc.h:242
util::str_view description
Optional human-readable explanation of the type, copied during registration. Shorter than RuntimeDesc...
Definition component_desc.h:271
Entity opaqueAsType
Semantic runtime type exposed by opaque metadata. EntityBad otherwise.
Definition component_desc.h:264
uint32_t elementCount
Fixed element count for array metadata. 0 otherwise.
Definition component_desc.h:262
Interned component-cache symbol identifier.
Definition component_desc.h:78
GAIA_NODISCARD constexpr bool operator!=(SymbolId other) const noexcept
Compares two interned identifiers for inequality.
Definition component_desc.h:96
GAIA_NODISCARD constexpr bool valid() const noexcept
Checks whether the identifier refers to an interned string.
Definition component_desc.h:84
uint32_t value
Zero-based index in the owning component cache symbol table, or UINT32_MAX when unset.
Definition component_desc.h:80
GAIA_NODISCARD constexpr bool operator==(SymbolId other) const noexcept
Compares two interned identifiers.
Definition component_desc.h:90
Compile-time adapter that converts typed component metadata into a plain ComponentDesc.
Definition component_desc.h:340
static constexpr auto func_dtor()
Builds the optional destructor callback for typed AoS payloads.
Definition component_desc.h:451
static constexpr auto func_move_ctor()
Builds the move-constructor callback used when typed payload storage grows or migrates.
Definition component_desc.h:472
static constexpr auto func_copy()
Builds the copy-assignment callback used for typed payload writes.
Definition component_desc.h:481
typename CT::TypeFull DescU
Fully-qualified component type used for stable symbol/hash generation.
Definition component_desc.h:346
typename component_type_t< T >::Type U
Stored C++ payload type.
Definition component_desc.h:344
static constexpr uint32_t alig()
Returns the payload alignment required by the component storage policy. Table columns are aligned wit...
Definition component_desc.h:376
static constexpr auto func_ctor()
Builds the optional constructor callback for typed AoS payloads.
Definition component_desc.h:439
static constexpr auto func_load()
Builds the serializer load callback for typed payload values.
Definition component_desc.h:563
static constexpr uint32_t size()
Returns the payload size stored in chunks.
Definition component_desc.h:365
component_type_t< T > CT
Reflected Gaia component type wrapper.
Definition component_desc.h:342
static ecs::ComponentDesc make(util::str_view descName, std::span< uint8_t, meta::StructToTupleMaxTypes > soaSizes)
Builds the plain descriptor used by component cache registration.
Definition component_desc.h:649
static constexpr auto func_cmp()
Builds the equality comparison callback for typed payload values.
Definition component_desc.h:508
static uint32_t soa(std::span< uint8_t, meta::StructToTupleMaxTypes > soaSizes)
Populates SoA element sizes for SoA payloads.
Definition component_desc.h:391
static constexpr auto func_copy_ctor()
Builds the copy-constructor callback used when typed payload storage grows or migrates.
Definition component_desc.h:463
static constexpr auto func_save()
Builds the serializer save callback for typed payload values.
Definition component_desc.h:536
static constexpr ComponentLookupHash hash_lookup()
Returns the stable lookup hash for the component type. The constexpr local forces compile-time evalua...
Definition component_desc.h:352
static constexpr auto func_swap()
Builds the swap callback used by storage operations.
Definition component_desc.h:499
static constexpr DataStorageType storage_type()
Returns the compile-time storage mode requested for the component payload. GAIA_STORAGE(DontFragment)...
Definition component_desc.h:414
static constexpr auto name()
Returns the reflected component symbol name.
Definition component_desc.h:359
static constexpr auto func_move()
Builds the move-assignment callback used for typed payload writes.
Definition component_desc.h:490
Read-only view for a selected layout and item type.
Definition data_layout_policy.h:127
Mutable view for a selected layout and item type.
Definition data_layout_policy.h:132
Storage policy for a selected layout and item type.
Definition data_layout_policy.h:121
Runtime serializer type-erased handle. Traversal logic is shared with compile-time serialization,...
Definition ser_rt.h:94
void load(T &arg)
Deserializes a value through generic traversal.
Definition ser_rt.h:126
void save(const T &arg)
Serializes a value through generic traversal.
Definition ser_rt.h:115
Lightweight non-owning string view over a character sequence.
Definition str.h:13
GAIA_NODISCARD constexpr uint32_t size() const
Returns the number of characters in the view.
Definition str.h:42