1use std::{
21 collections::HashMap,
22 fmt::{Debug, Display},
23 io,
24 net::IpAddr,
25 sync::Arc,
26};
27
28use regex::Regex;
29
30use crate::{
31 environment::scope::Scope,
32 mel::{
33 interpreter::{error::InterpError, interpret::BuiltinFunction},
34 types::{
35 mel_empty_var_type, mel_header_type_from_processable_rr, mel_header_type_from_req,
36 mel_req_type, mel_uri_type,
37 },
38 },
39 prr,
40};
41
42use crate::mel::{
43 analysis::CompiledConstant,
44 types::{Struct, Type},
45};
46
47#[derive(Debug, Clone)]
48pub struct StructValue {
49 pub fields: HashMap<String, TypedValue>,
50 pub tpe: Struct,
51}
52
53impl StructValue {
54 pub fn new(tpe: Struct) -> StructValue {
55 StructValue {
56 fields: HashMap::new(),
57 tpe,
58 }
59 }
60
61 pub fn insert_field(&mut self, name: &str, value: TypedValue) -> Result<(), Box<InterpError>> {
62 let ft = self
63 .tpe
64 .get_field(name)
65 .ok_or(InterpError::UnknownField(name.to_string()))?;
66
67 if ft != value.tpe {
68 return Err(InterpError::MistypedField(name.to_string(), ft.clone(), value.tpe).into());
69 }
70
71 self.fields.insert(name.to_string(), value);
72 Ok(())
73 }
74}
75
76impl Display for StructValue {
77 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78 let mut field_values = self
79 .fields
80 .iter()
81 .map(|(k, v)| format!("{k}: {v}"))
82 .collect::<Vec<_>>();
83 field_values.sort();
84 let field_values = field_values.join(", ");
85 write!(
86 f,
87 "Type: {}, Field Values: {}",
88 self.tpe.name,
89 if !field_values.is_empty() {
90 field_values
91 } else {
92 "None".to_string()
93 }
94 )
95 }
96}
97
98#[derive(Default, Debug, Clone)]
99pub enum Value {
100 Integer(i64),
101 Unsigned(u64),
102 Real(f64),
103 String(String),
104 Boolean(bool),
105 Regex(Regex),
106 IPAddress(IpAddr),
107 Function(Arc<dyn BuiltinFunction>),
108 Struct(StructValue),
109 ArgumentList(Vec<TypedValue>),
110 Nil,
111 #[default]
112 Uninitialized,
113}
114
115#[derive(Default, Debug, Clone)]
116pub struct TypedValue {
117 pub value: Value,
118 pub tpe: Type,
119}
120
121impl Display for TypedValue {
122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123 match &self.value {
124 Value::Nil => write!(f, "nil"),
125 Value::Integer(i) => write!(f, "{i}"),
126 Value::Unsigned(u) => write!(f, "{u}"),
127 Value::Real(i) => write!(f, "{i}"),
128 Value::String(s) => write!(f, "{s}"),
129 Value::Boolean(b) => write!(f, "{b}"),
130 Value::Regex(regex) => write!(f, "{regex}"),
131 Value::IPAddress(ip_addr) => write!(f, "{ip_addr}"),
132 Value::Function(bft) => write!(f, "Function: {}", bft.name()),
133 Value::Struct(struct_value) => write!(f, "{}", struct_value),
134 Value::ArgumentList(typed_values) => write!(
135 f,
136 "Argument List: {}",
137 typed_values
138 .iter()
139 .map(|tv| { tv.to_string() })
140 .collect::<Vec<_>>()
141 .join(",")
142 ),
143 Value::Uninitialized => write!(f, "Uninitialized"),
144 }
145 }
146}
147
148impl From<&CompiledConstant> for TypedValue {
149 fn from(value: &CompiledConstant) -> Self {
150 match value {
151 CompiledConstant::Integer(i) => TypedValue {
152 value: Value::Integer(*i),
153 tpe: Type::Integer,
154 },
155 CompiledConstant::String(s) => TypedValue {
156 value: Value::String(s.clone()),
157 tpe: Type::String,
158 },
159 CompiledConstant::Boolean(b) => TypedValue {
160 value: Value::Boolean(*b),
161 tpe: Type::Boolean,
162 },
163 CompiledConstant::IPAddress(ip) => TypedValue {
164 value: Value::IPAddress(*ip),
165 tpe: Type::IPAddress,
166 },
167 }
168 }
169}
170
171impl TryFrom<http::Request<Vec<u8>>> for Scope<TypedValue> {
172 type Error = io::Error;
173 fn try_from(value: http::Request<Vec<u8>>) -> Result<Self, Self::Error> {
174 let ht = mel_header_type_from_req(&value);
175 let urit = mel_uri_type();
176 let reqt = mel_req_type(ht.clone(), urit.clone());
177
178 let mut value_scope = Scope::<TypedValue>::default();
180
181 let mut reqv = StructValue::new(reqt.clone());
182
183 let mut hv = StructValue::new(ht.clone());
184
185 value.headers().iter().for_each(|header| {
186 if let Ok(x) = header.1.to_str() {
187 hv.insert_field(
188 &header.0.to_string().replace("-", "_").to_lowercase(),
189 TypedValue {
190 value: Value::String(x.to_string()),
191 tpe: Type::String,
192 },
193 )
194 .expect("header field value is mistyped");
195 }
196 });
197
198 let mut uriv = StructValue::new(urit.clone());
199
200 uriv.insert_field(
201 "path",
202 TypedValue {
203 value: Value::String(value.uri().path().to_string()),
204 tpe: Type::String,
205 },
206 )
207 .expect("path field value is mistyped.");
208
209 uriv.insert_field(
210 "query",
211 TypedValue {
212 value: Value::String(value.uri().query().unwrap_or_default().to_string()),
213 tpe: Type::String,
214 },
215 )
216 .expect("query field value is mistyped.");
217
218 reqv.insert_field(
219 "h",
220 TypedValue {
221 value: Value::Struct(hv),
222 tpe: Type::Struct(ht.clone()),
223 },
224 )
225 .expect("h field value is mistyped.");
226
227 reqv.insert_field(
228 "uri",
229 TypedValue {
230 value: Value::Struct(uriv),
231 tpe: Type::Struct(urit.clone()),
232 },
233 )
234 .expect("uri field value is mistyped.");
235
236 reqv.insert_field(
237 "method",
238 TypedValue {
239 value: Value::String(value.method().to_string()),
240 tpe: Type::String,
241 },
242 )
243 .expect("method field value is mistyped.");
244
245 reqv.insert_field(
246 "scheme",
247 TypedValue {
248 value: Value::String(value.uri().scheme().expect("Missing scheme").to_string()),
249 tpe: Type::String,
250 },
251 )
252 .expect("Header field value is mistyped.");
253
254 value_scope = value_scope.insert(
255 "req",
256 TypedValue {
257 value: Value::Struct(reqv),
258 tpe: Type::Struct(reqt),
259 },
260 );
261
262 Ok(value_scope)
263 }
264}
265
266impl<A> From<&dyn prr::Prr<A>> for Scope<TypedValue> {
268 fn from(value: &dyn prr::Prr<A>) -> Self {
269 let ht = mel_header_type_from_processable_rr(value);
270 let urit = mel_uri_type();
271 let reqt = mel_req_type(ht.clone(), urit.clone());
272
273 let mut value_scope = Scope::<TypedValue>::default();
275
276 let mut reqv = StructValue::new(reqt.clone());
277
278 let mut hv = StructValue::new(ht.clone());
279
280 value.headers().iter().for_each(|header| {
281 if let Ok(x) = header.1.to_str() {
282 hv.insert_field(
283 &header.0.to_string().replace("-", "_").to_lowercase(),
284 TypedValue {
285 value: Value::String(x.to_string()),
286 tpe: Type::String,
287 },
288 )
289 .expect("header field value is mistyped");
290 }
291 });
292
293 let mut uriv = StructValue::new(urit.clone());
294
295 uriv.insert_field(
296 "path",
297 TypedValue {
298 value: Value::String(value.url().expect("Missing URI").path().to_string()),
299 tpe: Type::String,
300 },
301 )
302 .expect("path field value is mistyped.");
303
304 uriv.insert_field(
305 "query",
306 TypedValue {
307 value: Value::String(
308 value
309 .url()
310 .expect("Missing URI")
311 .query()
312 .unwrap_or_default()
313 .to_string(),
314 ),
315 tpe: Type::String,
316 },
317 )
318 .expect("query field value is mistyped.");
319
320 reqv.insert_field(
321 "h",
322 TypedValue {
323 value: Value::Struct(hv),
324 tpe: Type::Struct(ht.clone()),
325 },
326 )
327 .expect("h field value is mistyped.");
328
329 reqv.insert_field(
330 "uri",
331 TypedValue {
332 value: Value::Struct(uriv),
333 tpe: Type::Struct(urit.clone()),
334 },
335 )
336 .expect("uri field value is mistyped.");
337
338 reqv.insert_field(
339 "method",
340 TypedValue {
341 value: Value::String(http::method::Method::GET.to_string()),
343 tpe: Type::String,
344 },
345 )
346 .expect("method field value is mistyped.");
347
348 reqv.insert_field(
349 "scheme",
350 TypedValue {
351 value: Value::String(value.url().expect("Missing URI").scheme().to_string()),
352 tpe: Type::String,
353 },
354 )
355 .expect("Header field value is mistyped.");
356
357 value_scope = value_scope.insert(
358 "req",
359 TypedValue {
360 value: Value::Struct(reqv),
361 tpe: Type::Struct(reqt),
362 },
363 );
364
365 value_scope
366 }
367}
368
369pub fn mel_empty_var_value() -> TypedValue {
370 let vart = mel_empty_var_type();
371
372 TypedValue {
373 value: Value::Struct(StructValue {
374 fields: Default::default(),
375 tpe: vart.clone(),
376 }),
377 tpe: Type::Struct(vart),
378 }
379}
380
381pub fn mel_var_value_from_type(tpe: Struct) -> TypedValue {
382 TypedValue {
383 value: Value::Struct(StructValue {
384 fields: Default::default(),
385 tpe: tpe.clone(),
386 }),
387 tpe: Type::Struct(tpe),
388 }
389}