icydb_core/model/entity.rs
1//! Module: model::entity
2//! Responsibility: module-local ownership and contracts for model::entity.
3//! Does not own: cross-module orchestration outside this module.
4//! Boundary: exposes this module API while keeping implementation details internal.
5
6//! Runtime-only entity schema surface generated by macros.
7//!
8//! This model intentionally includes only:
9//! - entity metadata (path + stable external name)
10//! - ordered fields
11//! - primary key field
12//! - index definitions
13//!
14//! It intentionally excludes:
15//! - validators/sanitizers/defaults
16//! - relations or full schema graphs
17//! - JSON schema ingestion or global registries
18//!
19//! Stability: this is the authoritative runtime contract for planning and
20//! execution. Additive changes are expected; breaking changes require a
21//! coordinated version bump across the engine.
22//!
23//! Field names are entity-scoped. Callers that combine entities must
24//! namespace by entity at the call site.
25
26use crate::model::{field::FieldModel, index::IndexModel};
27
28///
29/// EntityModel
30///
31/// Macro-generated runtime schema snapshot for a single entity.
32/// The planner and predicate validator consume this model directly.
33///
34
35#[derive(Debug)]
36pub struct EntityModel {
37 /// Fully-qualified Rust type path (for diagnostics).
38 pub(crate) path: &'static str,
39
40 /// Stable external name used in keys and routing.
41 pub(crate) entity_name: &'static str,
42
43 /// Primary key field (points at an entry in `fields`).
44 pub(crate) primary_key: &'static FieldModel,
45
46 /// Ordered field list (authoritative for runtime planning).
47 pub(crate) fields: &'static [FieldModel],
48
49 /// Index definitions (field order is significant).
50 pub(crate) indexes: &'static [&'static IndexModel],
51}
52
53impl EntityModel {
54 /// Construct one generated runtime entity descriptor.
55 ///
56 /// This constructor exists for derive/codegen output. Runtime query and
57 /// executor code treat `EntityModel` values as already validated build-time
58 /// artifacts and do not perform defensive model-shape validation per call.
59 #[must_use]
60 #[doc(hidden)]
61 pub const fn generated(
62 path: &'static str,
63 entity_name: &'static str,
64 primary_key: &'static FieldModel,
65 fields: &'static [FieldModel],
66 indexes: &'static [&'static IndexModel],
67 ) -> Self {
68 Self {
69 path,
70 entity_name,
71 primary_key,
72 fields,
73 indexes,
74 }
75 }
76
77 /// Return the fully-qualified Rust path for this entity.
78 #[must_use]
79 pub const fn path(&self) -> &'static str {
80 self.path
81 }
82
83 /// Return the stable external entity name.
84 #[must_use]
85 pub const fn name(&self) -> &'static str {
86 self.entity_name
87 }
88
89 /// Return the primary-key field descriptor.
90 #[must_use]
91 pub const fn primary_key(&self) -> &'static FieldModel {
92 self.primary_key
93 }
94
95 /// Return the ordered runtime field descriptors.
96 #[must_use]
97 pub const fn fields(&self) -> &'static [FieldModel] {
98 self.fields
99 }
100
101 /// Return the runtime index descriptors.
102 #[must_use]
103 pub const fn indexes(&self) -> &'static [&'static IndexModel] {
104 self.indexes
105 }
106}
107
108/// Resolve one schema field name into its stable slot index.
109#[must_use]
110pub(crate) fn resolve_field_slot(model: &EntityModel, field_name: &str) -> Option<usize> {
111 model
112 .fields
113 .iter()
114 .position(|field| field.name == field_name)
115}
116
117/// Resolve the primary-key field into its stable slot index.
118#[must_use]
119pub(crate) fn resolve_primary_key_slot(model: &EntityModel) -> Option<usize> {
120 model
121 .fields
122 .iter()
123 .position(|field| std::ptr::eq(field, model.primary_key))
124}