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)] // too complex to adhere to right now
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, PersistedRow, PersistedScalar, PrimaryKeyComponent,
66        PrimaryKeyValue, ScalarSlotValueRef, ScalarValueRef, SlotReader, SlotWriter,
67    };
68    pub use crate::error::{ErrorClass, ErrorOrigin, InternalError};
69    pub use crate::traits::{
70        EntityKeyBytes, EnumValue, FieldProjection, KeyValueCodec, PersistedByKindCodec,
71        PersistedFieldMetaCodec, PersistedFieldSlotCodec, PersistedStructuredFieldCodec,
72        PrimaryKeyCodec, PrimaryKeyDecode, PrimaryKeyEncodeError, RuntimeValueDecode,
73        RuntimeValueEncode, RuntimeValueKind, RuntimeValueMeta, ScalarRelationTargetKey,
74        ScalarRelationTargetKeyMatchesDeclaredPrimitive, runtime_value_btree_map_from_value,
75        runtime_value_btree_set_from_value, runtime_value_collection_to_value,
76        runtime_value_from_value, runtime_value_from_vec_into,
77        runtime_value_from_vec_into_btree_map, runtime_value_from_vec_into_btree_set,
78        runtime_value_into, runtime_value_map_collection_to_value, runtime_value_to_value,
79        runtime_value_vec_from_value,
80    };
81    pub use crate::value::{InputValue, Value, ValueEnum};
82    pub use ic_memory::{
83        bootstrap_default_memory_manager, ic_memory_declaration, ic_memory_key, ic_memory_range,
84    };
85
86    #[doc(hidden)]
87    #[must_use]
88    pub fn encode_generated_structural_text_payload_bytes(value: &str) -> Vec<u8> {
89        crate::db::encode_generated_structural_text_payload_bytes(value)
90    }
91
92    #[doc(hidden)]
93    #[must_use]
94    pub fn encode_generated_structural_list_payload_bytes(items: &[&[u8]]) -> Vec<u8> {
95        crate::db::encode_generated_structural_list_payload_bytes(items)
96    }
97
98    #[doc(hidden)]
99    #[must_use]
100    pub fn encode_generated_structural_map_payload_bytes(entries: &[(&[u8], &[u8])]) -> Vec<u8> {
101        crate::db::encode_generated_structural_map_payload_bytes(entries)
102    }
103
104    #[doc(hidden)]
105    #[must_use]
106    pub fn encode_generated_structural_enum_payload_bytes(
107        variant: &str,
108        path: Option<&str>,
109        payload: Option<&[u8]>,
110    ) -> Vec<u8> {
111        crate::db::encode_generated_structural_enum_payload_bytes(variant, path, payload)
112    }
113
114    #[doc(hidden)]
115    pub fn decode_generated_structural_text_payload_bytes(
116        raw_bytes: &[u8],
117    ) -> Result<String, crate::error::InternalError> {
118        crate::db::decode_generated_structural_text_payload_bytes(raw_bytes)
119    }
120
121    #[doc(hidden)]
122    pub fn decode_generated_structural_list_payload_bytes(
123        raw_bytes: &[u8],
124    ) -> Result<Vec<&[u8]>, crate::error::InternalError> {
125        crate::db::decode_generated_structural_list_payload_bytes(raw_bytes)
126    }
127
128    #[doc(hidden)]
129    pub fn decode_generated_structural_map_payload_bytes(
130        raw_bytes: &[u8],
131    ) -> Result<crate::db::GeneratedStructuralMapPayloadSlices<'_>, crate::error::InternalError>
132    {
133        crate::db::decode_generated_structural_map_payload_bytes(raw_bytes)
134    }
135
136    #[doc(hidden)]
137    pub fn decode_generated_structural_enum_payload_bytes(
138        raw_bytes: &[u8],
139    ) -> Result<crate::db::GeneratedStructuralEnumPayload<'_>, crate::error::InternalError> {
140        crate::db::decode_generated_structural_enum_payload_bytes(raw_bytes)
141    }
142
143    #[doc(hidden)]
144    pub fn generated_persisted_structured_payload_decode_failed(
145        detail: impl std::fmt::Display,
146    ) -> crate::error::InternalError {
147        crate::db::generated_persisted_structured_payload_decode_failed(detail)
148    }
149
150    #[doc(hidden)]
151    pub fn encode_persisted_structured_many_slot_payload<T>(
152        value: &[T],
153        field_name: &'static str,
154    ) -> Result<Vec<u8>, crate::error::InternalError>
155    where
156        T: crate::traits::PersistedStructuredFieldCodec,
157    {
158        crate::db::encode_persisted_structured_many_slot_payload(value, field_name)
159    }
160
161    #[doc(hidden)]
162    pub fn decode_persisted_structured_many_slot_payload<T>(
163        bytes: &[u8],
164        field_name: &'static str,
165    ) -> Result<Vec<T>, crate::error::InternalError>
166    where
167        T: crate::traits::PersistedStructuredFieldCodec,
168    {
169        crate::db::decode_persisted_structured_many_slot_payload(bytes, field_name)
170    }
171
172    #[doc(hidden)]
173    pub fn encode_persisted_structured_slot_payload<T>(
174        value: &T,
175        field_name: &'static str,
176    ) -> Result<Vec<u8>, crate::error::InternalError>
177    where
178        T: crate::traits::PersistedStructuredFieldCodec,
179    {
180        crate::db::encode_persisted_structured_slot_payload(value, field_name)
181    }
182
183    #[doc(hidden)]
184    pub fn decode_persisted_structured_slot_payload<T>(
185        bytes: &[u8],
186        field_name: &'static str,
187    ) -> Result<T, crate::error::InternalError>
188    where
189        T: crate::traits::PersistedStructuredFieldCodec,
190    {
191        crate::db::decode_persisted_structured_slot_payload(bytes, field_name)
192    }
193
194    #[doc(hidden)]
195    pub fn encode_persisted_option_scalar_slot_payload<T>(
196        value: &Option<T>,
197        field_name: &'static str,
198    ) -> Result<Vec<u8>, crate::error::InternalError>
199    where
200        T: PersistedScalar,
201    {
202        crate::db::encode_persisted_option_scalar_slot_payload(value, field_name)
203    }
204
205    #[doc(hidden)]
206    pub fn decode_persisted_option_scalar_slot_payload<T>(
207        bytes: &[u8],
208        field_name: &'static str,
209    ) -> Result<Option<T>, crate::error::InternalError>
210    where
211        T: PersistedScalar,
212    {
213        crate::db::decode_persisted_option_scalar_slot_payload(bytes, field_name)
214    }
215
216    #[doc(hidden)]
217    pub fn encode_persisted_scalar_slot_payload<T>(
218        value: &T,
219        field_name: &'static str,
220    ) -> Result<Vec<u8>, crate::error::InternalError>
221    where
222        T: PersistedScalar,
223    {
224        crate::db::encode_persisted_scalar_slot_payload(value, field_name)
225    }
226
227    #[doc(hidden)]
228    pub fn decode_persisted_scalar_slot_payload<T>(
229        bytes: &[u8],
230        field_name: &'static str,
231    ) -> Result<T, crate::error::InternalError>
232    where
233        T: PersistedScalar,
234    {
235        crate::db::decode_persisted_scalar_slot_payload(bytes, field_name)
236    }
237
238    #[doc(hidden)]
239    pub fn encode_persisted_slot_payload_by_kind<T>(
240        value: &T,
241        kind: crate::model::field::FieldKind,
242        field_name: &'static str,
243    ) -> Result<Vec<u8>, crate::error::InternalError>
244    where
245        T: crate::traits::PersistedByKindCodec,
246    {
247        crate::db::encode_persisted_slot_payload_by_kind(value, kind, field_name)
248    }
249
250    #[doc(hidden)]
251    pub fn decode_persisted_slot_payload_by_kind<T>(
252        bytes: &[u8],
253        kind: crate::model::field::FieldKind,
254        field_name: &'static str,
255    ) -> Result<T, crate::error::InternalError>
256    where
257        T: crate::traits::PersistedByKindCodec,
258    {
259        crate::db::decode_persisted_slot_payload_by_kind(bytes, kind, field_name)
260    }
261
262    #[doc(hidden)]
263    pub fn decode_persisted_option_slot_payload_by_kind<T>(
264        bytes: &[u8],
265        kind: crate::model::field::FieldKind,
266        field_name: &'static str,
267    ) -> Result<Option<T>, crate::error::InternalError>
268    where
269        T: crate::traits::PersistedByKindCodec,
270    {
271        crate::db::decode_persisted_option_slot_payload_by_kind(bytes, kind, field_name)
272    }
273
274    #[doc(hidden)]
275    pub fn encode_persisted_option_slot_payload_by_meta<T>(
276        value: &Option<T>,
277        field_name: &'static str,
278    ) -> Result<Vec<u8>, crate::error::InternalError>
279    where
280        T: crate::traits::PersistedFieldMetaCodec,
281    {
282        crate::db::encode_persisted_option_slot_payload_by_meta(value, field_name)
283    }
284
285    #[doc(hidden)]
286    pub fn decode_persisted_option_slot_payload_by_meta<T>(
287        bytes: &[u8],
288        field_name: &'static str,
289    ) -> Result<Option<T>, crate::error::InternalError>
290    where
291        T: crate::traits::PersistedFieldMetaCodec,
292    {
293        crate::db::decode_persisted_option_slot_payload_by_meta(bytes, field_name)
294    }
295
296    #[doc(hidden)]
297    pub fn encode_persisted_many_slot_payload_by_meta<T>(
298        value: &[T],
299        field_name: &'static str,
300    ) -> Result<Vec<u8>, crate::error::InternalError>
301    where
302        T: crate::traits::FieldTypeMeta + crate::traits::RuntimeValueEncode,
303    {
304        crate::db::encode_persisted_many_slot_payload_by_meta(value, field_name)
305    }
306
307    #[doc(hidden)]
308    pub fn decode_persisted_many_slot_payload_by_meta<T>(
309        bytes: &[u8],
310        field_name: &'static str,
311    ) -> Result<Vec<T>, crate::error::InternalError>
312    where
313        T: crate::traits::FieldTypeMeta + crate::traits::RuntimeValueDecode,
314    {
315        crate::db::decode_persisted_many_slot_payload_by_meta(bytes, field_name)
316    }
317
318    #[doc(hidden)]
319    pub fn encode_persisted_slot_payload_by_meta<T>(
320        value: &T,
321        field_name: &'static str,
322    ) -> Result<Vec<u8>, crate::error::InternalError>
323    where
324        T: crate::traits::PersistedFieldMetaCodec,
325    {
326        crate::db::encode_persisted_slot_payload_by_meta(value, field_name)
327    }
328
329    #[doc(hidden)]
330    pub fn decode_persisted_slot_payload_by_meta<T>(
331        bytes: &[u8],
332        field_name: &'static str,
333    ) -> Result<T, crate::error::InternalError>
334    where
335        T: crate::traits::PersistedFieldMetaCodec,
336    {
337        crate::db::decode_persisted_slot_payload_by_meta(bytes, field_name)
338    }
339
340    #[doc(hidden)]
341    pub fn encode_schema_runtime_field_slot<T>(
342        model: &'static crate::model::entity::EntityModel,
343        slot: usize,
344        value: &T,
345    ) -> Result<Vec<u8>, crate::error::InternalError>
346    where
347        T: ?Sized + crate::traits::RuntimeValueEncode,
348    {
349        let runtime_value = value.to_value();
350
351        crate::db::encode_runtime_value_into_slot(model, slot, &runtime_value)
352    }
353
354    #[doc(hidden)]
355    pub fn decode_schema_runtime_field_slot<T>(
356        model: &'static crate::model::entity::EntityModel,
357        slot: usize,
358        bytes: &[u8],
359        field_name: &'static str,
360    ) -> Result<T, crate::error::InternalError>
361    where
362        T: crate::traits::RuntimeValueDecode,
363    {
364        let runtime_value = crate::db::decode_slot_into_runtime_value(model, slot, bytes)?;
365
366        T::from_value(&runtime_value).ok_or_else(|| {
367            crate::error::InternalError::persisted_row_field_decode_failed(
368                field_name,
369                format!("payload does not match {}", std::any::type_name::<T>()),
370            )
371        })
372    }
373}