Lev
2 years ago
3 changed files with 100 additions and 1 deletions
@ -0,0 +1,97 @@ |
|||||||
|
use serde::{Deserialize, Serialize}; |
||||||
|
use crate::message::Address; |
||||||
|
|
||||||
|
/// Values used for variables in templates.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] |
||||||
|
pub enum Value { |
||||||
|
Int(i64), |
||||||
|
Bool(bool), |
||||||
|
Address(Address), |
||||||
|
Token(Address), |
||||||
|
Data(Vec<u8>), |
||||||
|
String(String), |
||||||
|
} |
||||||
|
|
||||||
|
/// Types for variable values.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy)] |
||||||
|
pub enum Type { |
||||||
|
Int, |
||||||
|
Bool, |
||||||
|
Address, |
||||||
|
Token, |
||||||
|
Data, |
||||||
|
String, |
||||||
|
} |
||||||
|
|
||||||
|
impl Value { |
||||||
|
/// Returns the type of the value.
|
||||||
|
pub fn var_type(&self) -> Type { |
||||||
|
match self { |
||||||
|
Value::Int(_) => Type::Int, |
||||||
|
Value::Bool(_) => Type::Bool, |
||||||
|
Value::Address(_) => Type::Address, |
||||||
|
Value::Token(_) => Type::Token, |
||||||
|
Value::Data(_) => Type::Data, |
||||||
|
Value::String(_) => Type::String, |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// Matchers of values
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] |
||||||
|
pub enum Matcher { |
||||||
|
Any, |
||||||
|
Fixed(Value), |
||||||
|
NotEqual(Value), |
||||||
|
Whitelist(Vec<Value>), |
||||||
|
Blacklist(Vec<Value>), |
||||||
|
IntRange(i64, i64), |
||||||
|
Regexp(String), |
||||||
|
} |
||||||
|
|
||||||
|
impl Matcher { |
||||||
|
/// Check if this is a valid matcher for a given type.
|
||||||
|
pub fn check_correctness_for_type(&self, type_: Type) -> bool { |
||||||
|
match self { |
||||||
|
Matcher::Any => true, |
||||||
|
Matcher::Fixed(v) => v.var_type() == type_, |
||||||
|
Matcher::NotEqual(v) => v.var_type() == type_, |
||||||
|
Matcher::Whitelist(v) | Matcher::Blacklist(v) => { |
||||||
|
if v.is_empty() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
// Check that all values are of the same type and that there are no duplicates.
|
||||||
|
if v.iter().any(|v| v.var_type() != type_) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
let mut v_clone = v.clone(); |
||||||
|
v_clone.dedup(); |
||||||
|
v_clone.len() == v.len() |
||||||
|
}, |
||||||
|
Matcher::IntRange(i1, i2) => i1 <= i2 && type_ == Type::Int, |
||||||
|
Matcher::Regexp(_) => type_ == Type::String, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// Match a value
|
||||||
|
pub fn match_value(&self, value: &Value) -> bool { |
||||||
|
if !self.check_correctness_for_type(value.var_type()) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
match self { |
||||||
|
Matcher::Any => true, |
||||||
|
Matcher::Fixed(v) => v == value, |
||||||
|
Matcher::NotEqual(v) => v != value, |
||||||
|
Matcher::Whitelist(v) => v.contains(value), |
||||||
|
Matcher::Blacklist(v) => !v.contains(value), |
||||||
|
Matcher::IntRange(i1, i2) => match value { |
||||||
|
Value::Int(i) => i >= i1 && i <= i2, |
||||||
|
_ => false, |
||||||
|
}, |
||||||
|
Matcher::Regexp(_regexp) => match value { |
||||||
|
Value::String(_s) => todo!(), |
||||||
|
_ => false, |
||||||
|
}, |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue