1use std::{
21 collections::HashMap,
22 fmt::{Debug, Display},
23};
24
25use brooks_macros::builtin_function;
26use regex::Regex;
27
28use crate::{
29 environment::scope::Scope,
30 mel::{MEL_USER_SET_VARIABLE_STRUCT_NAME, interpreter::interpret::BuiltinFunction},
31 prr::Prr,
32};
33
34#[derive(Debug, Clone, Default)]
37pub struct Struct {
38 pub name: String,
39 fields: HashMap<String, Type>,
40 wild: Vec<(Regex, Type)>,
41}
42
43impl PartialEq for Struct {
44 fn eq(&self, other: &Self) -> bool {
45 self.name == other.name
46 }
47}
48
49impl Struct {
50 pub fn new(name: &str) -> Struct {
51 Struct {
52 name: name.to_string(),
53 fields: HashMap::new(),
54 wild: vec![],
55 }
56 }
57
58 pub fn insert_field(&mut self, name: &str, tipe: Type) {
59 self.fields.insert(name.to_string(), tipe);
60 }
61
62 pub fn insert_wild_field(&mut self, matcher: &Regex, tipe: Type) {
63 self.wild.push((matcher.clone(), tipe));
64 }
65
66 pub fn get_field(&self, name: &str) -> Option<Type> {
67 if let Some(exact_field) = self.fields.get(name) {
68 Some(exact_field.clone())
69 } else {
70 self.wild.iter().find_map(|(regex, tpe)| {
71 if regex.is_match(name) {
72 Some(tpe.clone())
73 } else {
74 None
75 }
76 })
77 }
78 }
79
80 pub fn fields(&self) -> impl Iterator<Item = (Option<&String>, Option<&Regex>)> {
81 self.fields
82 .keys()
83 .map(|f| (Some(f), None))
84 .chain(self.wild.iter().map(|f| (None, Some(&f.0))))
85 }
86}
87
88#[derive(Debug, Clone, Default, PartialEq)]
89pub struct ArgumentTypeList {
90 pub args: Vec<Type>,
91}
92
93#[derive(Debug, Clone, Default, PartialEq)]
94pub struct ParameterTypesList {
95 pub params: Vec<Type>,
96}
97
98#[derive(Default, Debug, Clone)]
99pub enum Type {
100 Boolean,
101 Integer,
102 Unsigned,
103 Real,
104 String,
105 Regex,
106 IPAddress,
107 Params(ParameterTypesList),
108 Function(String, ReturnTypeCalculator, ParamsTypeCheckerGenerator),
109 Struct(Struct),
110 #[default]
111 Nil,
112}
113
114impl PartialEq for Type {
115 fn eq(&self, other: &Self) -> bool {
116 match (self, other) {
117 (Self::Params(left), Self::Params(right)) => left == right,
118 (Self::Function(name, _, _), Self::Function(other_name, _, _)) => name == other_name,
119 (Self::Struct(left), Self::Struct(right)) => left == right,
120 _ => core::mem::discriminant(self) == core::mem::discriminant(other),
121 }
122 }
123}
124
125impl Display for Struct {
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 write!(
128 f,
129 "Name: {}, Fields: {}",
130 self.name,
131 self.fields.keys().cloned().collect::<Vec<_>>().join(","),
132 )
133 }
134}
135
136impl Display for Type {
137 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138 match self {
139 Type::Unsigned => write!(f, "Unsigned"),
140 Type::Boolean => write!(f, "Bool"),
141 Type::Integer => write!(f, "Integer"),
142 Type::Real => write!(f, "Real"),
143 Type::String => write!(f, "String"),
144 Type::Regex => write!(f, "Regex"),
145 Type::IPAddress => write!(f, "IPAddress"),
146 Type::Params(items) => write!(
147 f,
148 "Parameters: {}",
149 items
150 .params
151 .iter()
152 .map(|c| c.to_string())
153 .collect::<Vec<_>>()
154 .join(","),
155 ),
156 Type::Function(name, rtg, ptcg) => {
157 let rt = rtg();
158 let ptc = ptcg();
159 write!(f, "Name: {name} Return Type: {rt}, Parameter Types: {ptc}")
160 }
161 Type::Struct(s) => write!(f, "Struct: {s}"),
162 Type::Nil => write!(f, "Nil"),
163 }
164 }
165}
166
167impl Struct {
168 pub fn type_for_field(&self, field_name: &str) -> Option<Type> {
169 self.fields.get(field_name).cloned()
170 }
171}
172
173pub struct SimpleParamTypeChecker {
176 pub p: ParameterTypesList,
177}
178
179impl ParamsTypeChecker for SimpleParamTypeChecker {
180 fn check(&self, a: ArgumentTypeList) -> Result<(), ParamsTypeCheckerError> {
181 if self.p.params.len() != a.args.len() {
182 return Err(ParamsTypeCheckerError::Miscount(
183 self.p.params.len(),
184 a.args.len(),
185 ));
186 }
187
188 for (p, a) in self.p.params.iter().zip(&a.args) {
189 if *p != *a {
190 return Err(ParamsTypeCheckerError::Mismatch(p.clone(), a.clone()));
191 }
192 }
193
194 Ok(())
195 }
196}
197
198impl Display for SimpleParamTypeChecker {
199 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200 write!(
201 f,
202 "{}",
203 self.p
204 .params
205 .iter()
206 .map(|a| a.to_string())
207 .collect::<Vec<_>>()
208 .join(",")
209 )
210 }
211}
212
213pub struct TypelessParamTypeChecker {
216 pub count: usize,
217}
218
219impl ParamsTypeChecker for TypelessParamTypeChecker {
220 fn check(&self, a: ArgumentTypeList) -> Result<(), ParamsTypeCheckerError> {
221 if self.count != a.args.len() {
222 return Err(ParamsTypeCheckerError::Miscount(self.count, a.args.len()));
223 }
224
225 Ok(())
226 }
227}
228
229impl Display for TypelessParamTypeChecker {
230 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
231 write!(f, "{}", ["Any"].repeat(self.count).join(","))
232 }
233}
234
235pub type ReturnTypeCalculator = fn() -> Type;
239
240#[derive(Debug, Clone)]
243pub enum ParamsTypeCheckerError {
244 Miscount(usize, usize),
245 Mismatch(Type, Type),
246}
247
248#[allow(clippy::result_large_err)]
249pub trait ParamsTypeChecker: Display {
250 fn check(&self, args: ArgumentTypeList) -> Result<(), ParamsTypeCheckerError>;
251}
252
253pub type ParamsTypeCheckerGenerator = fn() -> Box<dyn ParamsTypeChecker>;
255
256pub trait BuiltinFunctionType: Debug {
258 fn name(&self) -> String;
259 fn params_type_checker(&self) -> ParamsTypeCheckerGenerator;
260 fn return_type_calculator(&self) -> ReturnTypeCalculator;
261}
262
263#[allow(non_camel_case_types)]
264#[derive(Clone, Default, Debug)]
265#[builtin_function(Type::String, Type::String, Type::Integer)]
266pub struct Path_ElementBuiltin {}
267
268#[allow(non_camel_case_types)]
269#[derive(Clone, Default, Debug)]
270#[builtin_function(Type::String, Type::String, Type::Integer, Type::Integer)]
271pub struct Path_ElementsBuiltin {}
272
273#[allow(non_camel_case_types)]
274#[derive(Clone, Default, Debug)]
275#[builtin_function(Type::String, Type::String, Type::String)]
276pub struct MatchBuiltin {}
277
278#[allow(non_camel_case_types)]
279#[derive(Clone, Default, Debug)]
280#[builtin_function(Type::String, Type::String, Type::String, Type::String)]
281pub struct Match_ReplaceBuiltin {}
282
283#[allow(non_camel_case_types)]
284#[derive(Clone, Default, Debug)]
285#[builtin_function(Type::String, Type::String, Type::String, Type::String)]
286pub struct Add_QueryBuiltin {}
287
288#[allow(non_camel_case_types)]
289#[derive(Clone, Default, Debug)]
290#[builtin_function(Type::String, Type::String, Type::String)]
291pub struct Add_Query_MultiBuiltin {}
292
293#[allow(non_camel_case_types)]
294#[derive(Clone, Default, Debug)]
295#[builtin_function(Type::String, Type::String, Type::String)]
296pub struct Remove_QueryBuiltin {}
297
298#[allow(non_camel_case_types)]
299#[derive(Clone, Default, Debug)]
300#[builtin_function(Type::String, Type::String, Type::String)]
301pub struct Remove_Query_MultiBuiltin {}
302
303#[allow(non_camel_case_types)]
304#[derive(Clone, Default, Debug)]
305#[builtin_function(Type::String, Type::String, Type::String)]
306pub struct Keep_Query_MultiBuiltin {}
307
308#[allow(non_camel_case_types)]
309#[derive(Clone, Default, Debug)]
310#[builtin_function(Type::String, Type::String)]
311pub struct LowerBuiltin {}
312
313#[allow(non_camel_case_types)]
314#[derive(Clone, Default, Debug)]
315#[builtin_function(Type::String, Type::String)]
316pub struct UpperBuiltin {}
317
318#[derive(Clone, Default, Debug)]
319pub struct BooleanBuiltin {}
320impl BuiltinFunction for BooleanBuiltin {}
321impl BuiltinFunctionType for BooleanBuiltin {
322 fn name(&self) -> String {
323 "boolean".to_string()
324 }
325
326 fn params_type_checker(&self) -> ParamsTypeCheckerGenerator {
327 || Box::new(TypelessParamTypeChecker { count: 1 })
328 }
329
330 fn return_type_calculator(&self) -> ReturnTypeCalculator {
331 || Type::Boolean
332 }
333}
334
335#[derive(Clone, Default, Debug)]
336pub struct IntegerBuiltin {}
337impl BuiltinFunction for IntegerBuiltin {}
338impl BuiltinFunctionType for IntegerBuiltin {
339 fn name(&self) -> String {
340 "integer".to_string()
341 }
342
343 fn params_type_checker(&self) -> ParamsTypeCheckerGenerator {
344 || Box::new(TypelessParamTypeChecker { count: 1 })
345 }
346
347 fn return_type_calculator(&self) -> ReturnTypeCalculator {
348 || Type::Integer
349 }
350}
351
352#[derive(Clone, Default, Debug)]
353pub struct UnsignedBuiltin {}
354impl BuiltinFunction for UnsignedBuiltin {}
355impl BuiltinFunctionType for UnsignedBuiltin {
356 fn name(&self) -> String {
357 "unsigned".to_string()
358 }
359
360 fn params_type_checker(&self) -> ParamsTypeCheckerGenerator {
361 || Box::new(TypelessParamTypeChecker { count: 1 })
362 }
363
364 fn return_type_calculator(&self) -> ReturnTypeCalculator {
365 || Type::Unsigned
366 }
367}
368
369#[derive(Clone, Default, Debug)]
370pub struct RealBuiltin {}
371impl BuiltinFunction for RealBuiltin {}
372impl BuiltinFunctionType for RealBuiltin {
373 fn name(&self) -> String {
374 "real".to_string()
375 }
376
377 fn params_type_checker(&self) -> ParamsTypeCheckerGenerator {
378 || Box::new(TypelessParamTypeChecker { count: 1 })
379 }
380
381 fn return_type_calculator(&self) -> ReturnTypeCalculator {
382 || Type::Real
383 }
384}
385
386#[derive(Clone, Default, Debug)]
387pub struct StringBuiltin {}
388impl BuiltinFunction for StringBuiltin {}
389impl BuiltinFunctionType for StringBuiltin {
390 fn name(&self) -> String {
391 "string".to_string()
392 }
393
394 fn params_type_checker(&self) -> ParamsTypeCheckerGenerator {
395 || Box::new(TypelessParamTypeChecker { count: 1 })
396 }
397
398 fn return_type_calculator(&self) -> ReturnTypeCalculator {
399 || Type::String
400 }
401}
402
403pub fn mel_empty_header_type(wild: bool) -> Struct {
406 let mut ht = Struct::new("h");
407 if wild {
408 ht.insert_wild_field(
409 &Regex::new(".*").expect("Could not compile wildcard regex for header type"),
410 Type::String,
411 );
412 }
413
414 ht
415}
416
417pub fn mel_header_type_from_req<A>(value: &http::Request<A>) -> Struct {
418 let mut ht = Struct::new("h");
420 value.headers().iter().for_each(|header| {
421 ht.insert_field(
422 &header.0.to_string().replace("-", "_").to_lowercase(),
423 Type::String,
424 );
425 });
426 ht
427}
428
429pub fn mel_uri_type() -> Struct {
430 let mut urit = Struct::new("uri");
432 urit.insert_field("path", Type::String);
433 urit.insert_field("query", Type::String);
434
435 urit
436}
437
438pub fn mel_req_type(header_type: Struct, uri_type: Struct) -> Struct {
439 let mut reqs = Struct::new("req");
441 reqs.insert_field("h", Type::Struct(header_type));
442 reqs.insert_field("uri", Type::Struct(uri_type));
443 reqs.insert_field("method", Type::String);
444 reqs.insert_field("scheme", Type::String);
445 reqs.insert_field("clientip", Type::IPAddress);
446 reqs.insert_field("clientport", Type::Integer);
447
448 reqs
449}
450
451pub fn mel_empty_var_type() -> Struct {
452 Struct::new(MEL_USER_SET_VARIABLE_STRUCT_NAME)
453}
454
455pub(crate) fn mel_header_type_from_processable_rr<A>(value: &dyn Prr<A>) -> Struct {
456 let mut ht = Struct::new("h");
458 value.headers().iter().for_each(|header| {
459 ht.insert_field(
460 &header.0.to_string().replace("-", "_").to_lowercase(),
461 Type::String,
462 );
463 });
464 ht
465}
466
467pub fn minimal_core_variable_types() -> Scope<Type> {
469 let mut scope = Scope::<Type>::default();
470 let ht = mel_empty_header_type(true);
471 let vart = mel_empty_var_type();
472 scope = scope.insert("req", Type::Struct(mel_req_type(ht, mel_uri_type())));
473 scope = scope.insert(MEL_USER_SET_VARIABLE_STRUCT_NAME, Type::Struct(vart));
474 scope
475}
476
477macro_rules! add_builtin_function_type_to_scope {
478 ($scope:ident, $builtin:ident) => {
479 $scope.insert(
480 &$builtin.name(),
481 Type::Function(
482 $builtin.name(),
483 $builtin.return_type_calculator(),
484 $builtin.params_type_checker(),
485 ),
486 )
487 };
488}
489
490pub fn builtin_function_types() -> Scope<Type> {
492 let path_element = Path_ElementBuiltin {};
493 let path_elements = Path_ElementsBuiltin {};
494 let mtch = MatchBuiltin {};
495 let match_replace = Match_ReplaceBuiltin {};
496 let add_query = Add_QueryBuiltin {};
497 let add_query_multi = Add_Query_MultiBuiltin {};
498 let remove_query = Remove_QueryBuiltin {};
499 let remove_query_multi = Remove_Query_MultiBuiltin {};
500 let keep_query_multi = Keep_Query_MultiBuiltin {};
501 let lower = LowerBuiltin {};
502 let upper = UpperBuiltin {};
503
504 let boolean = BooleanBuiltin {};
506 let integer = IntegerBuiltin {};
507 let unsigned = UnsignedBuiltin {};
508 let string = StringBuiltin {};
509 let real = RealBuiltin {};
510
511 let mut scopes = Scope::<Type>::default();
512 scopes = add_builtin_function_type_to_scope!(scopes, path_element);
513 scopes = add_builtin_function_type_to_scope!(scopes, path_elements);
514 scopes = add_builtin_function_type_to_scope!(scopes, mtch);
515 scopes = add_builtin_function_type_to_scope!(scopes, match_replace);
516 scopes = add_builtin_function_type_to_scope!(scopes, add_query);
517 scopes = add_builtin_function_type_to_scope!(scopes, add_query_multi);
518 scopes = add_builtin_function_type_to_scope!(scopes, remove_query);
519 scopes = add_builtin_function_type_to_scope!(scopes, remove_query_multi);
520 scopes = add_builtin_function_type_to_scope!(scopes, keep_query_multi);
521 scopes = add_builtin_function_type_to_scope!(scopes, lower);
522 scopes = add_builtin_function_type_to_scope!(scopes, upper);
523
524 scopes = add_builtin_function_type_to_scope!(scopes, boolean);
525 scopes = add_builtin_function_type_to_scope!(scopes, integer);
526 scopes = add_builtin_function_type_to_scope!(scopes, real);
527 scopes = add_builtin_function_type_to_scope!(scopes, string);
528 scopes = add_builtin_function_type_to_scope!(scopes, unsigned);
529 scopes
530}
531
532impl<A> From<http::Request<A>> for Scope<Type> {
534 fn from(value: http::Request<A>) -> Self {
535 let mut scope = Scope::<Type>::default();
537
538 let ht = mel_header_type_from_req(&value);
539 let urit = mel_uri_type();
540 let reqs = mel_req_type(ht, urit);
541
542 scope = scope.insert("req", Type::Struct(reqs));
544
545 scope
546 }
547}
548
549#[cfg(test)]
550mod test_struct {
551 use regex::Regex;
552
553 use crate::mel::types::{Struct, Type};
554
555 #[test]
556 fn test_wild_struct_field() {
557 let mut s = Struct::new("s");
558
559 s.insert_field("testing", Type::String);
560 s.insert_wild_field(
561 &Regex::new("w.*").expect("Could not compile testing regex"),
562 Type::Integer,
563 );
564
565 let found = s
566 .get_field("testing")
567 .expect("Could not find testing field");
568 assert_eq!(found, Type::String);
569
570 let found = s.get_field("wild").expect("Could not find wild field");
571 assert_eq!(found, Type::Integer);
572 }
573}