@@ -288,6 +288,9 @@ impl ExprResult {
288288 ExprResult :: Str ( s) => {
289289 * self = ExprResult :: Str ( s. clone ( ) ) ;
290290 }
291+ ExprResult :: Vector ( vv) => {
292+ * self = ExprResult :: StrVector ( vv. iter ( ) . map ( |n| crate :: output:: float_string ( n) ) . collect ( ) ) ;
293+ }
291294 _ => panic ! ( "Unable to join objects others than strings" ) ,
292295 } ,
293296 ExprResult :: StrVector ( v) => match other {
@@ -353,13 +356,36 @@ impl ExprResult {
353356}
354357
355358impl < ' input > Expr < ' input > {
359+ /// Check that all macros exist in the collected results
360+ pub fn validate_macros ( & self , collect : & Vec < SnmpResult > ) -> Result < ( ) , String > {
361+ match self {
362+ Expr :: Id ( key) => {
363+ let k = str:: from_utf8 ( key) . unwrap ( ) ;
364+ for result in collect {
365+ if result. items . contains_key ( k) {
366+ return Ok ( ( ) ) ;
367+ }
368+ }
369+ Err ( format ! ( "Undefined macro in expression: {{{}}}" , k) )
370+ }
371+ Expr :: Number ( _) => Ok ( ( ) ) ,
372+ Expr :: OpPlus ( left, right) | Expr :: OpMinus ( left, right) |
373+ Expr :: OpStar ( left, right) | Expr :: OpSlash ( left, right) => {
374+ left. validate_macros ( collect) ?;
375+ right. validate_macros ( collect) ?;
376+ Ok ( ( ) )
377+ }
378+ Expr :: Fn ( _, expr) => expr. validate_macros ( collect) ,
379+ }
380+ }
381+
356382 /// Recursively evaluates this expression against the collected SNMP results.
357383 ///
358384 /// Resolves identifiers by searching through the `collect` vector, applies
359385 /// operators element-wise for vectors, and evaluates functions.
360- pub fn eval ( & self , collect : & Vec < SnmpResult > ) -> ExprResult {
386+ pub fn eval ( & self , collect : & Vec < SnmpResult > ) -> Result < ExprResult , String > {
361387 match self {
362- Expr :: Number ( n) => ExprResult :: Number ( * n) ,
388+ Expr :: Number ( n) => Ok ( ExprResult :: Number ( * n) ) ,
363389 Expr :: Id ( key) => {
364390 let k = str:: from_utf8 ( key) . unwrap ( ) ;
365391 for result in collect {
@@ -368,28 +394,28 @@ impl<'input> Expr<'input> {
368394 ExprResult :: Vector ( n) => {
369395 if n. len ( ) == 1 {
370396 info ! ( "ID '{}' has value {}" , k, n[ 0 ] ) ;
371- return ExprResult :: Number ( n[ 0 ] ) ;
397+ return Ok ( ExprResult :: Number ( n[ 0 ] ) ) ;
372398 } else {
373399 info ! ( "ID '{}' has value {:?}" , k, n) ;
374- return ExprResult :: Vector ( n. clone ( ) ) ;
400+ return Ok ( ExprResult :: Vector ( n. clone ( ) ) ) ;
375401 }
376402 }
377403 _ => panic ! ( "Should be a number" ) ,
378404 } ,
379405 None => continue ,
380406 }
381407 }
382- ExprResult :: Number ( 0.0 )
408+ Ok ( ExprResult :: Number ( 0.0 ) )
383409 }
384- Expr :: OpPlus ( left, right) => left. eval ( collect) + right. eval ( collect) ,
385- Expr :: OpMinus ( left, right) => left. eval ( collect) - right. eval ( collect) ,
386- Expr :: OpStar ( left, right) => left. eval ( collect) * right. eval ( collect) ,
387- Expr :: OpSlash ( left, right) => left. eval ( collect) / right. eval ( collect) ,
410+ Expr :: OpPlus ( left, right) => Ok ( left. eval ( collect) ? + right. eval ( collect) ? ) ,
411+ Expr :: OpMinus ( left, right) => Ok ( left. eval ( collect) ? - right. eval ( collect) ? ) ,
412+ Expr :: OpStar ( left, right) => Ok ( left. eval ( collect) ? * right. eval ( collect) ? ) ,
413+ Expr :: OpSlash ( left, right) => Ok ( left. eval ( collect) ? / right. eval ( collect) ? ) ,
388414 Expr :: Fn ( func, expr) => {
389- let v = expr. eval ( collect) ;
415+ let v = expr. eval ( collect) ? ;
390416 match func {
391417 Func :: Average => match v {
392- ExprResult :: Number ( n) => ExprResult :: Number ( n) ,
418+ ExprResult :: Number ( n) => Ok ( ExprResult :: Number ( n) ) ,
393419 ExprResult :: Vector ( v) => {
394420 let mut sum = 0.0 ;
395421 let mut count = 0 ;
@@ -400,26 +426,26 @@ impl<'input> Expr<'input> {
400426 }
401427 }
402428 if count > 0 {
403- return ExprResult :: Number ( sum / count as f64 ) ;
429+ Ok ( ExprResult :: Number ( sum / count as f64 ) )
404430 } else {
405- return ExprResult :: Number ( f64:: NAN ) ;
431+ Ok ( ExprResult :: Number ( f64:: NAN ) )
406432 }
407433 }
408434 _ => panic ! ( "Invalid operation" ) ,
409435 } ,
410436 Func :: Min => match v {
411- ExprResult :: Number ( n) => ExprResult :: Number ( n) ,
437+ ExprResult :: Number ( n) => Ok ( ExprResult :: Number ( n) ) ,
412438 ExprResult :: Vector ( v) => {
413439 let min = v. iter ( ) . cloned ( ) . fold ( f64:: INFINITY , f64:: min) ;
414- ExprResult :: Number ( min)
440+ Ok ( ExprResult :: Number ( min) )
415441 }
416442 _ => panic ! ( "Invalid operation" ) ,
417443 } ,
418444 Func :: Max => match v {
419- ExprResult :: Number ( n) => ExprResult :: Number ( n) ,
445+ ExprResult :: Number ( n) => Ok ( ExprResult :: Number ( n) ) ,
420446 ExprResult :: Vector ( v) => {
421447 let max = v. iter ( ) . cloned ( ) . fold ( f64:: NEG_INFINITY , f64:: max) ;
422- ExprResult :: Number ( max)
448+ Ok ( ExprResult :: Number ( max) )
423449 }
424450 _ => panic ! ( "Invalid operation" ) ,
425451 } ,
0 commit comments