brooks_lib/dcdn/processors/
mel.rs1use crate::{
21 cdni::mel::spec::TypedSetVariable,
22 dcdn::{
23 imdi,
24 interpret::{
25 Error::{self, InvalidType},
26 MetadataInformationResultElements, Stages,
27 },
28 processors::SimpleProcessorsInterpreterContext,
29 },
30 logging::{LogLevel::Debug, LogMsgs},
31 mel::{
32 self, MEL_USER_SET_VARIABLE_STRUCT_NAME,
33 interpreter::{
34 interpret::MelInterpContext,
35 values::{TypedValue, Value},
36 },
37 types::{Struct, Type},
38 },
39 processing::interpret::{InterpretationResult, Interpreter},
40 verifying::mel::verify::SetVariableVerificationKey,
41};
42
43impl
44 Interpreter<
45 SimpleProcessorsInterpreterContext<'_>,
46 (imdi::ResultValue, MetadataInformationResultElements),
47 Stages,
48 Error,
49 > for TypedSetVariable<SetVariableVerificationKey>
50{
51 fn interpret<'a>(
52 &self,
53 input: SimpleProcessorsInterpreterContext<'a>,
54 ) -> InterpretationResult<
55 SimpleProcessorsInterpreterContext<'a>,
56 (imdi::ResultValue, MetadataInformationResultElements),
57 Error,
58 > {
59 let lmsgs = LogMsgs::new(Debug);
60
61 let var = input
63 .scopes
64 .lookup(MEL_USER_SET_VARIABLE_STRUCT_NAME)
65 .ok_or(Error::RuntimeError("var not in scope".into()))?;
66
67 let (mut var, var_tpe) = match var {
68 TypedValue {
69 value: Value::Struct(value),
70 tpe: Type::Struct(tpe),
71 } => (value, tpe),
72 TypedValue { value: _, tpe } => {
73 return Err(InvalidType(
74 Type::Struct(Struct::new(MEL_USER_SET_VARIABLE_STRUCT_NAME)).to_string(),
75 tpe.to_string(),
76 )
77 .into());
78 }
79 };
80
81 if let Some(expression) = &self.value.aug.expression {
82 let result = mel::interpreter::interpret(
83 expression,
84 MelInterpContext {
85 val: None,
86 scopes: input.scopes.clone(),
87 log: lmsgs,
88 },
89 )
90 .map_err(|e| Error::RuntimeError(Box::new(e)))?;
91
92 var.insert_field(
93 &self.value.variable_name,
94 result.val.ok_or(Error::RuntimeError(
95 "Missing value after successful interpretation of Mel expression".into(),
96 ))?,
97 )
98 .map_err(|e| Error::RuntimeError(e))?;
99
100 let output = input.with_new_value_in_scope(
101 MEL_USER_SET_VARIABLE_STRUCT_NAME,
102 TypedValue {
103 value: Value::Struct(var),
104 tpe: Type::Struct(var_tpe),
105 },
106 );
107
108 Ok((output, (None, MetadataInformationResultElements::default())))
109 } else if let Some(_value) = &self.value.aug.value {
110 todo!()
111 } else {
112 todo!()
113 }
114 }
115
116 fn at(&self, stage: Stages) -> bool {
117 stage == Stages::Pre
118 }
119}
120
121#[cfg(test)]
122mod test {
123 use std::{assert_matches, str::FromStr};
124
125 use url::Url;
126
127 use crate::{
128 cdni::{
129 mel::spec::TypedSetVariable,
130 tests::test_helpers::{generic_metadata, set_variable},
131 },
132 dcdn::{
133 imdi, interpret::ProcessedRequestResponse,
134 processors::SimpleProcessorsInterpreterContext,
135 },
136 environment::scope::Scopes,
137 mel::{
138 MEL_USER_SET_VARIABLE_STRUCT_NAME,
139 interpreter::values::{TypedValue, Value, mel_var_value_from_type},
140 types::{Type, builtin_function_types, minimal_core_variable_types},
141 },
142 processing::interpret::Interpreter,
143 verifying::{
144 mel::verify::SetVariableMetadataAnalyzer,
145 verify::{CdniVerificationKey, MetadataAnalysisContext, Verifier},
146 },
147 };
148
149 #[test]
150 fn verify_test() {
151 let variable = set_variable("is_bad".to_string(), "true".to_string(), Some(true));
152
153 let json = generic_metadata(
154 &TypedSetVariable::<()>::typed_cdni_metadata_name(),
155 Some(
156 serde_json::to_value(variable.value)
157 .expect("Could not convert valid SetVariable to Value"),
158 ),
159 );
160
161 let svma = SetVariableMetadataAnalyzer {};
162
163 let result = svma
164 .analyze(
165 &json,
166 MetadataAnalysisContext {
167 scopes: (&builtin_function_types() + &minimal_core_variable_types()).into(),
168 },
169 )
170 .expect("Could not analyze correct MI.SetVariable");
171
172 let svmi = match result.1 {
173 CdniVerificationKey::SetVariable(typed_set_variable) => typed_set_variable,
174 _ => panic!("Result of verifying correct MI.SetVariable was of incorrect type"),
175 };
176
177 let var = result
178 .0
179 .scopes
180 .lookup(MEL_USER_SET_VARIABLE_STRUCT_NAME)
181 .expect("Could not get the var struct from the types of the analyzed generic metadata");
182
183 let var = match var {
184 Type::Struct(s) => s,
185 _ => panic!("var had the wrong type in the analyzed generic metadata"),
186 };
187
188 let rt = tokio::runtime::Builder::new_current_thread()
189 .build()
190 .expect("Could not get a runtime to use for testing interpret function");
191 let result = svmi
192 .interpret(SimpleProcessorsInterpreterContext {
193 scopes: Scopes::<TypedValue>::default().insert(
194 MEL_USER_SET_VARIABLE_STRUCT_NAME,
195 mel_var_value_from_type(var),
196 ),
197 mode: imdi::InterpretMode::Request,
198 runtime: rt.handle(),
199 req: Box::new(ProcessedRequestResponse::new_request(
200 &Url::from_str("http://www.example.com/")
201 .expect("Could not get a URI from a valid HTTP address"),
202 &http::Method::GET,
203 )),
204 res: None,
205 })
206 .expect("Could not interpret correct MI.SetVariable");
207
208 let value = match result
209 .0
210 .scopes
211 .lookup(MEL_USER_SET_VARIABLE_STRUCT_NAME)
212 .unwrap_or_else(|| {
213 panic!(
214 "Could not get {} from resulting scope",
215 MEL_USER_SET_VARIABLE_STRUCT_NAME
216 )
217 }) {
218 TypedValue {
219 value: Value::Struct(s),
220 tpe: Type::Struct(_),
221 } => s.fields.get("is_bad").cloned(),
222 _ => panic!(
223 "{} is not a struct in resulting scope",
224 MEL_USER_SET_VARIABLE_STRUCT_NAME
225 ),
226 };
227
228 let value = match value {
229 Some(v) => v,
230 None => panic!(
231 "is_bad field of {} does not have a value in resulting scope",
232 MEL_USER_SET_VARIABLE_STRUCT_NAME
233 ),
234 };
235 assert_matches!(value, TypedValue{ value: Value::Boolean(v), tpe: _} if v)
236 }
237}