aiscript_vm/vm/
extra.rs

1use std::collections::HashMap;
2
3use aiscript_arena::{Gc, RefLock};
4
5use crate::{
6    NativeFn, ReturnValue, Value,
7    builtins::response,
8    object::{Instance, Object},
9};
10
11use super::Vm;
12
13impl Vm {
14    pub fn get_global(&mut self, name: &'static str) -> Option<ReturnValue> {
15        self.arena.mutate_root(|_mc, state| {
16            let name = state.intern_static(name);
17            state.globals.get(&name).copied().map(ReturnValue::from)
18        })
19    }
20
21    pub fn register_extra_native_functions(&mut self) {
22        self.arena.mutate_root(|_mc, state| {
23            state.define_native_function("response", NativeFn(response::response));
24            state.define_native_function(
25                "temporary_redirect",
26                NativeFn(response::temporary_redirect),
27            );
28            state.define_native_function(
29                "permanent_redirect",
30                NativeFn(response::permanent_redirect),
31            );
32        });
33    }
34
35    pub fn inject_sso_instance<K>(&mut self, fields: HashMap<K, serde_json::Value>)
36    where
37        K: AsRef<str> + Eq,
38    {
39        self.arena.mutate_root(|mc, state| {
40            let ctx = state.get_context();
41            let name = state.intern_static("sso");
42            let class = crate::builtins::sso::create_sso_provider_class(ctx);
43            let mut instance = Instance::new(class);
44            for (key, value) in fields {
45                instance.fields.insert(
46                    state.intern(key.as_ref().as_bytes()),
47                    Value::from_serde_value(ctx, &value),
48                );
49            }
50            state
51                .globals
52                .insert(name, Gc::new(mc, RefLock::new(instance)).into());
53        });
54    }
55
56    pub fn inject_variables(&mut self, variables: HashMap<String, serde_json::Value>) {
57        self.arena.mutate_root(|_mc, state| {
58            let ctx = state.get_context();
59            for (key, value) in variables {
60                let name = state.intern(key.as_bytes());
61                state
62                    .globals
63                    .insert(name, Value::from_serde_value(ctx, &value));
64            }
65        });
66    }
67
68    pub fn inject_object<K>(&mut self, name: &'static str, fields: HashMap<K, serde_json::Value>)
69    where
70        K: AsRef<str> + Eq,
71    {
72        self.arena.mutate_root(|mc, state| {
73            let ctx = state.get_context();
74            let name = state.intern_static(name);
75            let mut obj = Object::default();
76            for (key, value) in fields {
77                obj.fields.insert(
78                    state.intern(key.as_ref().as_bytes()),
79                    Value::from_serde_value(ctx, &value),
80                );
81            }
82            state
83                .globals
84                .insert(name, Value::Object(Gc::new(mc, RefLock::new(obj))));
85        });
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use crate::ReturnValue;
92
93    use super::*;
94
95    #[test]
96    fn test_inject_variables() {
97        let mut vm = Vm::default();
98        vm.inject_variables({
99            let mut map = HashMap::new();
100            map.insert("test".into(), "abc".into());
101            map.insert("test2".into(), 123.into());
102            map.insert("test3".into(), true.into());
103            map
104        });
105        vm.compile("return test;").unwrap();
106        let result = vm.interpret().unwrap();
107        assert_eq!(result, ReturnValue::String("abc".into()));
108        vm.compile("return test2;").unwrap();
109        let result = vm.interpret().unwrap();
110        assert_eq!(result, ReturnValue::Number(123.0));
111        vm.compile("return test3;").unwrap();
112        let result = vm.interpret().unwrap();
113        assert_eq!(result, ReturnValue::Boolean(true));
114    }
115
116    #[test]
117    fn test_inject_instance() {
118        let mut vm = Vm::default();
119        vm.inject_object("request", {
120            let mut map = HashMap::new();
121            map.insert("method", "get".into());
122            map.insert("code", 200.0.into());
123            map.insert("test", true.into());
124            map
125        });
126        vm.compile("return request;").unwrap();
127        let result = vm.interpret().unwrap();
128        let request = result.as_object().unwrap();
129        assert_eq!(request.get("method").unwrap(), "get");
130        assert_eq!(request.get("code").unwrap(), 200.0);
131        assert_eq!(request.get("test").unwrap(), true);
132        assert!(request.get("abc").is_none());
133    }
134}