1use crate::bindings::{RequestBinding, ResponseBinding};
4use rhai::{Dynamic, Map, Scope};
5use std::collections::HashMap;
6use std::sync::Arc;
7
8#[derive(Debug, Clone)]
12pub struct ScriptContext {
13 pub request: RequestBinding,
15 pub state: Arc<HashMap<String, Dynamic>>,
17 pub locals: HashMap<String, Dynamic>,
19}
20
21impl ScriptContext {
22 pub fn new(request: RequestBinding) -> Self {
24 Self {
25 request,
26 state: Arc::new(HashMap::new()),
27 locals: HashMap::new(),
28 }
29 }
30
31 pub fn with_state(request: RequestBinding, state: Arc<HashMap<String, Dynamic>>) -> Self {
33 Self {
34 request,
35 state,
36 locals: HashMap::new(),
37 }
38 }
39
40 pub fn set_local(&mut self, key: impl Into<String>, value: Dynamic) {
42 self.locals.insert(key.into(), value);
43 }
44
45 pub fn get_local(&self, key: &str) -> Option<&Dynamic> {
47 self.locals.get(key)
48 }
49
50 pub fn get_state(&self, key: &str) -> Option<&Dynamic> {
52 self.state.get(key)
53 }
54
55 pub fn into_scope(self) -> Scope<'static> {
57 let mut scope = Scope::new();
58
59 scope.push_constant("request", self.request);
61
62 scope.push("response", ResponseBinding::new());
64
65 let mut state_map = Map::new();
67 for (key, value) in self.state.iter() {
68 state_map.insert(key.clone().into(), value.clone());
69 }
70 scope.push_constant("state", state_map);
71
72 for (key, value) in self.locals {
74 scope.push(&key, value);
75 }
76
77 scope
78 }
79}
80
81pub struct ScriptContextBuilder {
83 request: Option<RequestBinding>,
84 state: HashMap<String, Dynamic>,
85 locals: HashMap<String, Dynamic>,
86}
87
88impl Default for ScriptContextBuilder {
89 fn default() -> Self {
90 Self::new()
91 }
92}
93
94impl ScriptContextBuilder {
95 pub fn new() -> Self {
97 Self {
98 request: None,
99 state: HashMap::new(),
100 locals: HashMap::new(),
101 }
102 }
103
104 pub fn request(mut self, request: RequestBinding) -> Self {
106 self.request = Some(request);
107 self
108 }
109
110 pub fn state(mut self, key: impl Into<String>, value: impl Into<Dynamic>) -> Self {
112 self.state.insert(key.into(), value.into());
113 self
114 }
115
116 pub fn local(mut self, key: impl Into<String>, value: impl Into<Dynamic>) -> Self {
118 self.locals.insert(key.into(), value.into());
119 self
120 }
121
122 pub fn build(self) -> Option<ScriptContext> {
124 let request = self.request?;
125 Some(ScriptContext {
126 request,
127 state: Arc::new(self.state),
128 locals: self.locals,
129 })
130 }
131}
132