icydb_core/model/field.rs
1use crate::traits::FieldValueKind;
2
3///
4/// FieldModel
5///
6/// Runtime field metadata surfaced by macro-generated `EntityModel` values.
7///
8/// This is the smallest unit consumed by predicate validation, planning,
9/// and executor-side plan checks.
10///
11
12#[derive(Debug)]
13pub struct FieldModel {
14 /// Field name as used in predicates and indexing.
15 pub name: &'static str,
16 /// Runtime type shape (no schema-layer graph nodes).
17 pub kind: FieldKind,
18}
19
20///
21/// RelationStrength
22///
23/// Explicit relation intent for save-time referential integrity.
24///
25
26#[derive(Clone, Copy, Debug, Eq, PartialEq)]
27pub enum RelationStrength {
28 Strong,
29 Weak,
30}
31
32///
33/// FieldKind
34///
35/// Minimal runtime type surface needed by planning, validation, and execution.
36///
37/// This is aligned with `Value` variants and intentionally lossy: it encodes
38/// only the shape required for predicate compatibility and index planning.
39///
40
41#[derive(Clone, Copy, Debug)]
42pub enum FieldKind {
43 // Scalar primitives
44 Account,
45 Blob,
46 Bool,
47 Date,
48 Decimal {
49 /// Required schema-declared fractional scale for decimal fields.
50 scale: u32,
51 },
52 Duration,
53 Enum {
54 /// Fully-qualified enum type path used for strict filter normalization.
55 path: &'static str,
56 },
57 Float32,
58 Float64,
59 Int,
60 Int128,
61 IntBig,
62 Principal,
63 Subaccount,
64 Text,
65 Timestamp,
66 Uint,
67 Uint128,
68 UintBig,
69 Ulid,
70 Unit,
71
72 /// Typed relation; `key_kind` reflects the referenced key type.
73 /// `strength` encodes strong vs. weak relation intent.
74 Relation {
75 /// Fully-qualified Rust type path for diagnostics.
76 target_path: &'static str,
77 /// Stable external name used in storage keys.
78 target_entity_name: &'static str,
79 /// Data store path where the target entity is persisted.
80 target_store_path: &'static str,
81 key_kind: &'static Self,
82 strength: RelationStrength,
83 },
84
85 // Collections
86 List(&'static Self),
87 Set(&'static Self),
88 /// Deterministic, unordered key/value collection.
89 ///
90 /// Map fields are persistable and patchable, but not queryable or indexable.
91 Map {
92 key: &'static Self,
93 value: &'static Self,
94 },
95
96 /// Structured (non-atomic) value.
97 /// Queryability here controls whether predicates may target this field,
98 /// not whether it may be stored or updated.
99 Structured {
100 queryable: bool,
101 },
102}
103
104impl FieldKind {
105 #[must_use]
106 pub const fn value_kind(&self) -> FieldValueKind {
107 match self {
108 Self::Account
109 | Self::Blob
110 | Self::Bool
111 | Self::Date
112 | Self::Duration
113 | Self::Enum { .. }
114 | Self::Float32
115 | Self::Float64
116 | Self::Int
117 | Self::Int128
118 | Self::IntBig
119 | Self::Principal
120 | Self::Subaccount
121 | Self::Text
122 | Self::Timestamp
123 | Self::Uint
124 | Self::Uint128
125 | Self::UintBig
126 | Self::Ulid
127 | Self::Unit
128 | Self::Decimal { .. }
129 | Self::Relation { .. } => FieldValueKind::Atomic,
130 Self::List(_) | Self::Set(_) => FieldValueKind::Structured { queryable: true },
131 Self::Map { .. } => FieldValueKind::Structured { queryable: false },
132 Self::Structured { queryable } => FieldValueKind::Structured {
133 queryable: *queryable,
134 },
135 }
136 }
137
138 /// Returns `true` if this field shape is permitted in
139 /// persisted or query-visible schemas under the current
140 /// determinism policy.
141 ///
142 /// This shape-level check is structural only; query-time policy
143 /// enforcement (for example, map predicate fencing) is applied at
144 /// query construction and validation boundaries.
145 #[must_use]
146 pub const fn is_deterministic_collection_shape(&self) -> bool {
147 match self {
148 Self::Relation { key_kind, .. } => key_kind.is_deterministic_collection_shape(),
149
150 Self::List(inner) | Self::Set(inner) => inner.is_deterministic_collection_shape(),
151
152 Self::Map { key, value } => {
153 key.is_deterministic_collection_shape() && value.is_deterministic_collection_shape()
154 }
155
156 _ => true,
157 }
158 }
159}