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