Skip to main content

icydb_core/
lib.rs

1//! Module: lib
2//! Responsibility: crate root for the IcyDB core runtime surface.
3//! Does not own: canister-facing facade APIs from the public `icydb` crate.
4//! Boundary: exposes the engine subsystems used by schema, query, executor, and storage layers.
5
6//! Core runtime for IcyDB: entity traits, values, executors, visitors, and
7//! the ergonomics exported via the `prelude`.
8#![warn(unreachable_pub)]
9
10extern crate self as icydb;
11
12#[macro_use]
13pub(crate) mod scalar_registry;
14
15// public exports are one module level down
16pub mod db;
17pub mod error;
18pub mod metrics;
19pub mod model;
20pub(crate) mod runtime;
21pub mod sanitize;
22pub mod traits;
23pub mod types;
24pub mod validate;
25pub mod value;
26pub mod visitor;
27
28// testing
29#[cfg(test)]
30pub(crate) mod testing;
31
32///
33/// CONSTANTS
34///
35
36/// Maximum number of indexed fields allowed on an entity.
37///
38/// This limit keeps hashed index keys within bounded, storable sizes and
39/// simplifies sizing tests in the stores.
40pub const MAX_INDEX_FIELDS: usize = 4;
41
42///
43/// Prelude
44///
45/// Prelude contains only domain vocabulary.
46/// No errors, executors, stores, serializers, or helpers are re-exported here.
47///
48
49pub mod prelude {
50    pub use crate::{
51        model::{entity::EntityModel, index::IndexModel},
52        traits::{EntityKind, Path},
53        value::{InputValue, OutputValue},
54    };
55}
56
57// Macro/runtime wiring surface used by generated code in local core tests.
58// This mirrors the facade crate's hidden generated-code boundary so derive
59// output can target one stable path regardless of which workspace crate owns
60// the test harness.
61#[doc(hidden)]
62pub mod __macro {
63    pub use crate::db::{
64        CompositePrimaryKeyValue, CompositePrimaryKeyValueError, GeneratedStructuralEnumPayload,
65        GeneratedStructuralMapPayloadSlices, JournalTailStore, PersistedRow, PersistedScalar,
66        PrimaryKeyComponent, PrimaryKeyValue, ScalarSlotValueRef, ScalarValueRef, SlotReader,
67        SlotWriter, StoreRuntimeStorageCapabilities,
68    };
69    pub use crate::error::{ErrorClass, ErrorOrigin, InternalError};
70    pub use crate::traits::{
71        EntityKeyBytes, EnumValue, FieldProjection, KeyValueCodec, PersistedByKindCodec,
72        PersistedFieldMetaCodec, PersistedFieldSlotCodec, PersistedStructuredFieldCodec,
73        PrimaryKeyCodec, PrimaryKeyDecode, PrimaryKeyEncodeError, RuntimeValueDecode,
74        RuntimeValueEncode, RuntimeValueKind, RuntimeValueMeta, ScalarRelationTargetKey,
75        ScalarRelationTargetKeyMatchesDeclaredPrimitive, runtime_value_btree_map_from_value,
76        runtime_value_btree_set_from_value, runtime_value_collection_to_value,
77        runtime_value_from_value, runtime_value_from_vec_into,
78        runtime_value_from_vec_into_btree_map, runtime_value_from_vec_into_btree_set,
79        runtime_value_into, runtime_value_map_collection_to_value, runtime_value_to_value,
80        runtime_value_vec_from_value,
81    };
82    pub use crate::value::{InputValue, Value, ValueEnum};
83    pub use ic_memory::{
84        bootstrap_default_memory_manager, ic_memory_declaration, ic_memory_key, ic_memory_range,
85    };
86
87    #[doc(hidden)]
88    #[must_use]
89    pub fn encode_generated_structural_text_payload_bytes(value: &str) -> Vec<u8> {
90        crate::db::encode_generated_structural_text_payload_bytes(value)
91    }
92
93    #[doc(hidden)]
94    #[must_use]
95    pub fn encode_generated_structural_list_payload_bytes(items: &[&[u8]]) -> Vec<u8> {
96        crate::db::encode_generated_structural_list_payload_bytes(items)
97    }
98
99    #[doc(hidden)]
100    #[must_use]
101    pub fn encode_generated_structural_map_payload_bytes(entries: &[(&[u8], &[u8])]) -> Vec<u8> {
102        crate::db::encode_generated_structural_map_payload_bytes(entries)
103    }
104
105    #[doc(hidden)]
106    #[must_use]
107    pub fn encode_generated_structural_enum_payload_bytes(
108        variant: &str,
109        path: Option<&str>,
110        payload: Option<&[u8]>,
111    ) -> Vec<u8> {
112        crate::db::encode_generated_structural_enum_payload_bytes(variant, path, payload)
113    }
114
115    #[doc(hidden)]
116    pub fn decode_generated_structural_text_payload_bytes(
117        raw_bytes: &[u8],
118    ) -> Result<String, crate::error::InternalError> {
119        crate::db::decode_generated_structural_text_payload_bytes(raw_bytes)
120    }
121
122    #[doc(hidden)]
123    pub fn decode_generated_structural_list_payload_bytes(
124        raw_bytes: &[u8],
125    ) -> Result<Vec<&[u8]>, crate::error::InternalError> {
126        crate::db::decode_generated_structural_list_payload_bytes(raw_bytes)
127    }
128
129    #[doc(hidden)]
130    pub fn decode_generated_structural_map_payload_bytes(
131        raw_bytes: &[u8],
132    ) -> Result<crate::db::GeneratedStructuralMapPayloadSlices<'_>, crate::error::InternalError>
133    {
134        crate::db::decode_generated_structural_map_payload_bytes(raw_bytes)
135    }
136
137    #[doc(hidden)]
138    pub fn decode_generated_structural_enum_payload_bytes(
139        raw_bytes: &[u8],
140    ) -> Result<crate::db::GeneratedStructuralEnumPayload<'_>, crate::error::InternalError> {
141        crate::db::decode_generated_structural_enum_payload_bytes(raw_bytes)
142    }
143
144    #[doc(hidden)]
145    pub fn generated_persisted_structured_payload_decode_failed(
146        detail: impl std::fmt::Display,
147    ) -> crate::error::InternalError {
148        crate::db::generated_persisted_structured_payload_decode_failed(detail)
149    }
150
151    #[doc(hidden)]
152    pub fn encode_persisted_structured_many_slot_payload<T>(
153        value: &[T],
154        field_name: &'static str,
155    ) -> Result<Vec<u8>, crate::error::InternalError>
156    where
157        T: crate::traits::PersistedStructuredFieldCodec,
158    {
159        crate::db::encode_persisted_structured_many_slot_payload(value, field_name)
160    }
161
162    #[doc(hidden)]
163    pub fn decode_persisted_structured_many_slot_payload<T>(
164        bytes: &[u8],
165        field_name: &'static str,
166    ) -> Result<Vec<T>, crate::error::InternalError>
167    where
168        T: crate::traits::PersistedStructuredFieldCodec,
169    {
170        crate::db::decode_persisted_structured_many_slot_payload(bytes, field_name)
171    }
172
173    #[doc(hidden)]
174    pub fn encode_persisted_structured_slot_payload<T>(
175        value: &T,
176        field_name: &'static str,
177    ) -> Result<Vec<u8>, crate::error::InternalError>
178    where
179        T: crate::traits::PersistedStructuredFieldCodec,
180    {
181        crate::db::encode_persisted_structured_slot_payload(value, field_name)
182    }
183
184    #[doc(hidden)]
185    pub fn decode_persisted_structured_slot_payload<T>(
186        bytes: &[u8],
187        field_name: &'static str,
188    ) -> Result<T, crate::error::InternalError>
189    where
190        T: crate::traits::PersistedStructuredFieldCodec,
191    {
192        crate::db::decode_persisted_structured_slot_payload(bytes, field_name)
193    }
194
195    #[doc(hidden)]
196    pub fn encode_persisted_option_scalar_slot_payload<T>(
197        value: &Option<T>,
198        field_name: &'static str,
199    ) -> Result<Vec<u8>, crate::error::InternalError>
200    where
201        T: PersistedScalar,
202    {
203        crate::db::encode_persisted_option_scalar_slot_payload(value, field_name)
204    }
205
206    #[doc(hidden)]
207    pub fn decode_persisted_option_scalar_slot_payload<T>(
208        bytes: &[u8],
209        field_name: &'static str,
210    ) -> Result<Option<T>, crate::error::InternalError>
211    where
212        T: PersistedScalar,
213    {
214        crate::db::decode_persisted_option_scalar_slot_payload(bytes, field_name)
215    }
216
217    #[doc(hidden)]
218    pub fn encode_persisted_scalar_slot_payload<T>(
219        value: &T,
220        field_name: &'static str,
221    ) -> Result<Vec<u8>, crate::error::InternalError>
222    where
223        T: PersistedScalar,
224    {
225        crate::db::encode_persisted_scalar_slot_payload(value, field_name)
226    }
227
228    #[doc(hidden)]
229    pub fn decode_persisted_scalar_slot_payload<T>(
230        bytes: &[u8],
231        field_name: &'static str,
232    ) -> Result<T, crate::error::InternalError>
233    where
234        T: PersistedScalar,
235    {
236        crate::db::decode_persisted_scalar_slot_payload(bytes, field_name)
237    }
238
239    #[doc(hidden)]
240    pub fn encode_persisted_slot_payload_by_kind<T>(
241        value: &T,
242        kind: crate::model::field::FieldKind,
243        field_name: &'static str,
244    ) -> Result<Vec<u8>, crate::error::InternalError>
245    where
246        T: crate::traits::PersistedByKindCodec,
247    {
248        crate::db::encode_persisted_slot_payload_by_kind(value, kind, field_name)
249    }
250
251    #[doc(hidden)]
252    pub fn decode_persisted_slot_payload_by_kind<T>(
253        bytes: &[u8],
254        kind: crate::model::field::FieldKind,
255        field_name: &'static str,
256    ) -> Result<T, crate::error::InternalError>
257    where
258        T: crate::traits::PersistedByKindCodec,
259    {
260        crate::db::decode_persisted_slot_payload_by_kind(bytes, kind, field_name)
261    }
262
263    #[doc(hidden)]
264    pub fn decode_persisted_option_slot_payload_by_kind<T>(
265        bytes: &[u8],
266        kind: crate::model::field::FieldKind,
267        field_name: &'static str,
268    ) -> Result<Option<T>, crate::error::InternalError>
269    where
270        T: crate::traits::PersistedByKindCodec,
271    {
272        crate::db::decode_persisted_option_slot_payload_by_kind(bytes, kind, field_name)
273    }
274
275    #[doc(hidden)]
276    pub fn encode_persisted_option_slot_payload_by_meta<T>(
277        value: &Option<T>,
278        field_name: &'static str,
279    ) -> Result<Vec<u8>, crate::error::InternalError>
280    where
281        T: crate::traits::PersistedFieldMetaCodec,
282    {
283        crate::db::encode_persisted_option_slot_payload_by_meta(value, field_name)
284    }
285
286    #[doc(hidden)]
287    pub fn decode_persisted_option_slot_payload_by_meta<T>(
288        bytes: &[u8],
289        field_name: &'static str,
290    ) -> Result<Option<T>, crate::error::InternalError>
291    where
292        T: crate::traits::PersistedFieldMetaCodec,
293    {
294        crate::db::decode_persisted_option_slot_payload_by_meta(bytes, field_name)
295    }
296
297    #[doc(hidden)]
298    pub fn encode_persisted_many_slot_payload_by_meta<T>(
299        value: &[T],
300        field_name: &'static str,
301    ) -> Result<Vec<u8>, crate::error::InternalError>
302    where
303        T: crate::traits::FieldTypeMeta + crate::traits::RuntimeValueEncode,
304    {
305        crate::db::encode_persisted_many_slot_payload_by_meta(value, field_name)
306    }
307
308    #[doc(hidden)]
309    pub fn decode_persisted_many_slot_payload_by_meta<T>(
310        bytes: &[u8],
311        field_name: &'static str,
312    ) -> Result<Vec<T>, crate::error::InternalError>
313    where
314        T: crate::traits::FieldTypeMeta + crate::traits::RuntimeValueDecode,
315    {
316        crate::db::decode_persisted_many_slot_payload_by_meta(bytes, field_name)
317    }
318
319    #[doc(hidden)]
320    pub fn encode_persisted_slot_payload_by_meta<T>(
321        value: &T,
322        field_name: &'static str,
323    ) -> Result<Vec<u8>, crate::error::InternalError>
324    where
325        T: crate::traits::PersistedFieldMetaCodec,
326    {
327        crate::db::encode_persisted_slot_payload_by_meta(value, field_name)
328    }
329
330    #[doc(hidden)]
331    pub fn decode_persisted_slot_payload_by_meta<T>(
332        bytes: &[u8],
333        field_name: &'static str,
334    ) -> Result<T, crate::error::InternalError>
335    where
336        T: crate::traits::PersistedFieldMetaCodec,
337    {
338        crate::db::decode_persisted_slot_payload_by_meta(bytes, field_name)
339    }
340
341    #[doc(hidden)]
342    pub fn encode_schema_runtime_field_slot<T>(
343        model: &'static crate::model::entity::EntityModel,
344        slot: usize,
345        value: &T,
346    ) -> Result<Vec<u8>, crate::error::InternalError>
347    where
348        T: ?Sized + crate::traits::RuntimeValueEncode,
349    {
350        let runtime_value = value.to_value();
351
352        crate::db::encode_runtime_value_into_slot(model, slot, &runtime_value)
353    }
354
355    #[doc(hidden)]
356    pub fn decode_schema_runtime_field_slot<T>(
357        model: &'static crate::model::entity::EntityModel,
358        slot: usize,
359        bytes: &[u8],
360        field_name: &'static str,
361    ) -> Result<T, crate::error::InternalError>
362    where
363        T: crate::traits::RuntimeValueDecode,
364    {
365        let runtime_value = crate::db::decode_slot_into_runtime_value(model, slot, bytes)?;
366
367        T::from_value(&runtime_value).ok_or_else(|| {
368            crate::error::InternalError::persisted_row_field_decode_failed(
369                field_name,
370                format!("payload does not match {}", std::any::type_name::<T>()),
371            )
372        })
373    }
374}