icydb_core/traits/mod.rs
1//! Module: traits
2//!
3//! Responsibility: foundational kind, field metadata, projection, and wrapper
4//! contracts awaiting narrower domain ownership.
5//! Does not own: entity composition, key taxonomy, runtime value conversion,
6//! visitor traversal, executor policy, or public facade DTO behavior.
7//! Boundary: remaining reusable contracts consumed throughout `icydb-core`.
8
9use crate::{
10 model::field::{FieldKind, FieldModel, FieldStorageDecode},
11 value::{InputValue, Value},
12 visitor::Visitable,
13};
14use serde::de::DeserializeOwned;
15use std::collections::{BTreeMap, BTreeSet};
16
17// ============================================================================
18// FOUNDATIONAL KINDS
19// ============================================================================
20//
21// These traits define *where* something lives in the system,
22// not what data it contains.
23//
24
25///
26/// Path
27/// Fully-qualified schema path.
28///
29
30pub trait Path {
31 const PATH: &'static str;
32}
33
34///
35/// Kind
36/// Marker for all schema/runtime nodes.
37///
38
39pub trait Kind: Path + 'static {}
40impl<T> Kind for T where T: Path + 'static {}
41
42///
43/// CanisterKind
44/// Marker for canister namespaces
45///
46
47pub trait CanisterKind: Kind {
48 /// Stable memory slot used for commit marker storage.
49 const COMMIT_MEMORY_ID: u8;
50
51 /// Durable stable-memory allocation key for commit marker storage.
52 const COMMIT_STABLE_KEY: &'static str;
53}
54
55///
56/// StoreKind
57/// Marker for data stores bound to a canister
58///
59
60pub trait StoreKind: Kind {
61 type Canister: CanisterKind;
62}
63
64// ============================================================================
65// TYPE SYSTEM CONTRACTS
66// ============================================================================
67//
68// These traits define behavioral expectations for schema-defined types.
69//
70
71///
72/// TypeKind
73///
74/// Any schema-defined data type.
75///
76/// This is a *strong* contract and should only be required
77/// where full lifecycle semantics are needed.
78///
79
80pub trait TypeKind: Kind + Clone + DeserializeOwned + Visitable + PartialEq {}
81
82impl<T> TypeKind for T where T: Kind + Clone + DeserializeOwned + PartialEq + Visitable {}
83
84///
85/// FieldTypeMeta
86///
87/// Static runtime field metadata for one schema-facing value type.
88/// This is the single authority for generated field kind and storage-decode
89/// metadata, so callers do not need per-type inherent constants.
90///
91
92pub trait FieldTypeMeta {
93 /// Semantic field kind used for runtime planning and validation.
94 const KIND: FieldKind;
95
96 /// Persisted decode contract used by row and payload decoding.
97 const STORAGE_DECODE: FieldStorageDecode;
98
99 /// Known nested fields for generated structured records.
100 const NESTED_FIELDS: &'static [FieldModel] = &[];
101}
102
103impl<T> FieldTypeMeta for Option<T>
104where
105 T: FieldTypeMeta,
106{
107 const KIND: FieldKind = T::KIND;
108 const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
109 const NESTED_FIELDS: &'static [FieldModel] = T::NESTED_FIELDS;
110}
111
112impl<T> FieldTypeMeta for Box<T>
113where
114 T: FieldTypeMeta,
115{
116 const KIND: FieldKind = T::KIND;
117 const STORAGE_DECODE: FieldStorageDecode = T::STORAGE_DECODE;
118 const NESTED_FIELDS: &'static [FieldModel] = T::NESTED_FIELDS;
119}
120
121// Standard containers mirror the generated collection-wrapper contract: their
122// semantic kind remains structural, but persisted decode routes through the
123// shared structural `Value` storage seam instead of leaf-by-leaf scalar decode.
124impl<T> FieldTypeMeta for Vec<T>
125where
126 T: FieldTypeMeta,
127{
128 const KIND: FieldKind = FieldKind::List(&T::KIND);
129 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
130}
131
132impl<T> FieldTypeMeta for BTreeSet<T>
133where
134 T: FieldTypeMeta,
135{
136 const KIND: FieldKind = FieldKind::Set(&T::KIND);
137 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
138}
139
140impl<K, V> FieldTypeMeta for BTreeMap<K, V>
141where
142 K: FieldTypeMeta,
143 V: FieldTypeMeta,
144{
145 const KIND: FieldKind = FieldKind::Map {
146 key: &K::KIND,
147 value: &V::KIND,
148 };
149 const STORAGE_DECODE: FieldStorageDecode = FieldStorageDecode::Value;
150}
151
152/// ============================================================================
153/// QUERY VALUE BOUNDARIES
154/// ============================================================================
155
156/// Name-based field input projection used before accepted-catalog admission.
157pub trait AuthoredFieldProjection {
158 /// Resolve one authored field value by stable field slot index.
159 fn get_input_value_by_index(&self, index: usize) -> Option<InputValue>;
160}
161
162pub trait FieldProjection {
163 /// Resolve one field value by stable field slot index.
164 fn get_value_by_index(&self, index: usize) -> Option<Value>;
165}
166
167/// ============================================================================
168/// MISC HELPERS
169/// ============================================================================
170
171///
172/// Inner
173///
174/// For newtypes to expose their innermost value.
175///
176
177pub trait Inner<T> {
178 fn inner(&self) -> &T;
179 fn into_inner(self) -> T;
180}
181
182///
183/// Repr
184///
185/// Internal representation boundary for scalar wrapper types.
186///
187
188pub trait Repr {
189 type Inner;
190
191 fn repr(&self) -> Self::Inner;
192 fn from_repr(inner: Self::Inner) -> Self;
193}