1#![allow(clippy::result_large_err)]
3
4pub use shape_value::AlignedVec;
15
16pub mod alerts;
17pub mod annotation_context;
18pub mod arrow_c;
19pub mod ast_extensions;
20pub mod binary_reader;
21pub mod blob_prefetch;
22pub mod blob_store;
23pub mod blob_wire_format;
24pub mod builtin_metadata;
25pub mod chart_detect;
26pub mod closure;
27pub mod code_search;
28pub mod columnar_aggregations;
29pub mod const_eval;
30pub mod content_builders;
31pub mod content_dispatch;
32pub mod content_methods;
33pub mod content_renderer;
34pub mod context;
35pub mod crypto;
36pub mod data;
37pub mod dependency_resolver;
38pub mod distributed_gc;
39pub mod doc_extract;
40pub mod engine;
41pub mod event_queue;
42pub mod execution_proof;
43pub mod extension_context;
44pub mod extensions;
45pub mod extensions_config;
46pub mod frontmatter;
47pub mod fuzzy;
48pub mod fuzzy_property;
49pub mod hashing;
50pub mod intrinsics;
51pub mod join_executor;
52pub mod leakage;
53pub mod lookahead_guard;
54pub mod metadata;
55pub mod module_bindings;
56pub mod module_exports;
57pub mod module_loader;
58pub mod module_manifest;
59pub mod multi_table;
60pub mod multiple_testing;
61pub mod native_resolution;
62pub mod output_adapter;
63pub mod package_bundle;
64pub mod package_lock;
65pub mod pattern_library;
66pub mod pattern_state_machine;
67pub mod plugins;
68pub mod progress;
69pub mod project;
70#[cfg(all(test, feature = "deep-tests"))]
71mod project_deep_tests;
72pub mod provider_registry;
73pub mod query_builder;
74pub mod query_executor;
75pub mod query_result;
76pub mod renderers;
77pub mod schema_cache;
78pub mod schema_inference;
79pub mod simd_comparisons;
80pub mod simd_forward_fill;
81pub mod simd_i64;
82pub mod simd_rolling;
83pub mod simd_statistics;
84pub mod simulation;
85pub mod snapshot;
86pub mod state_diff;
87pub mod statistics;
88pub mod stdlib;
89pub mod stdlib_io;
90pub mod stdlib_metadata;
91pub mod stdlib_time;
92pub mod stream_executor;
93pub mod sync_bridge;
94pub mod time_window;
95pub mod timeframe_utils;
96pub mod type_mapping;
97pub mod type_methods;
98pub mod type_schema;
99pub mod type_system;
100pub mod visitor;
101pub mod window_executor;
102pub mod window_manager;
103pub mod wire_conversion;
104
105pub use alerts::{Alert, AlertRouter, AlertSeverity, AlertSink};
107pub use context::{DataLoadMode, ExecutionContext as Context};
108pub use data::DataFrame;
109pub use data::OwnedDataRow as RowValue;
110pub use event_queue::{
111 EventQueue, MemoryEventQueue, QueuedEvent, SharedEventQueue, SuspensionState, WaitCondition,
112 create_event_queue,
113};
114pub use extensions::{
115 ExtensionCapability, ExtensionDataSource, ExtensionLoader, ExtensionOutputSink,
116 LoadedExtension, ParsedOutputField, ParsedOutputSchema, ParsedQueryParam, ParsedQuerySchema,
117};
118pub use extensions_config::{
119 ExtensionEntry as GlobalExtensionEntry, ExtensionsConfig as GlobalExtensionsConfig,
120 load_extensions_config, load_extensions_config_from,
121};
122pub use hashing::{HashDigest, combine_hashes, hash_bytes, hash_file, hash_string};
123pub use intrinsics::{IntrinsicFn, IntrinsicsRegistry};
124pub use join_executor::JoinExecutor;
125pub use leakage::{LeakageDetector, LeakageReport, LeakageSeverity, LeakageType, LeakageWarning};
126pub use module_bindings::ModuleBindingRegistry;
127pub use module_exports::{
128 FrameInfo, ModuleContext, ModuleExportRegistry, ModuleExports, ModuleFn, VmStateAccessor,
129};
130pub use multiple_testing::{MultipleTestingGuard, MultipleTestingStats, WarningLevel};
131pub use progress::{
132 LoadPhase, ProgressEvent, ProgressGranularity, ProgressHandle, ProgressRegistry,
133};
134pub use query_result::{AlertResult, QueryResult, QueryType};
135use shape_value::ValueWord;
136pub use shape_value::ValueWord as Value;
137pub use stream_executor::{StreamEvent, StreamExecutor, StreamState};
138pub use sync_bridge::{
139 SyncDataProvider, block_on_shared, get_runtime_handle, initialize_shared_runtime,
140};
141pub use type_schema::{
142 FieldDef, FieldType, SchemaId, TypeSchema, TypeSchemaBuilder, TypeSchemaRegistry,
143};
144pub use window_executor::WindowExecutor;
145pub use wire_conversion::{
146 nb_extract_typed_value, nb_to_envelope, nb_to_wire, nb_typed_value_to_envelope, wire_to_nb,
147};
148
149use self::type_methods::TypeMethodRegistry;
150pub use error::{Result, ShapeError, SourceLocation};
151use shape_ast::ast::{Program, Query};
152pub use shape_ast::error;
153use shape_wire::WireValue;
154use std::collections::HashMap;
155use std::path::PathBuf;
156use std::sync::Arc;
157use std::sync::RwLock;
158use std::time::Duration;
159
160pub struct Runtime {
162 module_loader: module_loader::ModuleLoader,
164 persistent_context: Option<context::ExecutionContext>,
166 type_method_registry: Arc<TypeMethodRegistry>,
168 annotation_registry: Arc<RwLock<annotation_context::AnnotationRegistry>>,
170 module_binding_registry: Arc<RwLock<module_bindings::ModuleBindingRegistry>>,
172 debug_mode: bool,
174 execution_timeout: Option<Duration>,
176 memory_limit: Option<usize>,
178 last_runtime_error: Option<WireValue>,
183 blob_store: Option<Arc<dyn crate::blob_store::BlobStore>>,
185 keychain: Option<crate::crypto::keychain::Keychain>,
187}
188
189impl Default for Runtime {
190 fn default() -> Self {
191 Self::new()
192 }
193}
194
195impl Runtime {
196 pub fn new() -> Self {
198 Self::new_internal(true)
199 }
200
201 pub(crate) fn new_without_stdlib() -> Self {
202 Self::new_internal(false)
203 }
204
205 fn new_internal(_load_stdlib: bool) -> Self {
206 let module_loader = module_loader::ModuleLoader::new();
207 let module_binding_registry =
208 Arc::new(RwLock::new(module_bindings::ModuleBindingRegistry::new()));
209
210 Self {
211 module_loader,
212 persistent_context: None,
213 type_method_registry: Arc::new(TypeMethodRegistry::new()),
214 annotation_registry: Arc::new(RwLock::new(
215 annotation_context::AnnotationRegistry::new(),
216 )),
217 module_binding_registry,
218 debug_mode: false,
219 execution_timeout: None,
220 memory_limit: None,
221 last_runtime_error: None,
222 blob_store: None,
223 keychain: None,
224 }
225 }
226
227 pub fn annotation_registry(&self) -> Arc<RwLock<annotation_context::AnnotationRegistry>> {
228 self.annotation_registry.clone()
229 }
230
231 pub fn enable_persistent_context(&mut self, data: &DataFrame) {
232 self.persistent_context = Some(context::ExecutionContext::new_with_registry(
233 data,
234 self.type_method_registry.clone(),
235 ));
236 }
237
238 pub fn enable_persistent_context_without_data(&mut self) {
239 self.persistent_context = Some(context::ExecutionContext::new_empty_with_registry(
240 self.type_method_registry.clone(),
241 ));
242 }
243
244 pub fn set_persistent_context(&mut self, ctx: context::ExecutionContext) {
245 self.persistent_context = Some(ctx);
246 }
247
248 pub fn persistent_context(&self) -> Option<&context::ExecutionContext> {
249 self.persistent_context.as_ref()
250 }
251
252 pub fn persistent_context_mut(&mut self) -> Option<&mut context::ExecutionContext> {
253 self.persistent_context.as_mut()
254 }
255
256 pub fn set_last_runtime_error(&mut self, payload: Option<WireValue>) {
258 self.last_runtime_error = payload;
259 }
260
261 pub fn clear_last_runtime_error(&mut self) {
263 self.last_runtime_error = None;
264 }
265
266 pub fn last_runtime_error(&self) -> Option<&WireValue> {
268 self.last_runtime_error.as_ref()
269 }
270
271 pub fn take_last_runtime_error(&mut self) -> Option<WireValue> {
273 self.last_runtime_error.take()
274 }
275
276 pub fn type_method_registry(&self) -> &Arc<TypeMethodRegistry> {
277 &self.type_method_registry
278 }
279
280 pub fn module_binding_registry(&self) -> Arc<RwLock<module_bindings::ModuleBindingRegistry>> {
282 self.module_binding_registry.clone()
283 }
284
285 pub fn add_module_path(&mut self, path: PathBuf) {
290 self.module_loader.add_module_path(path);
291 }
292
293 pub fn set_keychain(&mut self, keychain: crate::crypto::keychain::Keychain) {
298 self.keychain = Some(keychain.clone());
299 self.module_loader.set_keychain(keychain);
300 }
301
302 pub fn set_blob_store(&mut self, store: Arc<dyn crate::blob_store::BlobStore>) {
307 self.blob_store = Some(store.clone());
308 self.module_loader.set_blob_store(store);
309 }
310
311 pub fn set_project_root(&mut self, root: &std::path::Path, extra_paths: &[PathBuf]) {
313 self.module_loader.set_project_root(root, extra_paths);
314 }
315
316 pub fn set_dependency_paths(
318 &mut self,
319 deps: std::collections::HashMap<String, std::path::PathBuf>,
320 ) {
321 self.module_loader.set_dependency_paths(deps);
322 }
323
324 pub fn get_dependency_paths(&self) -> &std::collections::HashMap<String, std::path::PathBuf> {
326 self.module_loader.get_dependency_paths()
327 }
328
329 pub fn register_extension_module_artifacts(
331 &mut self,
332 modules: &[crate::extensions::ParsedModuleSchema],
333 ) {
334 for module in modules {
335 for artifact in &module.artifacts {
336 let code = match (&artifact.source, &artifact.compiled) {
337 (Some(source), Some(compiled)) => module_loader::ModuleCode::Both {
338 source: Arc::from(source.as_str()),
339 compiled: Arc::from(compiled.clone()),
340 },
341 (Some(source), None) => {
342 module_loader::ModuleCode::Source(Arc::from(source.as_str()))
343 }
344 (None, Some(compiled)) => {
345 module_loader::ModuleCode::Compiled(Arc::from(compiled.clone()))
346 }
347 (None, None) => continue,
348 };
349 self.module_loader
350 .register_extension_module(artifact.module_path.clone(), code);
351 }
352 }
353 }
354
355 pub fn configured_module_loader(&self) -> module_loader::ModuleLoader {
360 let mut loader = self.module_loader.clone_without_cache();
361 if let Some(ref store) = self.blob_store {
362 loader.set_blob_store(store.clone());
363 }
364 if let Some(ref kc) = self.keychain {
365 loader.set_keychain(kc.clone());
366 }
367 loader
368 }
369
370 pub fn load_core_stdlib_into_context(&mut self, data: &DataFrame) -> Result<()> {
374 let module_paths = self.module_loader.list_core_stdlib_module_imports()?;
375
376 for module_path in module_paths {
377 if module_path == "std::core::prelude" {
381 continue;
382 }
383
384 let resolved = self.module_loader.resolve_module_path(&module_path).ok();
385 let context_dir = resolved
386 .as_ref()
387 .and_then(|path| path.parent().map(|p| p.to_path_buf()));
388 let module = self.module_loader.load_module(&module_path)?;
389 self.load_program_with_context(&module.ast, data, context_dir.as_ref())?;
390 }
391
392 Ok(())
393 }
394
395 pub fn load_program(&mut self, program: &Program, data: &DataFrame) -> Result<()> {
396 self.load_program_with_context(program, data, None)
397 }
398
399 pub(crate) fn load_program_with_context(
400 &mut self,
401 program: &Program,
402 data: &DataFrame,
403 context_dir: Option<&PathBuf>,
404 ) -> Result<()> {
405 let mut persistent_ctx = self.persistent_context.take();
406
407 let result = if let Some(ref mut ctx) = persistent_ctx {
408 if data.row_count() > 0 {
409 ctx.update_data(data);
410 }
411 self.process_program_items(program, ctx, context_dir)
412 } else {
413 let mut ctx = context::ExecutionContext::new_with_registry(
414 data,
415 self.type_method_registry.clone(),
416 );
417 self.process_program_items(program, &mut ctx, context_dir)
418 };
419
420 self.persistent_context = persistent_ctx;
421 result
422 }
423
424 fn process_program_items(
425 &mut self,
426 program: &Program,
427 ctx: &mut context::ExecutionContext,
428 context_dir: Option<&PathBuf>,
429 ) -> Result<()> {
430 for item in &program.items {
431 match item {
432 shape_ast::ast::Item::Import(import, _) => {
433 let module = self
434 .module_loader
435 .load_module_with_context(&import.from, context_dir)?;
436
437 match &import.items {
438 shape_ast::ast::ImportItems::Named(imports) => {
439 for import_spec in imports {
440 if let Some(export) = module.exports.get(&import_spec.name) {
441 if import_spec.is_annotation {
442 continue;
443 }
444 let var_name =
445 import_spec.alias.as_ref().unwrap_or(&import_spec.name);
446 match export {
447 module_loader::Export::Function(_) => {
448 }
450 module_loader::Export::Value(value) => {
451 if ctx.get_variable(var_name)?.is_none() {
452 ctx.set_variable(var_name, value.clone())?;
453 }
454 self.module_binding_registry
455 .write()
456 .unwrap()
457 .register_const(var_name, value.clone())?;
458 }
459 _ => {}
460 }
461 } else {
462 return Err(ShapeError::ModuleError {
463 message: format!(
464 "Export '{}' not found in module '{}'",
465 import_spec.name, import.from
466 ),
467 module_path: Some(import.from.clone().into()),
468 });
469 }
470 }
471 }
472 shape_ast::ast::ImportItems::Namespace { .. } => {
473 }
475 }
476 }
477 shape_ast::ast::Item::Export(export, _) => {
478 match &export.item {
479 shape_ast::ast::ExportItem::Function(_) => {
480 }
482 shape_ast::ast::ExportItem::BuiltinFunction(_)
483 | shape_ast::ast::ExportItem::BuiltinType(_)
484 | shape_ast::ast::ExportItem::Annotation(_) => {}
485 shape_ast::ast::ExportItem::Named(specs) => {
486 for spec in specs {
487 if let Ok(value) = ctx.get_variable(&spec.name) {
488 if value.is_none() {
489 return Err(ShapeError::RuntimeError {
490 message: format!(
491 "Cannot export undefined variable '{}'",
492 spec.name
493 ),
494 location: None,
495 });
496 }
497 }
498 }
499 }
500 shape_ast::ast::ExportItem::TypeAlias(alias_def) => {
501 let overrides = HashMap::new();
502 if let Some(ref overrides_ast) = alias_def.meta_param_overrides {
503 for (_key, _expr) in overrides_ast {
504 }
506 }
507
508 let base_type = match &alias_def.type_annotation {
509 shape_ast::ast::TypeAnnotation::Basic(n) => n.clone(),
510 shape_ast::ast::TypeAnnotation::Reference(n) => n.to_string(),
511 _ => "any".to_string(),
512 };
513
514 ctx.register_type_alias(&alias_def.name, &base_type, Some(overrides));
515 }
516 shape_ast::ast::ExportItem::Enum(enum_def) => {
517 ctx.register_enum(enum_def.clone());
518 }
519 shape_ast::ast::ExportItem::Struct(struct_def) => {
520 ctx.register_struct_type(struct_def.clone());
521 }
522 shape_ast::ast::ExportItem::Interface(_)
523 | shape_ast::ast::ExportItem::Trait(_) => {
524 }
526 shape_ast::ast::ExportItem::ForeignFunction(_) => {
527 }
529 }
530 }
531 shape_ast::ast::Item::Function(_function, _) => {
532 }
534 shape_ast::ast::Item::TypeAlias(alias_def, _) => {
535 let overrides = HashMap::new();
536 if let Some(ref overrides_ast) = alias_def.meta_param_overrides {
537 for (_key, _expr) in overrides_ast {
538 }
540 }
541
542 let base_type = match &alias_def.type_annotation {
543 shape_ast::ast::TypeAnnotation::Basic(n) => n.clone(),
544 shape_ast::ast::TypeAnnotation::Reference(n) => n.to_string(),
545 _ => "any".to_string(),
546 };
547
548 ctx.register_type_alias(&alias_def.name, &base_type, Some(overrides));
549 }
550 shape_ast::ast::Item::Interface(_, _) => {}
551 shape_ast::ast::Item::Trait(_, _) => {}
552 shape_ast::ast::Item::Impl(_, _) => {}
553 shape_ast::ast::Item::Enum(enum_def, _) => {
554 ctx.register_enum(enum_def.clone());
555 }
556 shape_ast::ast::Item::StructType(struct_def, _) => {
557 ctx.register_struct_type(struct_def.clone());
558 }
559 shape_ast::ast::Item::Extend(extend_stmt, _) => {
560 let registry = ctx.type_method_registry();
561 for method in &extend_stmt.methods {
562 registry.register_method(&extend_stmt.type_name, method.clone());
563 }
564 }
565 shape_ast::ast::Item::AnnotationDef(ann_def, _) => {
566 self.annotation_registry
567 .write()
568 .unwrap()
569 .register(ann_def.clone());
570 }
571 _ => {}
572 }
573 }
574 Ok(())
575 }
576
577 pub fn execute_query(
578 &mut self,
579 query: &shape_ast::ast::Item,
580 data: &DataFrame,
581 ) -> Result<QueryResult> {
582 let mut persistent_ctx = self.persistent_context.take();
583 let result = if let Some(ref mut ctx) = persistent_ctx {
584 ctx.update_data(data);
585 self.execute_query_with_context(query, ctx)
586 } else {
587 let mut ctx = context::ExecutionContext::new_with_registry(
588 data,
589 self.type_method_registry.clone(),
590 );
591 self.execute_query_with_context(query, &mut ctx)
592 };
593 self.persistent_context = persistent_ctx;
594 result
595 }
596
597 fn execute_query_with_context(
598 &mut self,
599 query: &shape_ast::ast::Item,
600 ctx: &mut context::ExecutionContext,
601 ) -> Result<QueryResult> {
602 let id = ctx.get_current_id().unwrap_or_default();
603 let timeframe = ctx
604 .get_current_timeframe()
605 .map(|t| t.to_string())
606 .unwrap_or_default();
607
608 match query {
609 shape_ast::ast::Item::Query(q, _) => match q {
610 Query::Backtest(_) => Err(ShapeError::RuntimeError {
611 message: "Backtesting not supported in core runtime.".to_string(),
612 location: None,
613 }),
614 Query::Alert(_alert_query) => {
615 let alert_id = format!("alert_{}", chrono::Utc::now().timestamp_micros());
616 Ok(
617 QueryResult::new(QueryType::Alert, id, timeframe).with_alert(AlertResult {
618 id: alert_id,
619 active: false,
620 message: "Alert triggered".to_string(),
621 level: "info".to_string(),
622 timestamp: chrono::Utc::now(),
623 }),
624 )
625 }
626 Query::With(with_query) => {
627 for cte in &with_query.ctes {
628 let cte_result = self.execute_query_with_context(
629 &shape_ast::ast::Item::Query(
630 (*cte.query).clone(),
631 shape_ast::ast::Span::DUMMY,
632 ),
633 ctx,
634 )?;
635 let value = cte_result.value.unwrap_or(ValueWord::none());
636 ctx.set_variable_nb(&cte.name, value)?;
637 }
638 self.execute_query_with_context(
639 &shape_ast::ast::Item::Query(
640 (*with_query.query).clone(),
641 shape_ast::ast::Span::DUMMY,
642 ),
643 ctx,
644 )
645 }
646 },
647 shape_ast::ast::Item::Expression(_, _) => {
648 Ok(QueryResult::new(QueryType::Value, id, timeframe).with_value(ValueWord::none()))
649 }
650 shape_ast::ast::Item::VariableDecl(var_decl, _) => {
651 ctx.declare_pattern(&var_decl.pattern, var_decl.kind, ValueWord::none())?;
652 Ok(QueryResult::new(QueryType::Value, id, timeframe).with_value(ValueWord::none()))
653 }
654 shape_ast::ast::Item::Assignment(assignment, _) => {
655 ctx.set_pattern(&assignment.pattern, ValueWord::none())?;
656 Ok(QueryResult::new(QueryType::Value, id, timeframe).with_value(ValueWord::none()))
657 }
658 shape_ast::ast::Item::Statement(_, _) => {
659 Ok(QueryResult::new(QueryType::Value, id, timeframe).with_value(ValueWord::none()))
660 }
661 _ => Err(ShapeError::RuntimeError {
662 message: format!("Unsupported item for query execution: {:?}", query),
663 location: None,
664 }),
665 }
666 }
667
668 pub fn execute_without_data(&mut self, item: &shape_ast::ast::Item) -> Result<QueryResult> {
669 let mut persistent_ctx = self.persistent_context.take();
670
671 let result = if let Some(ref mut ctx) = persistent_ctx {
672 match item {
673 shape_ast::ast::Item::Expression(_, _) => {
674 Ok(
675 QueryResult::new(QueryType::Value, "".to_string(), "".to_string())
676 .with_value(ValueWord::none()),
677 )
678 }
679 shape_ast::ast::Item::Statement(_, _) => {
680 Ok(
681 QueryResult::new(QueryType::Value, "".to_string(), "".to_string())
682 .with_value(ValueWord::none()),
683 )
684 }
685 shape_ast::ast::Item::VariableDecl(var_decl, _) => {
686 ctx.declare_pattern(&var_decl.pattern, var_decl.kind, ValueWord::none())?;
687 Ok(
688 QueryResult::new(QueryType::Value, "".to_string(), "".to_string())
689 .with_value(ValueWord::none()),
690 )
691 }
692 shape_ast::ast::Item::Assignment(assignment, _) => {
693 ctx.set_pattern(&assignment.pattern, ValueWord::none())?;
694 Ok(
695 QueryResult::new(QueryType::Value, "".to_string(), "".to_string())
696 .with_value(ValueWord::none()),
697 )
698 }
699 shape_ast::ast::Item::TypeAlias(_, _) => {
700 self.process_program_items(
701 &Program {
702 items: vec![item.clone()],
703 docs: shape_ast::ast::ProgramDocs::default(),
704 },
705 ctx,
706 None,
707 )?;
708 Ok(
709 QueryResult::new(QueryType::Value, "".to_string(), "".to_string())
710 .with_value(ValueWord::none()),
711 )
712 }
713 _ => Err(ShapeError::RuntimeError {
714 message: format!("Operation requires context: {:?}", item),
715 location: None,
716 }),
717 }
718 } else {
719 let mut ctx = context::ExecutionContext::new_empty_with_registry(
720 self.type_method_registry.clone(),
721 );
722 self.process_program_items(
723 &Program {
724 items: vec![item.clone()],
725 docs: shape_ast::ast::ProgramDocs::default(),
726 },
727 &mut ctx,
728 None,
729 )?;
730 persistent_ctx = Some(ctx);
731 Ok(
732 QueryResult::new(QueryType::Value, "".to_string(), "".to_string())
733 .with_value(ValueWord::none()),
734 )
735 };
736
737 self.persistent_context = persistent_ctx;
738 result
739 }
740
741 pub fn format_value(
745 &mut self,
746 _value: Value,
747 type_name: &str,
748 format_name: Option<&str>,
749 _param_overrides: std::collections::HashMap<String, Value>,
750 ) -> Result<String> {
751 if let Some(name) = format_name {
752 Ok(format!("<formatted {} as {}>", type_name, name))
753 } else {
754 Ok(format!("<formatted {}>", type_name))
755 }
756 }
757
758 pub fn set_debug_mode(&mut self, enabled: bool) {
763 self.debug_mode = enabled;
764 if enabled {
765 tracing::debug!("Shape runtime debug mode enabled");
766 }
767 }
768
769 pub fn debug_mode(&self) -> bool {
771 self.debug_mode
772 }
773
774 pub fn set_execution_timeout(&mut self, timeout: Duration) {
779 self.execution_timeout = Some(timeout);
780 }
781
782 pub fn execution_timeout(&self) -> Option<Duration> {
784 self.execution_timeout
785 }
786
787 pub fn set_memory_limit(&mut self, limit: usize) {
792 self.memory_limit = Some(limit);
793 }
794
795 pub fn memory_limit(&self) -> Option<usize> {
797 self.memory_limit
798 }
799}