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