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