use super::{services::ForeignFunctionVmServices, ForeignArguments, ForeignFunctionCallbackResult};
use crate::error::VmResult;
use crate::runtime_hooks::HookEvent;
use parking_lot::Mutex;
use std::sync::Arc;
use stoffel_vm_types::core_types::{ForeignObjectRef, Value};
pub struct ForeignFunctionContext<'a> {
pub(super) args: &'a [Value],
pub(super) services: &'a mut dyn ForeignFunctionVmServices,
}
impl<'a> ForeignFunctionContext<'a> {
pub(crate) fn new(args: &'a [Value], services: &'a mut dyn ForeignFunctionVmServices) -> Self {
Self { args, services }
}
pub fn args(&self) -> &[Value] {
self.args
}
pub fn len(&self) -> usize {
self.args.len()
}
pub fn is_empty(&self) -> bool {
self.args.is_empty()
}
pub fn arg(&self, index: usize) -> Option<&Value> {
self.args.get(index)
}
pub fn named_args(&self, function: &'static str) -> ForeignArguments<'_> {
ForeignArguments::new(function, self.args)
}
pub fn get_foreign_object<T: 'static + Send + Sync>(
&self,
object_ref: ForeignObjectRef,
) -> Option<Arc<Mutex<T>>> {
self.services
.get_foreign_object_any_ref(object_ref)
.and_then(|object| object.downcast::<Mutex<T>>().ok())
}
pub fn get_foreign_object_ref<T: 'static + Send + Sync>(
&self,
object_ref: ForeignObjectRef,
) -> Option<Arc<Mutex<T>>> {
self.get_foreign_object(object_ref)
}
pub fn write_output_line(&self, line: &str) -> ForeignFunctionCallbackResult<()> {
Ok(self.services.write_output_line(line)?)
}
pub(crate) fn trigger_hook_with_snapshot(&self, event: &HookEvent) -> VmResult<()> {
self.services.trigger_hook_with_snapshot(event)
}
pub(crate) fn hooks_enabled(&self) -> bool {
self.services.hooks_enabled()
}
pub(crate) fn create_closure_value(
&mut self,
function_name: String,
upvalue_names: &[String],
) -> VmResult<Value> {
self.services
.create_closure_value(function_name, upvalue_names)
}
pub(crate) fn call_closure_value(
&mut self,
closure_value: &Value,
args: &[Value],
) -> VmResult<()> {
self.services.call_closure_value(closure_value, args)
}
pub(crate) fn get_upvalue_value(&self, name: &str) -> VmResult<Value> {
self.services.get_upvalue_value(name)
}
pub(crate) fn set_upvalue_value(&mut self, name: &str, new_value: Value) -> VmResult<()> {
self.services.set_upvalue_value(name, new_value)
}
}