2#include "gaia/config/config.h"
9#include "gaia/core/span.h"
10#include "gaia/core/utility.h"
11#include "gaia/ecs/component.h"
12#include "gaia/mem/data_layout_policy.h"
13#include "gaia/mem/mem_utils.h"
14#include "gaia/meta/reflection.h"
15#include "gaia/meta/type_info.h"
16#include "gaia/ser/ser_rt.h"
17#include "gaia/util/str.h"
22 enum class RuntimeTypeKind : uint8_t {
44 enum class RuntimeJsonEncoding : uint8_t {
53 using RuntimeFieldFlagsType = uint16_t;
55 enum RuntimeFieldFlags : RuntimeFieldFlagsType {
57 RuntimeFieldFlag_None = 0,
59 RuntimeFieldFlag_ReadOnly = 1u << 0,
61 RuntimeFieldFlag_Hidden = 1u << 1,
63 RuntimeFieldFlag_Multiline = 1u << 2,
65 RuntimeFieldFlag_HasMinimum = 1u << 3,
67 RuntimeFieldFlag_HasMaximum = 1u << 4,
69 RuntimeFieldFlag_HasStep = 1u << 5
79 GAIA_NODISCARD
constexpr bool valid() const noexcept {
80 return value != UINT32_MAX;
86 return value == other.value;
92 return value != other.value;
98 template <
typename StringType>
114 RuntimeJsonEncoding jsonEncoding = RuntimeJsonEncoding::Default;
117 RuntimeFieldFlagsType
flags = RuntimeFieldFlag_None;
136 template <
typename StringType>
231 RuntimeTypeKind
typeKind = RuntimeTypeKind::Struct;
236 RuntimeJsonEncoding jsonEncoding = RuntimeJsonEncoding::Default;
269 using FuncFrom = void(
void*,
void*, uint32_t, uint32_t, uint32_t, uint32_t);
271 using FuncCopy = void(
void*,
const void*, uint32_t, uint32_t, uint32_t, uint32_t);
273 using FuncMove = void(
void*,
void*, uint32_t, uint32_t, uint32_t, uint32_t);
275 using FuncSwap = void(
void*,
void*, uint32_t, uint32_t, uint32_t, uint32_t);
277 using FuncCmp = bool(
const void*,
const void*);
325 template <
typename T>
328 using CT = component_type_t<T>;
330 using U =
typename component_type_t<T>::Type;
332 using DescU =
typename CT::TypeFull;
337 return {meta::type_info::hash<DescU>()};
343 return meta::type_info::name<DescU>();
348 static constexpr uint32_t
size() {
349 if constexpr (std::is_empty_v<U>)
352 return (uint32_t)
sizeof(
U);
357 static constexpr uint32_t
alig() {
366 static uint32_t
soa(std::span<uint8_t, meta::StructToTupleMaxTypes> soaSizes) {
367 if constexpr (mem::is_soa_layout_v<U>) {
369 using TTuple =
decltype(meta::struct_to_tuple(std::declval<U>()));
371 constexpr auto TTupleSize = std::tuple_size_v<TTuple>;
372 static_assert(TTupleSize > 0);
373 static_assert(TTupleSize <= meta::StructToTupleMaxTypes);
374 core::each_tuple<TTuple>([&](
auto&& item) {
375 static_assert(
sizeof(item) <= 255,
"Each member of a SoA component can be at most 255 B long!");
376 soaSizes[i] = (uint8_t)
sizeof(item);
379 GAIA_ASSERT(i <= meta::StructToTupleMaxTypes);
389 constexpr auto storageType = auto_storage_policy_v<U>;
391 storageType == DataStorageType::Table || storageType == DataStorageType::Sparse,
392 "Unsupported component storage type");
394 storageType != DataStorageType::Sparse || CT::Kind == EntityKind::EK_Gen,
395 "GAIA_STORAGE(Sparse) supports only generic components");
397 storageType != DataStorageType::Sparse || !std::is_empty_v<U>,
398 "GAIA_STORAGE(Sparse) requires a non-empty component payload");
400 storageType != DataStorageType::Sparse || !mem::is_soa_layout_v<U>,
401 "GAIA_STORAGE(Sparse) is not compatible with SoA layouts");
408 if constexpr (!mem::is_soa_layout_v<U> && !std::is_trivially_constructible_v<U>) {
409 return [](
void* ptr, uint32_t cnt) {
410 core::call_ctor_n((
U*)ptr, cnt);
420 if constexpr (!mem::is_soa_layout_v<U> && !std::is_trivially_destructible_v<U>) {
421 return [](
void* ptr, uint32_t cnt) {
422 core::call_dtor_n((
U*)ptr, cnt);
432 return [](
void* GAIA_RESTRICT dst,
const void* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
433 uint32_t sizeDst, uint32_t sizeSrc) {
434 mem::copy_ctor_element<U>((uint8_t*)dst, (
const uint8_t*)src, idxDst, idxSrc, sizeDst, sizeSrc);
441 return [](
void* GAIA_RESTRICT dst,
void* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
442 uint32_t sizeDst, uint32_t sizeSrc) {
443 mem::move_ctor_element<U>((uint8_t*)dst, (uint8_t*)src, idxDst, idxSrc, sizeDst, sizeSrc);
450 return [](
void* GAIA_RESTRICT dst,
const void* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
451 uint32_t sizeDst, uint32_t sizeSrc) {
452 mem::copy_element<U>((uint8_t*)dst, (
const uint8_t*)src, idxDst, idxSrc, sizeDst, sizeSrc);
459 return [](
void* GAIA_RESTRICT dst,
void* GAIA_RESTRICT src, uint32_t idxDst, uint32_t idxSrc,
460 uint32_t sizeDst, uint32_t sizeSrc) {
461 mem::move_element<U>((uint8_t*)dst, (uint8_t*)src, idxDst, idxSrc, sizeDst, sizeSrc);
468 return [](
void* GAIA_RESTRICT left,
void* GAIA_RESTRICT right, uint32_t idxLeft, uint32_t idxRight,
469 uint32_t sizeLeft, uint32_t sizeRight) {
470 mem::swap_elements<U>((uint8_t*)left, (uint8_t*)right, idxLeft, idxRight, sizeLeft, sizeRight);
477 if constexpr (mem::is_soa_layout_v<U>) {
478 return []([[maybe_unused]]
const void* left, [[maybe_unused]]
const void* right) {
479 GAIA_ASSERT(
false &&
"func_cmp for SoA not implemented yet");
485 if constexpr (hasGlobalCmp || hasMemberCmp) {
486 return [](
const void* left,
const void* right) {
487 const auto* l = (
const U*)left;
488 const auto* r = (
const U*)right;
493 return [](
const void* left,
const void* right) {
494 const auto* l = (
const U*)left;
495 const auto* r = (
const U*)right;
496 return memcmp(l, r,
sizeof(
U)) == 0;
505 return [](
ser::serializer& s,
const void* pSrc, uint32_t from, uint32_t to, uint32_t cap) {
506 const auto* pComponent = (
const U*)pSrc;
508#if GAIA_ASSERT_ENABLED
510 s.check(*pComponent);
513 if constexpr (mem::is_soa_layout_v<U>) {
515 GAIA_FOR2(from, to) {
521 GAIA_FOR2(from, to) {
532 return [](
ser::serializer& s,
void* pDst, uint32_t from, uint32_t to, uint32_t cap) {
533 if constexpr (mem::is_soa_layout_v<U>) {
535 GAIA_FOR2(from, to) {
541 auto* pComponent = (
U*)pDst + from;
542 GAIA_FOR2(from, to) {
550#if GAIA_ECS_AUTO_COMPONENT_FIELDS
555 template <
typename Field>
556 static Entity auto_field_type() noexcept {
557 using FU = core::raw_t<Field>;
558 if constexpr (std::is_same_v<FU, bool>)
560 else if constexpr (std::is_same_v<FU, char>)
562 else if constexpr (std::is_arithmetic_v<FU>)
563 return runtime_primitive_type_entity(ser::type_id<FU>());
571 static uint32_t auto_fields(std::span<RuntimeFieldInit, meta::StructToTupleMaxTypes> fields) {
572 using Raw = core::raw_t<T>;
573 if constexpr (std::is_empty_v<Raw> || mem::is_soa_layout_v<Raw>) {
575 }
else if constexpr (!std::is_class_v<Raw>) {
576 const auto fieldType = auto_field_type<Raw>();
577 if (fieldType == EntityBad)
581 }
else if constexpr (!std::is_aggregate_v<Raw>) {
585 const auto* pBase =
reinterpret_cast<const uint8_t*
>(&tmp);
586 static constexpr const char* FieldNames[meta::StructToTupleMaxTypes] = {
587 "f0",
"f1",
"f2",
"f3",
"f4",
"f5",
"f6",
"f7",
"f8",
"f9",
"f10",
"f11",
"f12",
"f13",
"f14"};
588 uint32_t fieldCount = 0;
589 meta::each_member(tmp, [&](
auto&... members) {
590 auto add_field = [&](
auto& member) {
591 using Field = core::raw_t<
decltype(member)>;
592 const auto fieldType = auto_field_type<Field>();
593 if (fieldType == EntityBad)
595 GAIA_ASSERT(fieldCount < meta::StructToTupleMaxTypes);
596 const auto* pField =
reinterpret_cast<const uint8_t*
>(&member);
597 const auto offset = (uint32_t)(pField - pBase);
598 const auto* fieldName = FieldNames[fieldCount];
599 const auto fieldNameLen = (uint32_t)GAIA_STRLEN(fieldName, 4);
600 fields[fieldCount] = {util::str_view(fieldName, fieldNameLen), fieldType, offset, 0};
603 (add_field(members), ...);
616 static ecs::ComponentDesc
619 desc.
name = descName;
623 desc.soa =
soa(soaSizes);
624 desc.pSoaSizes = soaSizes.data();
Detects whether T supports a free operator==.
Definition utility.h:776
Detects whether T defines operator== as a member function.
Definition utility.h:768
Plain component registration descriptor shared by typed and runtime component paths....
Definition component_desc.h:263
void(void *, uint32_t) FuncDtor
Component destructor callback for a contiguous range of payload slots.
Definition component_desc.h:267
FuncCopy * funcCopyCtor
Optional copy-constructor callback. Runtime byte-only components leave this null.
Definition component_desc.h:305
FuncSwap * funcSwap
Optional swap callback. Runtime byte-only components leave this null.
Definition component_desc.h:313
FuncCopy * funcCopy
Optional copy-assignment callback. Runtime byte-only components leave this null.
Definition component_desc.h:309
FuncCtor * funcCtor
Optional constructor callback. Runtime byte-only components leave this null.
Definition component_desc.h:301
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:295
bool(const void *, const void *) FuncCmp
Component equality callback for comparing two payload values.
Definition component_desc.h:277
FuncSave * funcSave
Optional typed serialization save callback. Semantic runtime JSON uses field metadata instead.
Definition component_desc.h:317
FuncMove * funcMove
Optional move-assignment callback. Runtime byte-only components leave this null.
Definition component_desc.h:311
void(ser::serializer &, const void *, uint32_t, uint32_t, uint32_t) FuncSave
Component serializer callback for typed component save operations.
Definition component_desc.h:279
uint32_t soa
Number of SoA elements, 0 means AoS.
Definition component_desc.h:292
DataStorageType storageType
Component storage mode.
Definition component_desc.h:290
RuntimeTypeDesc runtimeType
Runtime reflection metadata copied during registration.
Definition component_desc.h:299
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:271
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:275
void(ser::serializer &, void *, uint32_t, uint32_t, uint32_t) FuncLoad
Component serializer callback for typed component load operations.
Definition component_desc.h:281
uint32_t alig
Component payload alignment in bytes.
Definition component_desc.h:288
void(void *, uint32_t) FuncCtor
Component constructor callback for a contiguous range of payload slots.
Definition component_desc.h:265
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:269
uint32_t size
Component payload size in bytes.
Definition component_desc.h:286
FuncCmp * funcCmp
Optional equality callback. Runtime byte-only components leave this null.
Definition component_desc.h:315
ComponentLookupHash hashLookup
Optional explicit lookup hash. When empty, the symbol hash is used.
Definition component_desc.h:297
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:273
FuncMove * funcMoveCtor
Optional move-constructor callback. Runtime byte-only components leave this null.
Definition component_desc.h:303
FuncLoad * funcLoad
Optional typed serialization load callback. Semantic runtime JSON uses field metadata instead.
Definition component_desc.h:319
FuncDtor * funcDtor
Optional destructor callback. Runtime byte-only components leave this null.
Definition component_desc.h:307
util::str_view name
Registered component symbol.
Definition component_desc.h:284
static constexpr uint32_t MaxAlignment
Largest component alignment storable.
Definition id.h:52
Identifier of an entity or component instance in the world. Packs the entity index,...
Definition id.h:296
Callback table for opaque runtime values with adapter-owned physical storage.
Definition component_desc.h:217
void * ctx
User context passed to all callbacks.
Definition component_desc.h:219
bool(* project)(void *, const RuntimeOpaqueScope &, RuntimeOpaqueValue &)
Projects an opaque value to its semantic runtime type. Required for traversal.
Definition component_desc.h:221
bool(* commit)(void *, RuntimeOpaqueScope &, RuntimeOpaqueValue &)
Commits a projected semantic value after cursor writes. Optional for direct projections....
Definition component_desc.h:224
Runtime opaque adapter input scope. The physical byte layout is owned by the adapter.
Definition component_desc.h:191
const void * data
Read-only opaque payload or handle bytes.
Definition component_desc.h:195
Entity type
Opaque runtime type entity for the selected value.
Definition component_desc.h:193
void * mutData
Mutable opaque payload or handle bytes. Null for read-only traversal.
Definition component_desc.h:197
uint32_t size
Size of the opaque payload or handle bytes.
Definition component_desc.h:199
Semantic value projected from opaque runtime storage.
Definition component_desc.h:203
void * token
Adapter-owned projection token.
Definition component_desc.h:213
uint32_t size
Size of projected semantic bytes.
Definition component_desc.h:211
void * mutData
Mutable projected semantic bytes. Null for read-only traversal.
Definition component_desc.h:209
Entity type
Semantic runtime type entity for projected bytes. EntityBad uses opaqueAsType.
Definition component_desc.h:205
const void * data
Read-only projected semantic bytes.
Definition component_desc.h:207
Callback table for adapter-owned dynamic sequence values.
Definition component_desc.h:176
bool(* count)(void *, const RuntimeSequenceScope &, uint32_t &)
Reads the dynamic element count. Required for traversal.
Definition component_desc.h:180
bool(* commitElement)(void *, RuntimeSequenceScope &, RuntimeSequenceElement &)
Commits a projected element after cursor writes. Optional for direct element pointers....
Definition component_desc.h:187
bool(* element)(void *, const RuntimeSequenceScope &, uint32_t, RuntimeSequenceElement &)
Selects one element by index. Required for traversal.
Definition component_desc.h:182
bool(* resize)(void *, RuntimeSequenceScope &, uint32_t)
Resizes the sequence. Optional. Required for JSON load into dynamic sequences.
Definition component_desc.h:184
void * ctx
User context passed to all callbacks.
Definition component_desc.h:178
Runtime sequence element returned by an adapter.
Definition component_desc.h:162
Entity type
Runtime type entity for the selected element value.
Definition component_desc.h:164
uint32_t size
Size of the selected element bytes.
Definition component_desc.h:170
void * token
Adapter-owned token for projected elements.
Definition component_desc.h:172
void * mutData
Mutable element bytes. Null for read-only traversal.
Definition component_desc.h:168
const void * data
Read-only element bytes.
Definition component_desc.h:166
Runtime sequence adapter input scope. The byte layout is owned by the adapter.
Definition component_desc.h:150
void * mutData
Mutable sequence payload or handle bytes. Null for read-only traversal.
Definition component_desc.h:156
const void * data
Read-only sequence payload or handle bytes.
Definition component_desc.h:154
uint32_t size
Size of the selected sequence payload or handle bytes.
Definition component_desc.h:158
Entity type
Runtime type entity for the selected sequence value.
Definition component_desc.h:152
Runtime reflection metadata embedded in a component descriptor or supplied to typed registration....
Definition component_desc.h:229
Entity underlyingType
Primitive storage type for enum/bitmask metadata. EntityBad otherwise.
Definition component_desc.h:239
Entity semantic
Optional named entity identifying the authored semantic.
Definition component_desc.h:233
const RuntimeOpaqueAdapter * opaqueAdapter
Optional adapter for opaque semantic projections. The callback table must outlive the registration.
Definition component_desc.h:257
const RuntimeConstantInit * constants
Runtime constant initializers copied during registration.
Definition component_desc.h:245
const RuntimeFieldInit * fields
Runtime field initializers copied during registration.
Definition component_desc.h:241
uint32_t fieldCount
Number of field initializers.
Definition component_desc.h:243
uint32_t constantCount
Number of constant initializers.
Definition component_desc.h:247
Entity elementType
Element type for fixed array or dynamic vector metadata.
Definition component_desc.h:249
const RuntimeSequenceAdapter * sequenceAdapter
Optional adapter for dynamic sequence metadata. The callback table must outlive the registration.
Definition component_desc.h:255
RuntimeTypeKind typeKind
Runtime reflection type kind.
Definition component_desc.h:231
Entity opaqueAsType
Semantic runtime type exposed by opaque metadata. EntityBad otherwise.
Definition component_desc.h:253
uint32_t elementCount
Fixed element count for array metadata. 0 otherwise.
Definition component_desc.h:251
Interned component-cache symbol identifier.
Definition component_desc.h:73
GAIA_NODISCARD constexpr bool operator!=(SymbolId other) const noexcept
Compares two interned identifiers for inequality.
Definition component_desc.h:91
GAIA_NODISCARD constexpr bool valid() const noexcept
Checks whether the identifier refers to an interned string.
Definition component_desc.h:79
uint32_t value
Zero-based index in the owning component cache symbol table, or UINT32_MAX when unset.
Definition component_desc.h:75
GAIA_NODISCARD constexpr bool operator==(SymbolId other) const noexcept
Compares two interned identifiers.
Definition component_desc.h:85
Compile-time adapter that converts typed component metadata into a plain ComponentDesc.
Definition component_desc.h:326
static constexpr auto func_dtor()
Builds the optional destructor callback for typed AoS payloads.
Definition component_desc.h:419
static constexpr auto func_move_ctor()
Builds the move-constructor callback used when typed payload storage grows or migrates.
Definition component_desc.h:440
static constexpr auto func_copy()
Builds the copy-assignment callback used for typed payload writes.
Definition component_desc.h:449
typename CT::TypeFull DescU
Fully-qualified component type used for stable symbol/hash generation.
Definition component_desc.h:332
typename component_type_t< T >::Type U
Stored C++ payload type.
Definition component_desc.h:330
static constexpr uint32_t alig()
Returns the payload alignment required by the component storage policy.
Definition component_desc.h:357
static constexpr auto func_ctor()
Builds the optional constructor callback for typed AoS payloads.
Definition component_desc.h:407
static constexpr auto func_load()
Builds the serializer load callback for typed payload values.
Definition component_desc.h:531
static constexpr uint32_t size()
Returns the payload size stored in chunks.
Definition component_desc.h:348
component_type_t< T > CT
Reflected Gaia component type wrapper.
Definition component_desc.h:328
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:617
static constexpr auto func_cmp()
Builds the equality comparison callback for typed payload values.
Definition component_desc.h:476
static uint32_t soa(std::span< uint8_t, meta::StructToTupleMaxTypes > soaSizes)
Populates SoA element sizes for SoA payloads.
Definition component_desc.h:366
static constexpr auto func_copy_ctor()
Builds the copy-constructor callback used when typed payload storage grows or migrates.
Definition component_desc.h:431
static constexpr auto func_save()
Builds the serializer save callback for typed payload values.
Definition component_desc.h:504
static constexpr ComponentLookupHash hash_lookup()
Returns the stable lookup hash for the component type.
Definition component_desc.h:336
static constexpr auto func_swap()
Builds the swap callback used by storage operations.
Definition component_desc.h:467
static constexpr DataStorageType storage_type()
Returns the compile-time storage mode requested for the component payload.
Definition component_desc.h:388
static constexpr auto name()
Returns the reflected component symbol name.
Definition component_desc.h:342
static constexpr auto func_move()
Builds the move-assignment callback used for typed payload writes.
Definition component_desc.h:458
Read-only view for a selected layout and item type.
Definition data_layout_policy.h:129
Mutable view for a selected layout and item type.
Definition data_layout_policy.h:134
Storage policy for a selected layout and item type.
Definition data_layout_policy.h:123
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