mirror of
https://github.com/centreon/centreon-plugins.git
synced 2025-07-31 01:24:35 +02:00
enh(generic-snmp): new ast object
This commit is contained in:
parent
1ecfbb7d11
commit
ef7dffae3d
267
experimental/src/compute/ast.rs
Normal file
267
experimental/src/compute/ast.rs
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
use snmp::{SnmpItem, SnmpResult};
|
||||||
|
use std::str;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Expr<'input> {
|
||||||
|
Id(&'input [u8]),
|
||||||
|
Number(f64),
|
||||||
|
OpPlus(Box<Expr<'input>>, Box<Expr<'input>>),
|
||||||
|
OpMinus(Box<Expr<'input>>, Box<Expr<'input>>),
|
||||||
|
OpStar(Box<Expr<'input>>, Box<Expr<'input>>),
|
||||||
|
OpSlash(Box<Expr<'input>>, Box<Expr<'input>>),
|
||||||
|
Fn(Func, Box<Expr<'input>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Func {
|
||||||
|
Average,
|
||||||
|
Min,
|
||||||
|
Max,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ExprResult {
|
||||||
|
Vector(Vec<f64>),
|
||||||
|
Scalar(f64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Add for ExprResult {
|
||||||
|
type Output = ExprResult;
|
||||||
|
|
||||||
|
fn add(self, other: Self) -> Self::Output {
|
||||||
|
match (self, other) {
|
||||||
|
(ExprResult::Scalar(a), ExprResult::Scalar(b)) => ExprResult::Scalar(a + b),
|
||||||
|
(ExprResult::Vector(a), ExprResult::Vector(b)) => {
|
||||||
|
let len_a = a.len();
|
||||||
|
let len_b = b.len();
|
||||||
|
if len_a == len_b {
|
||||||
|
let mut result = Vec::with_capacity(len_a);
|
||||||
|
for i in 0..len_a {
|
||||||
|
result.push(a[i] + b[i]);
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
} else {
|
||||||
|
if len_a > len_b {
|
||||||
|
let mut result = a.clone();
|
||||||
|
for (idx, value) in b.iter().enumerate() {
|
||||||
|
result[idx] += value;
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
} else {
|
||||||
|
let mut result = b.clone();
|
||||||
|
for (idx, value) in a.iter().enumerate() {
|
||||||
|
result[idx] += value;
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(ExprResult::Scalar(a), ExprResult::Vector(b)) => {
|
||||||
|
let mut result = b.clone();
|
||||||
|
for value in result.iter_mut() {
|
||||||
|
*value += a;
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
}
|
||||||
|
(ExprResult::Vector(a), ExprResult::Scalar(b)) => {
|
||||||
|
let mut result = a.clone();
|
||||||
|
for value in result.iter_mut() {
|
||||||
|
*value += b;
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Sub for ExprResult {
|
||||||
|
type Output = ExprResult;
|
||||||
|
|
||||||
|
fn sub(self, other: Self) -> Self::Output {
|
||||||
|
match (self, other) {
|
||||||
|
(ExprResult::Scalar(a), ExprResult::Scalar(b)) => ExprResult::Scalar(a - b),
|
||||||
|
(ExprResult::Vector(a), ExprResult::Vector(b)) => {
|
||||||
|
let len_a = a.len();
|
||||||
|
let len_b = b.len();
|
||||||
|
if len_a == len_b {
|
||||||
|
let mut result = Vec::with_capacity(len_a);
|
||||||
|
for i in 0..len_a {
|
||||||
|
result.push(a[i] - b[i]);
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
} else {
|
||||||
|
if len_a > len_b {
|
||||||
|
let mut result = a.clone();
|
||||||
|
for (idx, value) in b.iter().enumerate() {
|
||||||
|
result[idx] -= value;
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
} else {
|
||||||
|
let mut result = b.clone();
|
||||||
|
for (idx, value) in a.iter().enumerate() {
|
||||||
|
result[idx] -= value;
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(ExprResult::Scalar(a), ExprResult::Vector(b)) => {
|
||||||
|
let mut result = vec![0_f64; b.len()];
|
||||||
|
for (idx, value) in result.iter_mut().enumerate() {
|
||||||
|
*value = a - b[idx];
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
}
|
||||||
|
(ExprResult::Vector(a), ExprResult::Scalar(b)) => {
|
||||||
|
let mut result = a.clone();
|
||||||
|
for value in result.iter_mut() {
|
||||||
|
*value -= b;
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Mul for ExprResult {
|
||||||
|
type Output = ExprResult;
|
||||||
|
|
||||||
|
fn mul(self, other: Self) -> Self::Output {
|
||||||
|
match (self, other) {
|
||||||
|
(ExprResult::Scalar(a), ExprResult::Scalar(b)) => ExprResult::Scalar(a * b),
|
||||||
|
(ExprResult::Vector(a), ExprResult::Vector(b)) => {
|
||||||
|
let len_a = a.len();
|
||||||
|
let len_b = b.len();
|
||||||
|
if len_a == len_b {
|
||||||
|
let mut result = Vec::with_capacity(len_a);
|
||||||
|
for i in 0..len_a {
|
||||||
|
result.push(a[i] * b[i]);
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
} else {
|
||||||
|
if len_a > len_b {
|
||||||
|
let mut result = a.clone();
|
||||||
|
for (idx, value) in b.iter().enumerate() {
|
||||||
|
result[idx] *= value;
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
} else {
|
||||||
|
let mut result = b.clone();
|
||||||
|
for (idx, value) in a.iter().enumerate() {
|
||||||
|
result[idx] *= value;
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(ExprResult::Scalar(a), ExprResult::Vector(b)) => {
|
||||||
|
let mut result = b.clone();
|
||||||
|
for value in result.iter_mut() {
|
||||||
|
*value *= a;
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
}
|
||||||
|
(ExprResult::Vector(a), ExprResult::Scalar(b)) => {
|
||||||
|
let mut result = a.clone();
|
||||||
|
for value in result.iter_mut() {
|
||||||
|
*value *= b;
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Div for ExprResult {
|
||||||
|
type Output = ExprResult;
|
||||||
|
|
||||||
|
fn div(self, other: Self) -> Self::Output {
|
||||||
|
match (self, other) {
|
||||||
|
(ExprResult::Scalar(a), ExprResult::Scalar(b)) => ExprResult::Scalar(a / b),
|
||||||
|
(ExprResult::Vector(a), ExprResult::Vector(b)) => {
|
||||||
|
let len_a = a.len();
|
||||||
|
let len_b = b.len();
|
||||||
|
if len_a == len_b {
|
||||||
|
let mut result = Vec::with_capacity(len_a);
|
||||||
|
for i in 0..len_a {
|
||||||
|
result.push(a[i] / b[i]);
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
} else {
|
||||||
|
if len_a > len_b {
|
||||||
|
let mut result = a.clone();
|
||||||
|
for (idx, value) in b.iter().enumerate() {
|
||||||
|
result[idx] /= value;
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
} else {
|
||||||
|
let mut result = b.clone();
|
||||||
|
for (idx, value) in a.iter().enumerate() {
|
||||||
|
result[idx] /= value;
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(ExprResult::Scalar(a), ExprResult::Vector(b)) => {
|
||||||
|
let mut result = vec![0_f64; b.len()];
|
||||||
|
for (idx, value) in result.iter_mut().enumerate() {
|
||||||
|
*value = a / b[idx];
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
}
|
||||||
|
(ExprResult::Vector(a), ExprResult::Scalar(b)) => {
|
||||||
|
let mut result = a.clone();
|
||||||
|
for value in result.iter_mut() {
|
||||||
|
*value /= b;
|
||||||
|
}
|
||||||
|
ExprResult::Vector(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'input> Expr<'input> {
|
||||||
|
pub fn eval(&self, collect: &Vec<SnmpResult>) -> ExprResult {
|
||||||
|
match self {
|
||||||
|
Expr::Number(n) => ExprResult::Scalar(*n),
|
||||||
|
Expr::Id(key) => {
|
||||||
|
for result in collect {
|
||||||
|
let k = str::from_utf8(key).unwrap();
|
||||||
|
let item = &result.items[k];
|
||||||
|
match item {
|
||||||
|
SnmpItem::Nbr(n) => {
|
||||||
|
if n.len() == 1 {
|
||||||
|
return ExprResult::Scalar(n[0]);
|
||||||
|
} else {
|
||||||
|
return ExprResult::Vector(n.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("Should be a number"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExprResult::Scalar(0.0)
|
||||||
|
}
|
||||||
|
Expr::OpPlus(left, right) => left.eval(collect) + right.eval(collect),
|
||||||
|
Expr::OpMinus(left, right) => left.eval(collect) - right.eval(collect),
|
||||||
|
Expr::OpStar(left, right) => left.eval(collect) * right.eval(collect),
|
||||||
|
Expr::OpSlash(left, right) => left.eval(collect) / right.eval(collect),
|
||||||
|
Expr::Fn(func, expr) => {
|
||||||
|
let v = expr.eval(collect);
|
||||||
|
match func {
|
||||||
|
Func::Average => v,
|
||||||
|
Func::Min => v,
|
||||||
|
Func::Max => v,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eval_as_str(&self) -> &[u8] {
|
||||||
|
if let Expr::Id(id) = self {
|
||||||
|
return id;
|
||||||
|
} else {
|
||||||
|
return b"Bad value";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,20 +4,23 @@ use std::str;
|
|||||||
pub type Spanned<Tok, Loc, Error> = Result<(Loc, Tok, Loc), Error>;
|
pub type Spanned<Tok, Loc, Error> = Result<(Loc, Tok, Loc), Error>;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Tok {
|
pub enum Tok<'input> {
|
||||||
Num(f32),
|
Num(f64),
|
||||||
Id,
|
Id(&'input [u8]),
|
||||||
OpStar,
|
OpStar,
|
||||||
OpSlash,
|
OpSlash,
|
||||||
OpPlus,
|
OpPlus,
|
||||||
OpMinus,
|
OpMinus,
|
||||||
LParen,
|
LParen,
|
||||||
RParen,
|
RParen,
|
||||||
|
LBrace,
|
||||||
|
RBrace,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum LexicalError {
|
pub enum LexicalError {
|
||||||
NotPossible,
|
NotPossible,
|
||||||
|
UnmatchedBrace,
|
||||||
// Not possible
|
// Not possible
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,8 +38,9 @@ impl<'input> Lexer<'input> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn number(&mut self, start: usize, chars: &[u8]) -> Option<Spanned<Tok, usize, LexicalError>> {
|
fn number(&mut self, start: usize) -> Option<Spanned<Tok<'input>, usize, LexicalError>> {
|
||||||
// Consume digits and decimal points
|
// Consume digits and decimal points
|
||||||
|
let chars = self.chars.as_bytes();
|
||||||
let mut end = start;
|
let mut end = start;
|
||||||
let mut done = false;
|
let mut done = false;
|
||||||
for c in chars[(start + 1)..].iter() {
|
for c in chars[(start + 1)..].iter() {
|
||||||
@ -59,22 +63,19 @@ impl<'input> Lexer<'input> {
|
|||||||
self.offset = end;
|
self.offset = end;
|
||||||
let value = str::from_utf8(&chars[start..end])
|
let value = str::from_utf8(&chars[start..end])
|
||||||
.unwrap_or("Bad value")
|
.unwrap_or("Bad value")
|
||||||
.parse::<f32>()
|
.parse::<f64>()
|
||||||
.unwrap_or(0.0);
|
.unwrap_or(0.0);
|
||||||
Some(Ok((start, Tok::Num(value), end)))
|
Some(Ok((start, Tok::Num(value), end)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn identifier(
|
fn identifier(&mut self, start: usize) -> Option<Spanned<Tok<'input>, usize, LexicalError>> {
|
||||||
&mut self,
|
|
||||||
start: usize,
|
|
||||||
chars: &[u8],
|
|
||||||
) -> Option<Spanned<Tok, usize, LexicalError>> {
|
|
||||||
// Consume identifier
|
// Consume identifier
|
||||||
|
let chars = self.chars.as_bytes();
|
||||||
let mut end = start;
|
let mut end = start;
|
||||||
let mut done = false;
|
let mut done = false;
|
||||||
for c in chars[(start + 1)..].iter() {
|
for c in chars[(start + 1)..].iter() {
|
||||||
end += 1;
|
end += 1;
|
||||||
if !c.is_ascii_alphanumeric() && *c != b'_' {
|
if !c.is_ascii_alphanumeric() && *c != b'_' && *c != b'.' {
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -89,12 +90,12 @@ impl<'input> Lexer<'input> {
|
|||||||
str::from_utf8(&chars[start..end]).unwrap_or("Bad value")
|
str::from_utf8(&chars[start..end]).unwrap_or("Bad value")
|
||||||
);
|
);
|
||||||
self.offset = end;
|
self.offset = end;
|
||||||
Some(Ok((start, Tok::Id, end)))
|
Some(Ok((start, Tok::Id(&chars[start..end]), end)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'input> Iterator for Lexer<'input> {
|
impl<'input> Iterator for Lexer<'input> {
|
||||||
type Item = Spanned<Tok, usize, LexicalError>;
|
type Item = Spanned<Tok<'input>, usize, LexicalError>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
for (i, c) in self.chars.as_bytes().iter().enumerate().skip(self.offset) {
|
for (i, c) in self.chars.as_bytes().iter().enumerate().skip(self.offset) {
|
||||||
@ -124,12 +125,20 @@ impl<'input> Iterator for Lexer<'input> {
|
|||||||
self.offset = i + 1;
|
self.offset = i + 1;
|
||||||
return Some(Ok((i, Tok::RParen, i + 1)));
|
return Some(Ok((i, Tok::RParen, i + 1)));
|
||||||
}
|
}
|
||||||
|
b'{' => {
|
||||||
|
self.offset = i + 1;
|
||||||
|
return Some(Ok((i, Tok::LBrace, i + 1)));
|
||||||
|
}
|
||||||
|
b'}' => {
|
||||||
|
self.offset = i + 1;
|
||||||
|
return Some(Ok((i, Tok::RBrace, i + 1)));
|
||||||
|
}
|
||||||
b'0'..=b'9' => {
|
b'0'..=b'9' => {
|
||||||
// Consume digits and decimal points
|
// Consume digits and decimal points
|
||||||
return self.number(i, &self.chars.as_bytes());
|
return self.number(i);
|
||||||
}
|
}
|
||||||
b'a'..=b'z' | b'A'..=b'Z' | b'_' => {
|
b'a'..=b'z' | b'A'..=b'Z' | b'_' => {
|
||||||
return self.identifier(i, &self.chars.as_bytes());
|
return self.identifier(i);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Unknown character
|
// Unknown character
|
||||||
@ -151,9 +160,9 @@ mod Test {
|
|||||||
fn test_lexer_num_id_num() {
|
fn test_lexer_num_id_num() {
|
||||||
let input = "123 abc 456";
|
let input = "123 abc 456";
|
||||||
let mut lexer = Lexer::new(input);
|
let mut lexer = Lexer::new(input);
|
||||||
assert_eq!(lexer.next(), Some(Ok((0, Tok::Num(123_f32), 3))));
|
assert_eq!(lexer.next(), Some(Ok((0, Tok::Num(123_f64), 3))));
|
||||||
assert_eq!(lexer.next(), Some(Ok((4, Tok::Id, 7))));
|
assert_eq!(lexer.next(), Some(Ok((4, Tok::Id(b"abc"), 7))));
|
||||||
assert_eq!(lexer.next(), Some(Ok((8, Tok::Num(456_f32), 11))));
|
assert_eq!(lexer.next(), Some(Ok((8, Tok::Num(456_f64), 11))));
|
||||||
assert_eq!(lexer.next(), None);
|
assert_eq!(lexer.next(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,20 +170,20 @@ mod Test {
|
|||||||
fn test_lexer_id_num_id() {
|
fn test_lexer_id_num_id() {
|
||||||
let input = "abc 123 def";
|
let input = "abc 123 def";
|
||||||
let mut lexer = Lexer::new(input);
|
let mut lexer = Lexer::new(input);
|
||||||
assert_eq!(lexer.next(), Some(Ok((0, Tok::Id, 3))));
|
assert_eq!(lexer.next(), Some(Ok((0, Tok::Id(b"abc"), 3))));
|
||||||
assert_eq!(lexer.next(), Some(Ok((4, Tok::Num(123_f32), 7))));
|
assert_eq!(lexer.next(), Some(Ok((4, Tok::Num(123_f64), 7))));
|
||||||
assert_eq!(lexer.next(), Some(Ok((8, Tok::Id, 11))));
|
assert_eq!(lexer.next(), Some(Ok((8, Tok::Id(b"def"), 11))));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_lexer_num_op() {
|
fn test_lexer_num_op() {
|
||||||
let input = "1+2*3";
|
let input = "1+2*3";
|
||||||
let mut lexer = Lexer::new(input);
|
let mut lexer = Lexer::new(input);
|
||||||
assert_eq!(lexer.next(), Some(Ok((0, Tok::Num(1_f32), 1))));
|
assert_eq!(lexer.next(), Some(Ok((0, Tok::Num(1_f64), 1))));
|
||||||
assert_eq!(lexer.next(), Some(Ok((1, Tok::OpPlus, 2))));
|
assert_eq!(lexer.next(), Some(Ok((1, Tok::OpPlus, 2))));
|
||||||
assert_eq!(lexer.next(), Some(Ok((2, Tok::Num(2_f32), 3))));
|
assert_eq!(lexer.next(), Some(Ok((2, Tok::Num(2_f64), 3))));
|
||||||
assert_eq!(lexer.next(), Some(Ok((3, Tok::OpStar, 4))));
|
assert_eq!(lexer.next(), Some(Ok((3, Tok::OpStar, 4))));
|
||||||
assert_eq!(lexer.next(), Some(Ok((4, Tok::Num(3_f32), 5))));
|
assert_eq!(lexer.next(), Some(Ok((4, Tok::Num(3_f64), 5))));
|
||||||
assert_eq!(lexer.next(), None);
|
assert_eq!(lexer.next(), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
|
pub mod ast;
|
||||||
pub mod lexer;
|
pub mod lexer;
|
||||||
|
|
||||||
use lalrpop_util::lalrpop_mod;
|
use self::ast::ExprResult;
|
||||||
|
use self::lexer::{LexicalError, Tok};
|
||||||
|
use lalrpop_util::{lalrpop_mod, ParseError};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use snmp::SnmpResult;
|
use snmp::SnmpResult;
|
||||||
|
|
||||||
@ -10,10 +13,10 @@ lalrpop_mod!(grammar);
|
|||||||
pub struct Metric {
|
pub struct Metric {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub prefix: Option<String>,
|
pub prefix: Option<String>,
|
||||||
value: String,
|
pub value: String,
|
||||||
uom: Option<String>,
|
uom: Option<String>,
|
||||||
min: Option<f32>,
|
min: Option<f64>,
|
||||||
max: Option<f32>,
|
max: Option<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
@ -35,8 +38,19 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval(&self, expr: &str) -> f32 {
|
pub fn eval(
|
||||||
2.0_f32
|
&self,
|
||||||
|
expr: &'a str,
|
||||||
|
) -> Result<ExprResult, ParseError<usize, Tok<'a>, LexicalError>> {
|
||||||
|
let lexer = lexer::Lexer::new(expr);
|
||||||
|
let res = self.parser.parse(lexer);
|
||||||
|
match res {
|
||||||
|
Ok(res) => {
|
||||||
|
let res = res.eval(self.collect);
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +62,7 @@ mod Test {
|
|||||||
let lexer = lexer::Lexer::new("123");
|
let lexer = lexer::Lexer::new("123");
|
||||||
let res = grammar::ExprParser::new().parse(lexer);
|
let res = grammar::ExprParser::new().parse(lexer);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap() == 123_f32);
|
assert!(res.unwrap().eval() == 123_f32);
|
||||||
let lexer = lexer::Lexer::new("123");
|
let lexer = lexer::Lexer::new("123");
|
||||||
assert!(grammar::ExprParser::new().parse(lexer).is_ok());
|
assert!(grammar::ExprParser::new().parse(lexer).is_ok());
|
||||||
let lexer = lexer::Lexer::new("(((123))");
|
let lexer = lexer::Lexer::new("(((123))");
|
||||||
@ -61,27 +75,27 @@ mod Test {
|
|||||||
let lexer = lexer::Lexer::new("1 + 2");
|
let lexer = lexer::Lexer::new("1 + 2");
|
||||||
let res = grammar::ExprParser::new().parse(lexer);
|
let res = grammar::ExprParser::new().parse(lexer);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap() == 3_f32);
|
assert!(res.unwrap().eval() == 3_f32);
|
||||||
|
|
||||||
let lexer = lexer::Lexer::new("1 + 2 - 3");
|
let lexer = lexer::Lexer::new("1 + 2 - 3");
|
||||||
let res = grammar::ExprParser::new().parse(lexer);
|
let res = grammar::ExprParser::new().parse(lexer);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap() == 0_f32);
|
assert!(res.unwrap().eval() == 0_f32);
|
||||||
|
|
||||||
let lexer = lexer::Lexer::new("1 - 2 + 3");
|
let lexer = lexer::Lexer::new("1 - 2 + 3");
|
||||||
let res = grammar::ExprParser::new().parse(lexer);
|
let res = grammar::ExprParser::new().parse(lexer);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap() == 2_f32);
|
assert!(res.unwrap().eval() == 2_f32);
|
||||||
|
|
||||||
let lexer = lexer::Lexer::new("1 - (2 + 3)");
|
let lexer = lexer::Lexer::new("1 - (2 + 3)");
|
||||||
let res = grammar::ExprParser::new().parse(lexer);
|
let res = grammar::ExprParser::new().parse(lexer);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap() == -4_f32);
|
assert!(res.unwrap().eval() == -4_f32);
|
||||||
|
|
||||||
let lexer = lexer::Lexer::new("1 - (2 + (3 - (4 + (5 - (6 + 7)))))");
|
let lexer = lexer::Lexer::new("1 - (2 + (3 - (4 + (5 - (6 + 7)))))");
|
||||||
let res = grammar::ExprParser::new().parse(lexer);
|
let res = grammar::ExprParser::new().parse(lexer);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap() == -8_f32);
|
assert!((res.unwrap()).eval() == -8_f32);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -89,27 +103,27 @@ mod Test {
|
|||||||
let lexer = lexer::Lexer::new("2 * 3");
|
let lexer = lexer::Lexer::new("2 * 3");
|
||||||
let res = grammar::ExprParser::new().parse(lexer);
|
let res = grammar::ExprParser::new().parse(lexer);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap() == 6_f32);
|
assert!(res.unwrap().eval() == 6_f32);
|
||||||
|
|
||||||
let lexer = lexer::Lexer::new("1 + 2 * 3");
|
let lexer = lexer::Lexer::new("1 + 2 * 3");
|
||||||
let res = grammar::ExprParser::new().parse(lexer);
|
let res = grammar::ExprParser::new().parse(lexer);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap() == 7_f32);
|
assert!(res.unwrap().eval() == 7_f32);
|
||||||
|
|
||||||
let lexer = lexer::Lexer::new("(1 + 2) * 3");
|
let lexer = lexer::Lexer::new("(1 + 2) * 3");
|
||||||
let res = grammar::ExprParser::new().parse(lexer);
|
let res = grammar::ExprParser::new().parse(lexer);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap() == 9_f32);
|
assert!(res.unwrap().eval() == 9_f32);
|
||||||
|
|
||||||
let lexer = lexer::Lexer::new("2 * 3 * 4");
|
let lexer = lexer::Lexer::new("2 * 3 * 4");
|
||||||
let res = grammar::ExprParser::new().parse(lexer);
|
let res = grammar::ExprParser::new().parse(lexer);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap() == 24_f32);
|
assert!(res.unwrap().eval() == 24_f32);
|
||||||
|
|
||||||
let lexer = lexer::Lexer::new("2 * 3 / 2");
|
let lexer = lexer::Lexer::new("2 * 3 / 2");
|
||||||
let res = grammar::ExprParser::new().parse(lexer);
|
let res = grammar::ExprParser::new().parse(lexer);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap() == 3_f32);
|
assert!(res.unwrap().eval() == 3_f32);
|
||||||
|
|
||||||
// We have an issue with 2/0, I know it but we'll fix it later.
|
// We have an issue with 2/0, I know it but we'll fix it later.
|
||||||
}
|
}
|
||||||
@ -119,7 +133,20 @@ mod Test {
|
|||||||
let lexer = lexer::Lexer::new("1 + (3 + 2 * 3) / 3");
|
let lexer = lexer::Lexer::new("1 + (3 + 2 * 3) / 3");
|
||||||
let res = grammar::ExprParser::new().parse(lexer);
|
let res = grammar::ExprParser::new().parse(lexer);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap() == 4_f32);
|
assert!(res.unwrap().eval() == 4_f32);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn identifier() {
|
||||||
|
let lexer = lexer::Lexer::new("{abc} + 1");
|
||||||
|
let res = grammar::ExprParser::new().parse(lexer);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
println!("{:?}", res);
|
||||||
|
assert!(res.unwrap().eval() == 1_f32);
|
||||||
|
|
||||||
|
let lexer = lexer::Lexer::new("abc + 1");
|
||||||
|
let res = grammar::ExprParser::new().parse(lexer);
|
||||||
|
assert!(res.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -4,7 +4,7 @@ extern crate serde_json;
|
|||||||
use compute::{Compute, Parser};
|
use compute::{Compute, Parser};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use snmp::{snmp_bulk_get, snmp_bulk_walk, snmp_bulk_walk_with_labels};
|
use snmp::{snmp_bulk_get, snmp_bulk_walk, snmp_bulk_walk_with_labels};
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub enum Status {
|
pub enum Status {
|
||||||
@ -56,7 +56,7 @@ pub struct Snmp {
|
|||||||
name: String,
|
name: String,
|
||||||
oid: String,
|
oid: String,
|
||||||
query: QueryType,
|
query: QueryType,
|
||||||
labels: Option<BTreeMap<String, String>>,
|
labels: Option<HashMap<String, String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
@ -82,7 +82,7 @@ pub struct CommandExt {
|
|||||||
pub critical_agregation: Option<String>,
|
pub critical_agregation: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_status(value: f32, warn: &Option<String>, crit: &Option<String>) -> Status {
|
fn compute_status(value: f64, warn: &Option<String>, crit: &Option<String>) -> Status {
|
||||||
if let Some(c) = crit {
|
if let Some(c) = crit {
|
||||||
let crit = c.parse().unwrap();
|
let crit = c.parse().unwrap();
|
||||||
if value > crit {
|
if value > crit {
|
||||||
@ -130,12 +130,20 @@ impl Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let p = Parser::new(&collect);
|
for (i, metric) in self.compute.metrics.iter().enumerate() {
|
||||||
for (idx, metric) in self.compute.metrics.iter().enumerate() {
|
|
||||||
let name = match &metric.prefix {
|
let name = match &metric.prefix {
|
||||||
Some(prefix) => format!("{}#{}", p.eval(prefix), metric.name),
|
Some(prefix) => {
|
||||||
None => format!("{}#{}", idx, metric.name),
|
format!("{:?}#{}", prefix, metric.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
None => format!("{}#{}", i, metric.name),
|
||||||
};
|
};
|
||||||
|
println!("name: {}", name);
|
||||||
|
let value = &metric.value;
|
||||||
|
println!("value: {}", value);
|
||||||
|
let parser = Parser::new(&collect);
|
||||||
|
let value = parser.eval(value).unwrap();
|
||||||
|
println!("value result: {:?}", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !to_get.is_empty() {
|
if !to_get.is_empty() {
|
||||||
|
@ -1,23 +1,24 @@
|
|||||||
use std::str::FromStr;
|
|
||||||
use compute::lexer;
|
use compute::lexer;
|
||||||
|
use compute::ast;
|
||||||
|
|
||||||
grammar;
|
grammar<'input>;
|
||||||
|
|
||||||
pub Expr: f32 = {
|
pub Expr: Box<ast::Expr<'input>> = {
|
||||||
<s:Expr> "+" <p:Product> => s + p,
|
<s:Expr> "+" <p:Product> => Box::new(ast::Expr::OpPlus(<>)),
|
||||||
<s:Expr> "-" <p:Product> => s - p,
|
<s:Expr> "-" <p:Product> => Box::new(ast::Expr::OpMinus(<>)),
|
||||||
<p:Product> => p,
|
Product,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub Product: f32 = {
|
pub Product: Box<ast::Expr<'input>> = {
|
||||||
<s:Product> "*" <v:Term> => s * v,
|
<s:Product> "*" <v:Term> => Box::new(ast::Expr::OpStar(<>)),
|
||||||
<s:Product> "/" <v:Term> => s / v,
|
<s:Product> "/" <v:Term> => Box::new(ast::Expr::OpSlash(<>)),
|
||||||
<v:Term> => v,
|
<v:Term> => <>,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub Term: f32 = {
|
pub Term: Box<ast::Expr<'input>> = {
|
||||||
"num" => <>,
|
"num" => Box::new(ast::Expr::Number(<>)),
|
||||||
"(" <v:Expr> ")" => v,
|
"(" <v:Expr> ")" => <>,
|
||||||
|
"{" <"id"> "}" => Box::new(ast::Expr::Id(<>)),
|
||||||
};
|
};
|
||||||
|
|
||||||
extern {
|
extern {
|
||||||
@ -26,13 +27,16 @@ extern {
|
|||||||
|
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
enum lexer::Tok {
|
enum lexer::Tok<'input> {
|
||||||
"*" => lexer::Tok::OpStar,
|
"*" => lexer::Tok::OpStar,
|
||||||
"/" => lexer::Tok::OpSlash,
|
"/" => lexer::Tok::OpSlash,
|
||||||
"+" => lexer::Tok::OpPlus,
|
"+" => lexer::Tok::OpPlus,
|
||||||
"-" => lexer::Tok::OpMinus,
|
"-" => lexer::Tok::OpMinus,
|
||||||
"(" => lexer::Tok::LParen,
|
"(" => lexer::Tok::LParen,
|
||||||
")" => lexer::Tok::RParen,
|
")" => lexer::Tok::RParen,
|
||||||
"num" => lexer::Tok::Num(<f32>)
|
"{" => lexer::Tok::LBrace,
|
||||||
|
"}" => lexer::Tok::RBrace,
|
||||||
|
"num" => lexer::Tok::Num(<f64>),
|
||||||
|
"id" => lexer::Tok::Id(<&'input [u8]>),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ mod compute;
|
|||||||
mod generic;
|
mod generic;
|
||||||
mod snmp;
|
mod snmp;
|
||||||
|
|
||||||
use generic::{Command, CommandExt};
|
use generic::Command;
|
||||||
use lalrpop_util::lalrpop_mod;
|
use lalrpop_util::lalrpop_mod;
|
||||||
use serde_json::Result;
|
use serde_json::Result;
|
||||||
//use snmp::snmp_get;
|
//use snmp::snmp_get;
|
||||||
|
@ -11,26 +11,26 @@ use rasn_snmp::v2::VarBind;
|
|||||||
use rasn_snmp::v2::VarBindValue;
|
use rasn_snmp::v2::VarBindValue;
|
||||||
use rasn_snmp::v2::{GetBulkRequest, GetNextRequest, GetRequest};
|
use rasn_snmp::v2::{GetBulkRequest, GetNextRequest, GetRequest};
|
||||||
use rasn_snmp::v2c::Message;
|
use rasn_snmp::v2c::Message;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
|
|
||||||
pub enum ValueType {
|
pub enum ValueType {
|
||||||
None(()),
|
None(()),
|
||||||
Integer(i64),
|
Integer(i64),
|
||||||
Float(f32),
|
Float(f64),
|
||||||
String(String),
|
String(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SnmpItem {
|
pub enum SnmpItem {
|
||||||
Nbr(Vec<f32>),
|
Nbr(Vec<f64>),
|
||||||
Str(Vec<String>),
|
Str(Vec<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SnmpResult {
|
pub struct SnmpResult {
|
||||||
items: BTreeMap<String, SnmpItem>,
|
pub items: HashMap<String, SnmpItem>,
|
||||||
last_oid: Vec<u32>,
|
last_oid: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ pub fn snmp_bulk_get<'a>(
|
|||||||
.collect::<Vec<Vec<u32>>>();
|
.collect::<Vec<Vec<u32>>>();
|
||||||
|
|
||||||
let mut retval = SnmpResult {
|
let mut retval = SnmpResult {
|
||||||
items: BTreeMap::new(),
|
items: HashMap::new(),
|
||||||
last_oid: Vec::new(),
|
last_oid: Vec::new(),
|
||||||
};
|
};
|
||||||
let mut request_id: i32 = 1;
|
let mut request_id: i32 = 1;
|
||||||
@ -256,7 +256,7 @@ pub fn snmp_bulk_walk<'a>(
|
|||||||
.collect::<Vec<u32>>();
|
.collect::<Vec<u32>>();
|
||||||
let mut oid_tab = &oid_init;
|
let mut oid_tab = &oid_init;
|
||||||
let mut retval = SnmpResult {
|
let mut retval = SnmpResult {
|
||||||
items: BTreeMap::new(),
|
items: HashMap::new(),
|
||||||
last_oid: Vec::new(),
|
last_oid: Vec::new(),
|
||||||
};
|
};
|
||||||
let request_id: i32 = 1;
|
let request_id: i32 = 1;
|
||||||
@ -314,7 +314,7 @@ pub fn snmp_bulk_walk_with_labels<'a>(
|
|||||||
community: &str,
|
community: &str,
|
||||||
oid: &str,
|
oid: &str,
|
||||||
snmp_name: &str,
|
snmp_name: &str,
|
||||||
labels: &'a BTreeMap<String, String>,
|
labels: &'a HashMap<String, String>,
|
||||||
) -> SnmpResult {
|
) -> SnmpResult {
|
||||||
let oid_init = oid
|
let oid_init = oid
|
||||||
.split('.')
|
.split('.')
|
||||||
@ -323,7 +323,7 @@ pub fn snmp_bulk_walk_with_labels<'a>(
|
|||||||
|
|
||||||
let mut oid_tab = &oid_init;
|
let mut oid_tab = &oid_init;
|
||||||
let mut retval = SnmpResult {
|
let mut retval = SnmpResult {
|
||||||
items: BTreeMap::new(),
|
items: HashMap::new(),
|
||||||
last_oid: Vec::new(),
|
last_oid: Vec::new(),
|
||||||
};
|
};
|
||||||
let request_id: i32 = 1;
|
let request_id: i32 = 1;
|
||||||
@ -380,7 +380,7 @@ impl SnmpResult {
|
|||||||
decoded: Message<Pdus>,
|
decoded: Message<Pdus>,
|
||||||
oid: &str,
|
oid: &str,
|
||||||
snmp_name: &str,
|
snmp_name: &str,
|
||||||
labels: &'a BTreeMap<String, String>,
|
labels: &'a HashMap<String, String>,
|
||||||
walk: bool,
|
walk: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut completed = false;
|
let mut completed = false;
|
||||||
@ -461,7 +461,7 @@ impl SnmpResult {
|
|||||||
ValueType::String(_) => {
|
ValueType::String(_) => {
|
||||||
panic!("Value should be a float");
|
panic!("Value should be a float");
|
||||||
}
|
}
|
||||||
ValueType::Integer(i) => *i as f32,
|
ValueType::Integer(i) => *i as f64,
|
||||||
}),
|
}),
|
||||||
SnmpItem::Str(v) => v.push(match &typ {
|
SnmpItem::Str(v) => v.push(match &typ {
|
||||||
ValueType::Float(_) => {
|
ValueType::Float(_) => {
|
||||||
@ -482,7 +482,7 @@ impl SnmpResult {
|
|||||||
panic!("Should not arrive");
|
panic!("Should not arrive");
|
||||||
}
|
}
|
||||||
ValueType::String(s) => SnmpItem::Str(vec![s]),
|
ValueType::String(s) => SnmpItem::Str(vec![s]),
|
||||||
ValueType::Integer(i) => SnmpItem::Nbr(vec![i as f32]),
|
ValueType::Integer(i) => SnmpItem::Nbr(vec![i as f64]),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -572,7 +572,7 @@ impl SnmpResult {
|
|||||||
ValueType::String(_) => {
|
ValueType::String(_) => {
|
||||||
panic!("Value should be a float");
|
panic!("Value should be a float");
|
||||||
}
|
}
|
||||||
ValueType::Integer(i) => *i as f32,
|
ValueType::Integer(i) => *i as f64,
|
||||||
}),
|
}),
|
||||||
SnmpItem::Str(v) => v.push(match &typ {
|
SnmpItem::Str(v) => v.push(match &typ {
|
||||||
ValueType::Float(_) => {
|
ValueType::Float(_) => {
|
||||||
@ -593,7 +593,7 @@ impl SnmpResult {
|
|||||||
panic!("Should not arrive");
|
panic!("Should not arrive");
|
||||||
}
|
}
|
||||||
ValueType::String(s) => SnmpItem::Str(vec![s]),
|
ValueType::String(s) => SnmpItem::Str(vec![s]),
|
||||||
ValueType::Integer(i) => SnmpItem::Nbr(vec![i as f32]),
|
ValueType::Integer(i) => SnmpItem::Nbr(vec![i as f64]),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -714,7 +714,7 @@ impl SnmpResult {
|
|||||||
ValueType::String(_) => {
|
ValueType::String(_) => {
|
||||||
panic!("Value should be a float");
|
panic!("Value should be a float");
|
||||||
}
|
}
|
||||||
ValueType::Integer(i) => *i as f32,
|
ValueType::Integer(i) => *i as f64,
|
||||||
}),
|
}),
|
||||||
SnmpItem::Str(v) => v.push(match &typ {
|
SnmpItem::Str(v) => v.push(match &typ {
|
||||||
ValueType::Float(_) => {
|
ValueType::Float(_) => {
|
||||||
@ -735,7 +735,7 @@ impl SnmpResult {
|
|||||||
panic!("Should not arrive");
|
panic!("Should not arrive");
|
||||||
}
|
}
|
||||||
ValueType::String(s) => SnmpItem::Str(vec![s]),
|
ValueType::String(s) => SnmpItem::Str(vec![s]),
|
||||||
ValueType::Integer(i) => SnmpItem::Nbr(vec![i as f32]),
|
ValueType::Integer(i) => SnmpItem::Nbr(vec![i as f64]),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user